@knpkv/jira-cli 1.5.0 → 1.6.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,31 @@
1
1
  # @knpkv/jira-cli
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#479](https://github.com/knpkv/npm/pull/479) [`1ef1847`](https://github.com/knpkv/npm/commit/1ef1847c867f83de237dec1c454b6bb5e40183ef) Thanks [@konopkov](https://github.com/konopkov)! - One error report for every Atlassian CLI (`jira`, `confluence`, `atlassian`), from the new `@knpkv/atlassian-common/cli` subpath (`handleCliError`, `withCliErrorHandling`, `Verbose`, `commandArgs`, `verboseRequested`).
8
+
9
+ - A failed command prints the error's message; a defect prints `Error: <message>`. The full cause, with stack traces, prints only with the new global `--verbose` flag or `DEBUG=1`.
10
+ - jira: stderr no longer prints the pretty-printed cause and stack trace by default.
11
+ - atlassian: tagged errors print their message instead of `String(error)`, and defects are reported too.
12
+ - Help and usage errors that the CLI already rendered are not printed a second time. Exit codes are unchanged.
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies [[`1ef1847`](https://github.com/knpkv/npm/commit/1ef1847c867f83de237dec1c454b6bb5e40183ef)]:
17
+ - @knpkv/atlassian-common@1.9.0
18
+
19
+ ## 1.5.1
20
+
21
+ ### Patch Changes
22
+
23
+ - [#477](https://github.com/knpkv/npm/pull/477) [`b4a69a0`](https://github.com/knpkv/npm/commit/b4a69a056ce3e2575df70d7aaea1a202f49b6a56) Thanks [@konopkov](https://github.com/konopkov)! - `JiraAuthService` and `ConfluenceAuthService` are now derived from atlassian-common's `AtlassianCliAuth` instead of re-spelling it, and `LoginOptions` / `AccessibleSite` are re-exported from there. The types are unchanged: a type-equality check against the previous hand-written interfaces passed before the switch. `ConfluenceAuthService` keeps its one real difference, a string access token and no `getSiteUrl`.
24
+
25
+ - [#475](https://github.com/knpkv/npm/pull/475) [`08c62b7`](https://github.com/knpkv/npm/commit/08c62b787c649d8f78753515be6faf317791d62b) Thanks [@konopkov](https://github.com/konopkov)! - `auth use <profile>` and `auth remove <profile>` now fail with a typed `ProfileNotFoundError` (exported from `@knpkv/atlassian-common/cli-auth`) and exit non-zero when no stored profile matches. The failure names the profile (`Profile not found: <profile>`, on stderr through each CLI's error handler); previously the line went to stdout and the command exited 0, so a script could not tell a typo from a switch.
26
+ - Updated dependencies [[`08c62b7`](https://github.com/knpkv/npm/commit/08c62b787c649d8f78753515be6faf317791d62b)]:
27
+ - @knpkv/atlassian-common@1.8.0
28
+
3
29
  ## 1.5.0
4
30
 
5
31
  ### Minor Changes
package/README.md CHANGED
@@ -299,3 +299,11 @@ const direct = Effect.gen(function* () {
299
299
  ## License
300
300
 
301
301
  MIT
302
+
303
+ ## Troubleshooting
304
+
305
+ A failed command prints the error message. Add `--verbose` (or set `DEBUG=1`) to print the full cause with stack traces:
306
+
307
+ ```bash
308
+ jira --verbose auth status
309
+ ```
@@ -16,66 +16,18 @@
16
16
  *
17
17
  * @module
18
18
  */
19
- import type { OAuthError } from "@knpkv/atlassian-common/auth";
20
- import { type AtlassianCliDescriptor } from "@knpkv/atlassian-common/cli-auth";
21
- import type { AuthProfile, FileSystemError, HomeDirectoryError, OAuthConfig, OAuthUser } from "@knpkv/atlassian-common/config";
19
+ import { type AtlassianCliAuth, type AtlassianCliDescriptor } from "@knpkv/atlassian-common/cli-auth";
22
20
  import * as Context from "effect/Context";
23
- import type * as Effect from "effect/Effect";
24
21
  import * as Layer from "effect/Layer";
25
- import type * as PlatformError from "effect/PlatformError";
26
- import type * as Redacted from "effect/Redacted";
27
22
  import type { AuthMissingError } from "./JiraCliError.js";
23
+ export type { AccessibleSite, LoginOptions } from "@knpkv/atlassian-common/cli-auth";
28
24
  /**
29
- * Options for the login method.
30
- *
31
- * @category Types
32
- */
33
- export interface LoginOptions {
34
- /** Site URL to select (for accounts with multiple sites) */
35
- readonly siteUrl?: string;
36
- }
37
- /**
38
- * Information about an accessible Jira site.
39
- *
40
- * @category Types
41
- */
42
- export interface AccessibleSite {
43
- readonly id: string;
44
- readonly name: string;
45
- readonly url: string;
46
- }
47
- /**
48
- * JiraAuth service interface.
25
+ * JiraAuth service interface: the shared Atlassian CLI auth, failing with Jira's own
26
+ * {@link AuthMissingError} when nobody is logged in.
49
27
  *
50
28
  * @category Services
51
29
  */
52
- export interface JiraAuthService {
53
- /** Configure OAuth client credentials */
54
- readonly configure: (config: OAuthConfig) => Effect.Effect<void, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
55
- /** Check if OAuth is configured */
56
- readonly isConfigured: () => Effect.Effect<boolean, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
57
- /** Start OAuth login flow. Returns list of sites if multiple are available. */
58
- readonly login: (options?: LoginOptions) => Effect.Effect<ReadonlyArray<AccessibleSite> | void, OAuthError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
59
- /** Remove stored authentication */
60
- readonly logout: () => Effect.Effect<void, OAuthError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
61
- /** Get access token, refreshing if needed */
62
- readonly getAccessToken: () => Effect.Effect<Redacted.Redacted<string>, AuthMissingError | OAuthError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
63
- /** Get cloud ID from stored token */
64
- readonly getCloudId: () => Effect.Effect<string, AuthMissingError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
65
- /** Get site URL from stored token */
66
- readonly getSiteUrl: () => Effect.Effect<string, AuthMissingError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
67
- /** Get current user info from stored token */
68
- readonly getCurrentUser: () => Effect.Effect<OAuthUser | null, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
69
- /** Get active auth profile */
70
- readonly getActiveProfile: () => Effect.Effect<AuthProfile | null, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
71
- /** List stored auth profiles */
72
- readonly listProfiles: () => Effect.Effect<ReadonlyArray<AuthProfile>, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
73
- /** Switch active profile by ID, name, site URL, cloud ID, or account ID */
74
- readonly switchProfile: (selector: string) => Effect.Effect<AuthProfile | null, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
75
- /** Remove stored profile by ID, name, site URL, cloud ID, or account ID */
76
- readonly removeProfile: (selector: string) => Effect.Effect<AuthProfile | null, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
77
- /** Check if user is logged in */
78
- readonly isLoggedIn: () => Effect.Effect<boolean, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>;
30
+ export interface JiraAuthService extends AtlassianCliAuth<AuthMissingError> {
79
31
  }
80
32
  declare const JiraAuth_base: Context.ServiceClass<JiraAuth, "@knpkv/jira-cli/JiraAuth", JiraAuthService>;
81
33
  /**
@@ -107,5 +59,4 @@ export declare const jiraCliDescriptor: AtlassianCliDescriptor;
107
59
  * @category Layers
108
60
  */
109
61
  export declare const layer: Layer.Layer<JiraAuth, never, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/Crypto").Crypto | import("effect/http/HttpClient").HttpClient>;
110
- export {};
111
62
  //# sourceMappingURL=JiraAuth.d.ts.map
@@ -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,EACL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAG5B,MAAM,kCAAkC,CAAA;AACzC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAqBzD,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAEpF;;;;;GAKG;AACH,MAAM,WAAW,eAAgB,SAAQ,gBAAgB,CAAC,gBAAgB,CAAC;CAAG;;AAE9E;;;;;;;;;;;;;;;;;;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
@@ -1,3 +1,21 @@
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
+ * `ChildProcessSpawner` and `Crypto`. The flow — refresh lock, rotating-token persistence,
8
+ * browser login, profiles — is `@knpkv/atlassian-common/cli-auth`'s, bound to the
9
+ * `"jira-cli"` storage namespace, Jira's scopes and Jira's names.
10
+ *
11
+ * **Common tasks**
12
+ *
13
+ * - Get a valid access token: `auth.getAccessToken()` (auto-refreshes if expired)
14
+ * - Full login flow: `auth.login()`
15
+ * - Check auth state: `auth.isLoggedIn()`
16
+ *
17
+ * @module
18
+ */
1
19
  import { makeAtlassianCliAuth, NodeCliAuthLive } from "@knpkv/atlassian-common/cli-auth";
2
20
  import * as Context from "effect/Context";
3
21
  import * as Layer from "effect/Layer";
@@ -1 +1 @@
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
+ {"version":3,"file":"JiraAuth.js","sourceRoot":"","sources":["../src/JiraAuth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAGL,oBAAoB,EACpB,eAAe,EAChB,MAAM,kCAAkC,CAAA;AACzC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,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;AAYD;;;;;;;;;;;;;;;;;;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"}
package/dist/bin.js CHANGED
@@ -8,12 +8,13 @@
8
8
  */
9
9
  import { NodeRuntime, NodeStdio } from "@effect/platform-node";
10
10
  import { makeInstallCommand } from "@knpkv/agent-skills";
11
+ import { commandArgs, Verbose, withCliErrorHandling } from "@knpkv/atlassian-common/cli";
11
12
  import { Command } from "effect/cli";
12
13
  import * as Console from "effect/Console";
13
14
  import * as Effect from "effect/Effect";
14
15
  import * as Stdio from "effect/Stdio";
15
16
  import pkg from "../package.json" with { type: "json" };
16
- import { AppLayer, authCommand, AuthOnlyLayer, getLayerType, handleError, issueCommand, MinimalLayer, versionCommand } from "./commands/index.js";
17
+ import { AppLayer, authCommand, AuthOnlyLayer, getLayerType, issueCommand, MinimalLayer, versionCommand } from "./commands/index.js";
17
18
  const skillsInstall = makeInstallCommand({
18
19
  description: "Install the Jira agent skill",
19
20
  name: "install",
@@ -21,7 +22,7 @@ const skillsInstall = makeInstallCommand({
21
22
  });
22
23
  const skillsCommand = Command.make("skills", {}, () => Console.log("Usage: jira skills install")).pipe(Command.withDescription("Local write agent skill commands"), Command.withSubcommands([skillsInstall]));
23
24
  // === Main command ===
24
- const jira = Command.make("jira").pipe(Command.withDescription("Jira CLI commands"), Command.withSubcommands([
25
+ const jira = Command.make("jira").pipe(Command.withDescription("Jira CLI commands"), Command.withGlobalFlags([Verbose]), Command.withSubcommands([
25
26
  authCommand,
26
27
  issueCommand,
27
28
  skillsCommand,
@@ -34,13 +35,16 @@ const cli = Command.runWith(jira, {
34
35
  const program = Effect.gen(function* () {
35
36
  const stdio = yield* Stdio.Stdio;
36
37
  const args = yield* stdio.args;
37
- const layerType = getLayerType(args);
38
+ const layerType = getLayerType(commandArgs(args));
38
39
  const layer = layerType === "full"
39
40
  ? AppLayer
40
41
  : layerType === "auth"
41
42
  ? AuthOnlyLayer
42
43
  : MinimalLayer;
43
44
  return yield* cli(args).pipe(Effect.provide(layer));
44
- }).pipe(Effect.provide(NodeStdio.layer), Effect.catchCause((cause) => handleError(cause).pipe(Effect.andThen(Effect.failCause(cause)))));
45
+ }).pipe(withCliErrorHandling,
46
+ // Executable entry point: the host's stdio is provided once for this process.
47
+ // @effect-diagnostics-next-line strictEffectProvide:off
48
+ Effect.provide(NodeStdio.layer));
45
49
  NodeRuntime.runMain(program, { disableErrorReporting: true });
46
50
  //# sourceMappingURL=bin.js.map
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AACH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACvD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACf,MAAM,qBAAqB,CAAA;AAE5B,MAAM,aAAa,GAAG,kBAAkB,CAAC;IACvC,WAAW,EAAE,8BAA8B;IAC3C,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,CAAC,MAAM,CAAC;CACjB,CAAC,CAAA;AAEF,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CACpG,OAAO,CAAC,eAAe,CAAC,kCAAkC,CAAC,EAC3D,OAAO,CAAC,eAAe,CAAC,CAAC,aAAa,CAAC,CAAC,CACzC,CAAA;AAED,uBAAuB;AACvB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CACpC,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,EAC5C,OAAO,CAAC,eAAe,CAAC;IACtB,WAAW;IACX,YAAY;IACZ,aAAa;IACb,cAAc;CACf,CAAC,CACH,CAAA;AAED,kBAAkB;AAClB,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE;IAChC,OAAO,EAAE,GAAG,CAAC,OAAO;CACrB,CAAC,CAAA;AAEF,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAA;IAChC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAA;IAC9B,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;IACpC,MAAM,KAAK,GAAG,SAAS,KAAK,MAAM;QAChC,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,SAAS,KAAK,MAAM;YACtB,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,YAAY,CAAA;IAEhB,OAAO,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAC1B,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CACtB,CAAA;AACH,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAC/B,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAC/F,CAAA;AAED,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAA"}
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AACH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACvD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,cAAc,EACf,MAAM,qBAAqB,CAAA;AAE5B,MAAM,aAAa,GAAG,kBAAkB,CAAC;IACvC,WAAW,EAAE,8BAA8B;IAC3C,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,CAAC,MAAM,CAAC;CACjB,CAAC,CAAA;AAEF,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CACpG,OAAO,CAAC,eAAe,CAAC,kCAAkC,CAAC,EAC3D,OAAO,CAAC,eAAe,CAAC,CAAC,aAAa,CAAC,CAAC,CACzC,CAAA;AAED,uBAAuB;AACvB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CACpC,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,EAC5C,OAAO,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,EAClC,OAAO,CAAC,eAAe,CAAC;IACtB,WAAW;IACX,YAAY;IACZ,aAAa;IACb,cAAc;CACf,CAAC,CACH,CAAA;AAED,kBAAkB;AAClB,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE;IAChC,OAAO,EAAE,GAAG,CAAC,OAAO;CACrB,CAAC,CAAA;AAEF,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAA;IAChC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAA;IAC9B,MAAM,SAAS,GAAG,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;IACjD,MAAM,KAAK,GAAG,SAAS,KAAK,MAAM;QAChC,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,SAAS,KAAK,MAAM;YACtB,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,YAAY,CAAA;IAEhB,OAAO,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAC1B,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CACtB,CAAA;AACH,CAAC,CAAC,CAAC,IAAI,CACL,oBAAoB;AACpB,8EAA8E;AAC9E,wDAAwD;AACxD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAChC,CAAA;AAED,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAA"}
@@ -1,3 +1,3 @@
1
1
  import { JiraAuth } from "../JiraAuth.js";
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>;
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("@knpkv/atlassian-common/cli-auth").ProfileNotFoundError | import("effect/Terminal").QuitError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | JiraAuth | import("effect/cli/Prompt").Environment>;
3
3
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
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
+ {"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,2hBAA2E,CAAA"}
@@ -4,7 +4,6 @@
4
4
  * @module
5
5
  */
6
6
  export { authCommand } from "./auth.js";
7
- export { handleError } from "./errorHandler.js";
8
7
  export { issueCommand } from "./issue.js";
9
8
  export { attachmentCommand } from "./issueAttachment.js";
10
9
  export { AppLayer, AuthOnlyLayer, getLayerType, MinimalLayer } from "./layers.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA"}
@@ -4,7 +4,6 @@
4
4
  * @module
5
5
  */
6
6
  export { authCommand } from "./auth.js";
7
- export { handleError } from "./errorHandler.js";
8
7
  export { issueCommand } from "./issue.js";
9
8
  export { attachmentCommand } from "./issueAttachment.js";
10
9
  export { AppLayer, AuthOnlyLayer, getLayerType, MinimalLayer } from "./layers.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,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").FileSystemError | import("@knpkv/atlassian-common").HomeDirectoryError | import("@knpkv/atlassian-common").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").OAuthError | (import("@knpkv/atlassian-common").FileSystemError | import("@knpkv/atlassian-common").HomeDirectoryError | 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,+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"}
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,icASpB,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.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "CLI tool to fetch Jira tickets and export to markdown",
5
5
  "license": "MIT",
6
6
  "author": "knpkv",
@@ -61,7 +61,7 @@
61
61
  "gray-matter": "^4.0.3",
62
62
  "js-yaml": "5.4.2",
63
63
  "@knpkv/agent-skills": "^0.3.3",
64
- "@knpkv/atlassian-common": "1.7.0",
64
+ "@knpkv/atlassian-common": "1.9.0",
65
65
  "@knpkv/jira-api-client": "2.0.0"
66
66
  },
67
67
  "devDependencies": {
package/src/JiraAuth.ts CHANGED
@@ -16,20 +16,14 @@
16
16
  *
17
17
  * @module
18
18
  */
19
- import type { OAuthError } from "@knpkv/atlassian-common/auth"
20
- import { type AtlassianCliDescriptor, makeAtlassianCliAuth, NodeCliAuthLive } from "@knpkv/atlassian-common/cli-auth"
21
- import type {
22
- AuthProfile,
23
- FileSystemError,
24
- HomeDirectoryError,
25
- OAuthConfig,
26
- OAuthUser
27
- } from "@knpkv/atlassian-common/config"
19
+ import {
20
+ type AtlassianCliAuth,
21
+ type AtlassianCliDescriptor,
22
+ makeAtlassianCliAuth,
23
+ NodeCliAuthLive
24
+ } from "@knpkv/atlassian-common/cli-auth"
28
25
  import * as Context from "effect/Context"
29
- import type * as Effect from "effect/Effect"
30
26
  import * as Layer from "effect/Layer"
31
- import type * as PlatformError from "effect/PlatformError"
32
- import type * as Redacted from "effect/Redacted"
33
27
  import type { AuthMissingError } from "./JiraCliError.js"
34
28
  import { authMissing } from "./JiraCliError.js"
35
29
 
@@ -51,95 +45,15 @@ const JIRA_CLI_SCOPES = [
51
45
  "offline_access"
52
46
  ]
53
47
 
54
- /**
55
- * Options for the login method.
56
- *
57
- * @category Types
58
- */
59
- export interface LoginOptions {
60
- /** Site URL to select (for accounts with multiple sites) */
61
- readonly siteUrl?: string
62
- }
63
-
64
- /**
65
- * Information about an accessible Jira site.
66
- *
67
- * @category Types
68
- */
69
- export interface AccessibleSite {
70
- readonly id: string
71
- readonly name: string
72
- readonly url: string
73
- }
48
+ export type { AccessibleSite, LoginOptions } from "@knpkv/atlassian-common/cli-auth"
74
49
 
75
50
  /**
76
- * JiraAuth service interface.
51
+ * JiraAuth service interface: the shared Atlassian CLI auth, failing with Jira's own
52
+ * {@link AuthMissingError} when nobody is logged in.
77
53
  *
78
54
  * @category Services
79
55
  */
80
- export interface JiraAuthService {
81
- /** Configure OAuth client credentials */
82
- readonly configure: (
83
- config: OAuthConfig
84
- ) => Effect.Effect<void, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>
85
- /** Check if OAuth is configured */
86
- readonly isConfigured: () => Effect.Effect<
87
- boolean,
88
- FileSystemError | HomeDirectoryError | PlatformError.PlatformError
89
- >
90
- /** Start OAuth login flow. Returns list of sites if multiple are available. */
91
- readonly login: (
92
- options?: LoginOptions
93
- ) => Effect.Effect<
94
- ReadonlyArray<AccessibleSite> | void,
95
- OAuthError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError
96
- >
97
- /** Remove stored authentication */
98
- readonly logout: () => Effect.Effect<
99
- void,
100
- OAuthError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError
101
- >
102
- /** Get access token, refreshing if needed */
103
- readonly getAccessToken: () => Effect.Effect<
104
- Redacted.Redacted<string>,
105
- AuthMissingError | OAuthError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError
106
- >
107
- /** Get cloud ID from stored token */
108
- readonly getCloudId: () => Effect.Effect<
109
- string,
110
- AuthMissingError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError
111
- >
112
- /** Get site URL from stored token */
113
- readonly getSiteUrl: () => Effect.Effect<
114
- string,
115
- AuthMissingError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError
116
- >
117
- /** Get current user info from stored token */
118
- readonly getCurrentUser: () => Effect.Effect<
119
- OAuthUser | null,
120
- FileSystemError | HomeDirectoryError | PlatformError.PlatformError
121
- >
122
- /** Get active auth profile */
123
- readonly getActiveProfile: () => Effect.Effect<
124
- AuthProfile | null,
125
- FileSystemError | HomeDirectoryError | PlatformError.PlatformError
126
- >
127
- /** List stored auth profiles */
128
- readonly listProfiles: () => Effect.Effect<
129
- ReadonlyArray<AuthProfile>,
130
- FileSystemError | HomeDirectoryError | PlatformError.PlatformError
131
- >
132
- /** Switch active profile by ID, name, site URL, cloud ID, or account ID */
133
- readonly switchProfile: (
134
- selector: string
135
- ) => Effect.Effect<AuthProfile | null, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>
136
- /** Remove stored profile by ID, name, site URL, cloud ID, or account ID */
137
- readonly removeProfile: (
138
- selector: string
139
- ) => Effect.Effect<AuthProfile | null, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>
140
- /** Check if user is logged in */
141
- readonly isLoggedIn: () => Effect.Effect<boolean, FileSystemError | HomeDirectoryError | PlatformError.PlatformError>
142
- }
56
+ export interface JiraAuthService extends AtlassianCliAuth<AuthMissingError> {}
143
57
 
144
58
  /**
145
59
  * JiraAuth service tag.
package/src/bin.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { NodeRuntime, NodeStdio } from "@effect/platform-node"
10
10
  import { makeInstallCommand } from "@knpkv/agent-skills"
11
+ import { commandArgs, Verbose, withCliErrorHandling } from "@knpkv/atlassian-common/cli"
11
12
  import { Command } from "effect/cli"
12
13
  import * as Console from "effect/Console"
13
14
  import * as Effect from "effect/Effect"
@@ -18,7 +19,6 @@ import {
18
19
  authCommand,
19
20
  AuthOnlyLayer,
20
21
  getLayerType,
21
- handleError,
22
22
  issueCommand,
23
23
  MinimalLayer,
24
24
  versionCommand
@@ -38,6 +38,7 @@ const skillsCommand = Command.make("skills", {}, () => Console.log("Usage: jira
38
38
  // === Main command ===
39
39
  const jira = Command.make("jira").pipe(
40
40
  Command.withDescription("Jira CLI commands"),
41
+ Command.withGlobalFlags([Verbose]),
41
42
  Command.withSubcommands([
42
43
  authCommand,
43
44
  issueCommand,
@@ -54,7 +55,7 @@ const cli = Command.runWith(jira, {
54
55
  const program = Effect.gen(function*() {
55
56
  const stdio = yield* Stdio.Stdio
56
57
  const args = yield* stdio.args
57
- const layerType = getLayerType(args)
58
+ const layerType = getLayerType(commandArgs(args))
58
59
  const layer = layerType === "full"
59
60
  ? AppLayer
60
61
  : layerType === "auth"
@@ -65,8 +66,10 @@ const program = Effect.gen(function*() {
65
66
  Effect.provide(layer)
66
67
  )
67
68
  }).pipe(
68
- Effect.provide(NodeStdio.layer),
69
- Effect.catchCause((cause) => handleError(cause).pipe(Effect.andThen(Effect.failCause(cause))))
69
+ withCliErrorHandling,
70
+ // Executable entry point: the host's stdio is provided once for this process.
71
+ // @effect-diagnostics-next-line strictEffectProvide:off
72
+ Effect.provide(NodeStdio.layer)
70
73
  )
71
74
 
72
75
  NodeRuntime.runMain(program, { disableErrorReporting: true })
@@ -5,7 +5,6 @@
5
5
  */
6
6
 
7
7
  export { authCommand } from "./auth.js"
8
- export { handleError } from "./errorHandler.js"
9
8
  export { issueCommand } from "./issue.js"
10
9
  export { attachmentCommand } from "./issueAttachment.js"
11
10
  export { AppLayer, AuthOnlyLayer, getLayerType, MinimalLayer } from "./layers.js"
@@ -1,17 +1,9 @@
1
1
  import { defineConfig } from "vitest/config"
2
+ import { workspaceSourceAlias } from "../../vitest.workspace-sources.ts"
2
3
 
3
4
  export default defineConfig({
4
5
  resolve: {
5
- alias: {
6
- "@knpkv/atlassian-common/attachments":
7
- new URL("../atlassian-common/src/attachments.ts", import.meta.url).pathname,
8
- "@knpkv/atlassian-common/auth": new URL("../atlassian-common/src/auth/index.ts", import.meta.url).pathname,
9
- "@knpkv/atlassian-common/cli-auth":
10
- new URL("../atlassian-common/src/cli-auth/index.ts", import.meta.url).pathname,
11
- "@knpkv/atlassian-common/config": new URL("../atlassian-common/src/config/index.ts", import.meta.url).pathname,
12
- "@knpkv/agent-skills": new URL("../agent-skills/src/index.ts", import.meta.url).pathname,
13
- "@knpkv/jira-api-client": new URL("../jira-api-client/src/index.ts", import.meta.url).pathname
14
- }
6
+ alias: [...workspaceSourceAlias]
15
7
  },
16
8
  test: {
17
9
  include: ["test/integration.test.ts"],
package/vitest.config.ts CHANGED
@@ -1,17 +1,9 @@
1
1
  import { defineConfig } from "vitest/config"
2
+ import { workspaceSourceAlias } from "../../vitest.workspace-sources.ts"
2
3
 
3
4
  export default defineConfig({
4
5
  resolve: {
5
- alias: {
6
- "@knpkv/atlassian-common/attachments":
7
- new URL("../atlassian-common/src/attachments.ts", import.meta.url).pathname,
8
- "@knpkv/atlassian-common/auth": new URL("../atlassian-common/src/auth/index.ts", import.meta.url).pathname,
9
- "@knpkv/atlassian-common/cli-auth":
10
- new URL("../atlassian-common/src/cli-auth/index.ts", import.meta.url).pathname,
11
- "@knpkv/atlassian-common/config": new URL("../atlassian-common/src/config/index.ts", import.meta.url).pathname,
12
- "@knpkv/agent-skills": new URL("../agent-skills/src/index.ts", import.meta.url).pathname,
13
- "@knpkv/jira-api-client": new URL("../jira-api-client/src/index.ts", import.meta.url).pathname
14
- }
6
+ alias: [...workspaceSourceAlias]
15
7
  },
16
8
  test: {
17
9
  include: ["test/**/*.test.ts"],
@@ -1,13 +0,0 @@
1
- /**
2
- * Effect-idiomatic error handler — uses Cause.pretty for structured failure output.
3
- *
4
- * @internal
5
- */
6
- import * as Cause from "effect/Cause";
7
- import type * as Effect from "effect/Effect";
8
- /**
9
- * Handle errors from CLI execution.
10
- * Logs the pretty-printed cause to stderr via Console.error.
11
- */
12
- export declare const handleError: <E>(cause: Cause.Cause<E>) => Effect.Effect<void>;
13
- //# sourceMappingURL=errorHandler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/commands/errorHandler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAE5C;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAuC,CAAA"}
@@ -1,13 +0,0 @@
1
- /**
2
- * Effect-idiomatic error handler — uses Cause.pretty for structured failure output.
3
- *
4
- * @internal
5
- */
6
- import * as Cause from "effect/Cause";
7
- import * as Console from "effect/Console";
8
- /**
9
- * Handle errors from CLI execution.
10
- * Logs the pretty-printed cause to stderr via Console.error.
11
- */
12
- export const handleError = (cause) => Console.error(Cause.pretty(cause));
13
- //# sourceMappingURL=errorHandler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/commands/errorHandler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAGzC;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAI,KAAqB,EAAuB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Effect-idiomatic error handler — uses Cause.pretty for structured failure output.
3
- *
4
- * @internal
5
- */
6
- import * as Cause from "effect/Cause"
7
- import * as Console from "effect/Console"
8
- import type * as Effect from "effect/Effect"
9
-
10
- /**
11
- * Handle errors from CLI execution.
12
- * Logs the pretty-printed cause to stderr via Console.error.
13
- */
14
- export const handleError = <E>(cause: Cause.Cause<E>): Effect.Effect<void> => Console.error(Cause.pretty(cause))