@knpkv/atlassian-common 0.3.0 → 1.0.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +29 -13
  3. package/dist/Hash.d.ts +4 -4
  4. package/dist/Hash.js +6 -6
  5. package/dist/Hash.js.map +1 -1
  6. package/dist/auth/OAuthEndpoints.d.ts +6 -4
  7. package/dist/auth/OAuthEndpoints.d.ts.map +1 -1
  8. package/dist/auth/OAuthEndpoints.js +12 -7
  9. package/dist/auth/OAuthEndpoints.js.map +1 -1
  10. package/dist/auth/OAuthErrors.d.ts.map +1 -1
  11. package/dist/auth/OAuthErrors.js +4 -3
  12. package/dist/auth/OAuthErrors.js.map +1 -1
  13. package/dist/auth/OAuthOperations.d.ts +0 -20
  14. package/dist/auth/OAuthOperations.d.ts.map +1 -1
  15. package/dist/auth/OAuthOperations.js +3 -1
  16. package/dist/auth/OAuthOperations.js.map +1 -1
  17. package/dist/auth/uuid.d.ts +5 -3
  18. package/dist/auth/uuid.d.ts.map +1 -1
  19. package/dist/auth/uuid.js +7 -3
  20. package/dist/auth/uuid.js.map +1 -1
  21. package/dist/bin.d.ts +3 -0
  22. package/dist/bin.d.ts.map +1 -0
  23. package/dist/bin.js +58 -0
  24. package/dist/bin.js.map +1 -0
  25. package/dist/config/AuthProfiles.d.ts +342 -0
  26. package/dist/config/AuthProfiles.d.ts.map +1 -0
  27. package/dist/config/AuthProfiles.js +275 -0
  28. package/dist/config/AuthProfiles.js.map +1 -0
  29. package/dist/config/ConfigPaths.d.ts +6 -0
  30. package/dist/config/ConfigPaths.d.ts.map +1 -1
  31. package/dist/config/ConfigPaths.js +10 -0
  32. package/dist/config/ConfigPaths.js.map +1 -1
  33. package/dist/config/ProfileManager.d.ts +92 -0
  34. package/dist/config/ProfileManager.d.ts.map +1 -0
  35. package/dist/config/ProfileManager.js +175 -0
  36. package/dist/config/ProfileManager.js.map +1 -0
  37. package/dist/config/index.d.ts +3 -1
  38. package/dist/config/index.d.ts.map +1 -1
  39. package/dist/config/index.js +5 -1
  40. package/dist/config/index.js.map +1 -1
  41. package/package.json +11 -3
  42. package/src/Hash.ts +6 -6
  43. package/src/auth/OAuthEndpoints.ts +18 -11
  44. package/src/auth/OAuthErrors.ts +4 -3
  45. package/src/auth/OAuthOperations.ts +3 -1
  46. package/src/auth/uuid.ts +9 -3
  47. package/src/bin.ts +115 -0
  48. package/src/config/AuthProfiles.ts +384 -0
  49. package/src/config/ConfigPaths.ts +14 -0
  50. package/src/config/ProfileManager.ts +268 -0
  51. package/src/config/index.ts +42 -0
  52. package/test/AuthProfiles.test.ts +131 -0
  53. package/test/OAuthEndpoints.test.ts +20 -15
  54. package/test/OAuthOperations.test.ts +5 -1
  55. package/test/ProfileManager.test.ts +188 -0
  56. package/tsconfig.tsbuildinfo +1 -1
@@ -95,6 +95,16 @@ export const getOAuthConfigPath = (toolName) => Effect.gen(function* () {
95
95
  const configDir = yield* getConfigDir(toolName);
96
96
  return path.join(configDir, "oauth.json");
97
97
  });
98
+ /**
99
+ * Get auth profiles file path for a specific tool.
100
+ *
101
+ * @category Utilities
102
+ */
103
+ export const getProfilesPath = (toolName) => Effect.gen(function* () {
104
+ const path = yield* Path.Path;
105
+ const configDir = yield* getConfigDir(toolName);
106
+ return path.join(configDir, "profiles.json");
107
+ });
98
108
  /**
99
109
  * Ensure config directory exists with secure permissions.
100
110
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigPaths.js","sourceRoot":"","sources":["../../src/config/ConfigPaths.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ConfigPaths.js","sourceRoot":"","sources":["../../src/config/ConfigPaths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as FileSystem from "effect/FileSystem";
3
+ import * as Path from "effect/Path";
4
+ import type * as PlatformError from "effect/PlatformError";
5
+ import type { HttpClient } from "effect/unstable/http";
6
+ import type { OAuthError } from "../auth/OAuthErrors.js";
7
+ import { type AuthProfile } from "./AuthProfiles.js";
8
+ import { type HomeDirectoryError, HomeDirectoryTag } from "./ConfigPaths.js";
9
+ import { type OAuthToken } from "./OAuthSchemas.js";
10
+ import { FileSystemError } from "./TokenStorage.js";
11
+ export interface AtlassianToolDefinition {
12
+ readonly toolName: string;
13
+ readonly authStoreName?: string;
14
+ readonly legacyAuthPath?: ReadonlyArray<string>;
15
+ readonly label: string;
16
+ readonly loginHint: string;
17
+ readonly requiredScopes: ReadonlyArray<string>;
18
+ }
19
+ export declare const JIRA_REQUIRED_SCOPES: readonly ["read:jira-work", "write:jira-work", "manage:jira-project", "read:jira-user", "read:me", "offline_access"];
20
+ export declare const CONFLUENCE_REQUIRED_SCOPES: readonly ["read:page:confluence", "write:page:confluence", "delete:page:confluence", "read:me", "offline_access"];
21
+ export declare const ATLASSIAN_TOOLS: readonly [{
22
+ readonly toolName: "jira-cli";
23
+ readonly label: "Jira CLI";
24
+ readonly loginHint: "jira auth login";
25
+ readonly requiredScopes: readonly ["read:jira-work", "write:jira-work", "manage:jira-project", "read:jira-user", "read:me", "offline_access"];
26
+ }, {
27
+ readonly toolName: "confluence-to-markdown";
28
+ readonly legacyAuthPath: readonly [".confluence", "auth.json"];
29
+ readonly label: "Confluence to Markdown";
30
+ readonly loginHint: "confluence auth login";
31
+ readonly requiredScopes: readonly ["read:page:confluence", "write:page:confluence", "delete:page:confluence", "read:me", "offline_access"];
32
+ }, {
33
+ readonly toolName: "jira-clockify";
34
+ readonly authStoreName: "jira-cli";
35
+ readonly label: "Jira Clockify";
36
+ readonly loginHint: "jcf auth jira login";
37
+ readonly requiredScopes: readonly ["read:jira-work", "write:jira-work", "manage:jira-project", "read:jira-user", "read:me", "offline_access"];
38
+ }];
39
+ export type ProfileTokenStatus = "valid" | "expired";
40
+ declare const ProfileNotFoundError_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 & {
41
+ readonly _tag: "ProfileNotFoundError";
42
+ } & Readonly<A>;
43
+ export declare class ProfileNotFoundError extends ProfileNotFoundError_base<{
44
+ readonly selector: string;
45
+ }> {
46
+ get message(): string;
47
+ }
48
+ declare const MissingOAuthConfigError_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 & {
49
+ readonly _tag: "MissingOAuthConfigError";
50
+ } & Readonly<A>;
51
+ export declare class MissingOAuthConfigError extends MissingOAuthConfigError_base<{
52
+ readonly authStoreName: string;
53
+ readonly profileId: string;
54
+ }> {
55
+ get message(): string;
56
+ }
57
+ export interface ToolProfileStatus {
58
+ readonly tool: AtlassianToolDefinition;
59
+ readonly authStoreName: string;
60
+ readonly activeProfile: AuthProfile | null;
61
+ readonly profiles: ReadonlyArray<AuthProfile>;
62
+ readonly tokenStatus: ProfileTokenStatus | "missing";
63
+ readonly missingScopes: ReadonlyArray<string>;
64
+ readonly oauthConfigured: boolean;
65
+ }
66
+ export declare const tokenScopes: (token: OAuthToken) => ReadonlySet<string>;
67
+ export declare const missingScopes: (token: OAuthToken, requiredScopes: ReadonlyArray<string>) => ReadonlyArray<string>;
68
+ export declare const inspectToolProfiles: (tool: AtlassianToolDefinition) => Effect.Effect<ToolProfileStatus, FileSystemError | HomeDirectoryError, FileSystem.FileSystem | Path.Path | HomeDirectoryTag>;
69
+ export declare const inspectAllToolProfiles: (tools?: ReadonlyArray<AtlassianToolDefinition>) => Effect.Effect<ToolProfileStatus[], HomeDirectoryError | FileSystemError, HomeDirectoryTag | Path.Path | FileSystem.FileSystem>;
70
+ /**
71
+ * Switch matching existing profiles across auth stores.
72
+ *
73
+ * Fails when the selector is not present in any store so callers do not
74
+ * mistake an unchanged profile list for a successful switch.
75
+ */
76
+ export declare const useProfileForAllTools: (selector: string, tools?: ReadonlyArray<AtlassianToolDefinition>) => Effect.Effect<ReadonlyArray<ToolProfileStatus>, ProfileNotFoundError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError, FileSystem.FileSystem | Path.Path | HomeDirectoryTag>;
77
+ /**
78
+ * Persist legacy single-token auth files into shared profile stores.
79
+ *
80
+ * Supports both XDG Atlassian auth files and tool-specific legacy paths such
81
+ * as Confluence's historical `~/.confluence/auth.json`.
82
+ */
83
+ export declare const migrateLegacyProfiles: (tools?: ReadonlyArray<AtlassianToolDefinition>) => Effect.Effect<ReadonlyArray<ToolProfileStatus>, FileSystemError | HomeDirectoryError | PlatformError.PlatformError, FileSystem.FileSystem | Path.Path | HomeDirectoryTag>;
84
+ /**
85
+ * Refresh expired active profiles.
86
+ *
87
+ * Fails when an expired profile lacks OAuth client configuration so refresh
88
+ * callers cannot report success while leaving a token expired.
89
+ */
90
+ export declare const refreshActiveProfiles: (tools?: ReadonlyArray<AtlassianToolDefinition>) => Effect.Effect<ReadonlyArray<ToolProfileStatus>, MissingOAuthConfigError | OAuthError | FileSystemError | HomeDirectoryError | PlatformError.PlatformError, FileSystem.FileSystem | Path.Path | HomeDirectoryTag | HttpClient.HttpClient>;
91
+ export {};
92
+ //# sourceMappingURL=ProfileManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProfileManager.d.ts","sourceRoot":"","sources":["../../src/config/ProfileManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Unified Atlassian profile management helpers shared by Atlassian CLIs.
3
+ *
4
+ * @module
5
+ */
6
+ import * as Data from "effect/Data";
7
+ import * as Effect from "effect/Effect";
8
+ import * as FileSystem from "effect/FileSystem";
9
+ import * as Path from "effect/Path";
10
+ import * as Schema from "effect/Schema";
11
+ import { refreshToken } from "../auth/OAuthOperations.js";
12
+ import { findProfile, loadProfiles, saveProfiles, saveProfileToken } from "./AuthProfiles.js";
13
+ import { getProfilesPath, HomeDirectoryTag } from "./ConfigPaths.js";
14
+ import { OAuthTokenSchema } from "./OAuthSchemas.js";
15
+ import { FileSystemError, isTokenExpired, loadOAuthConfig } from "./TokenStorage.js";
16
+ export const JIRA_REQUIRED_SCOPES = [
17
+ "read:jira-work",
18
+ "write:jira-work",
19
+ "manage:jira-project",
20
+ "read:jira-user",
21
+ "read:me",
22
+ "offline_access"
23
+ ];
24
+ export const CONFLUENCE_REQUIRED_SCOPES = [
25
+ "read:page:confluence",
26
+ "write:page:confluence",
27
+ "delete:page:confluence",
28
+ "read:me",
29
+ "offline_access"
30
+ ];
31
+ export const ATLASSIAN_TOOLS = [
32
+ {
33
+ toolName: "jira-cli",
34
+ label: "Jira CLI",
35
+ loginHint: "jira auth login",
36
+ requiredScopes: JIRA_REQUIRED_SCOPES
37
+ },
38
+ {
39
+ toolName: "confluence-to-markdown",
40
+ legacyAuthPath: [".confluence", "auth.json"],
41
+ label: "Confluence to Markdown",
42
+ loginHint: "confluence auth login",
43
+ requiredScopes: CONFLUENCE_REQUIRED_SCOPES
44
+ },
45
+ {
46
+ toolName: "jira-clockify",
47
+ authStoreName: "jira-cli",
48
+ label: "Jira Clockify",
49
+ loginHint: "jcf auth jira login",
50
+ requiredScopes: JIRA_REQUIRED_SCOPES
51
+ }
52
+ ];
53
+ export class ProfileNotFoundError extends Data.TaggedError("ProfileNotFoundError") {
54
+ get message() {
55
+ return `Profile not found: ${this.selector}`;
56
+ }
57
+ }
58
+ export class MissingOAuthConfigError extends Data.TaggedError("MissingOAuthConfigError") {
59
+ get message() {
60
+ return `Cannot refresh expired profile ${this.profileId}: missing OAuth config for ${this.authStoreName}`;
61
+ }
62
+ }
63
+ const authStoreName = (tool) => tool.authStoreName ?? tool.toolName;
64
+ const uniqueAuthTools = (tools) => tools.filter((tool, index) => tools.findIndex((candidate) => authStoreName(candidate) === authStoreName(tool)) === index);
65
+ const loadLegacyToken = (tool) => Effect.gen(function* () {
66
+ if (!tool.legacyAuthPath)
67
+ return null;
68
+ const fs = yield* FileSystem.FileSystem;
69
+ const path = yield* Path.Path;
70
+ const homeDirectory = yield* HomeDirectoryTag;
71
+ const home = yield* homeDirectory.get();
72
+ const authPath = path.join(home, ...tool.legacyAuthPath);
73
+ const exists = yield* fs.exists(authPath).pipe(Effect.catch(() => Effect.succeed(false)));
74
+ if (!exists)
75
+ return null;
76
+ const content = yield* fs.readFileString(authPath).pipe(Effect.mapError((cause) => new FileSystemError({ operation: "read", path: authPath, cause })));
77
+ const parsed = yield* Effect.try({
78
+ try: () => JSON.parse(content),
79
+ catch: (cause) => cause
80
+ }).pipe(Effect.catch(() => Effect.succeed(null)));
81
+ if (parsed === null)
82
+ return null;
83
+ return yield* Schema.decodeUnknownEffect(OAuthTokenSchema)(parsed).pipe(Effect.catch(() => Effect.succeed(null)));
84
+ });
85
+ export const tokenScopes = (token) => new Set(token.scope.split(/\s+/).filter((scope) => scope.length > 0));
86
+ export const missingScopes = (token, requiredScopes) => {
87
+ const granted = tokenScopes(token);
88
+ return requiredScopes.filter((scope) => !granted.has(scope));
89
+ };
90
+ export const inspectToolProfiles = (tool) => Effect.gen(function* () {
91
+ const storeName = authStoreName(tool);
92
+ const [store, config] = yield* Effect.all([loadProfiles(storeName), loadOAuthConfig(storeName)]);
93
+ const activeProfile = store.profiles.find((profile) => profile.id === store.activeProfileId) ?? store.profiles[0] ??
94
+ null;
95
+ return {
96
+ tool,
97
+ authStoreName: storeName,
98
+ activeProfile,
99
+ profiles: store.profiles,
100
+ tokenStatus: activeProfile === null ? "missing" : isTokenExpired(activeProfile.token, 0) ? "expired" : "valid",
101
+ missingScopes: activeProfile === null ? [] : missingScopes(activeProfile.token, tool.requiredScopes),
102
+ oauthConfigured: config !== null
103
+ };
104
+ });
105
+ export const inspectAllToolProfiles = (tools = ATLASSIAN_TOOLS) => Effect.forEach(tools, inspectToolProfiles);
106
+ /**
107
+ * Switch matching existing profiles across auth stores.
108
+ *
109
+ * Fails when the selector is not present in any store so callers do not
110
+ * mistake an unchanged profile list for a successful switch.
111
+ */
112
+ export const useProfileForAllTools = (selector, tools = ATLASSIAN_TOOLS) => Effect.gen(function* () {
113
+ const authTools = uniqueAuthTools(tools);
114
+ const stores = yield* Effect.forEach(authTools, (tool) => loadProfiles(authStoreName(tool)).pipe(Effect.map((store) => [tool, store])));
115
+ const selected = stores.map(([, store]) => findProfile(store.profiles, selector)).find((profile) => profile !== null);
116
+ if (!selected)
117
+ return yield* Effect.fail(new ProfileNotFoundError({ selector }));
118
+ yield* Effect.forEach(stores, ([tool, store]) => {
119
+ const matching = findProfile(store.profiles, selector) ?? findProfile(store.profiles, selected.id);
120
+ if (!matching)
121
+ return Effect.void;
122
+ return saveProfiles(authStoreName(tool), { ...store, activeProfileId: matching.id });
123
+ });
124
+ return yield* inspectAllToolProfiles(tools);
125
+ });
126
+ /**
127
+ * Persist legacy single-token auth files into shared profile stores.
128
+ *
129
+ * Supports both XDG Atlassian auth files and tool-specific legacy paths such
130
+ * as Confluence's historical `~/.confluence/auth.json`.
131
+ */
132
+ export const migrateLegacyProfiles = (tools = ATLASSIAN_TOOLS) => Effect.gen(function* () {
133
+ const fs = yield* FileSystem.FileSystem;
134
+ yield* Effect.forEach(uniqueAuthTools(tools), (tool) => Effect.gen(function* () {
135
+ const storeName = authStoreName(tool);
136
+ const profilesPath = yield* getProfilesPath(storeName);
137
+ const hasProfilesFile = yield* fs.exists(profilesPath).pipe(Effect.catch(() => Effect.succeed(false)));
138
+ if (hasProfilesFile)
139
+ return;
140
+ const store = yield* loadProfiles(storeName);
141
+ if (store.profiles.length > 0) {
142
+ yield* saveProfiles(storeName, store);
143
+ return;
144
+ }
145
+ const legacyToken = yield* loadLegacyToken(tool);
146
+ if (legacyToken !== null) {
147
+ yield* saveProfileToken(storeName, legacyToken);
148
+ }
149
+ }));
150
+ return yield* inspectAllToolProfiles(tools);
151
+ });
152
+ /**
153
+ * Refresh expired active profiles.
154
+ *
155
+ * Fails when an expired profile lacks OAuth client configuration so refresh
156
+ * callers cannot report success while leaving a token expired.
157
+ */
158
+ export const refreshActiveProfiles = (tools = ATLASSIAN_TOOLS) => Effect.gen(function* () {
159
+ yield* Effect.forEach(uniqueAuthTools(tools), (tool) => Effect.gen(function* () {
160
+ const storeName = authStoreName(tool);
161
+ const store = yield* loadProfiles(storeName);
162
+ const active = store.profiles.find((profile) => profile.id === store.activeProfileId) ?? store.profiles[0] ??
163
+ null;
164
+ if (!active || !isTokenExpired(active.token, 0))
165
+ return;
166
+ const config = yield* loadOAuthConfig(storeName);
167
+ if (!config) {
168
+ return yield* Effect.fail(new MissingOAuthConfigError({ authStoreName: storeName, profileId: active.id }));
169
+ }
170
+ const refreshed = yield* refreshToken(active.token, config);
171
+ yield* saveProfileToken(storeName, refreshed);
172
+ }));
173
+ return yield* inspectAllToolProfiles(tools);
174
+ });
175
+ //# sourceMappingURL=ProfileManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProfileManager.js","sourceRoot":"","sources":["../../src/config/ProfileManager.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,9 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- export { ensureConfigDir, getAuthPath, getConfigDir, getOAuthConfigPath, type HomeDirectory, HomeDirectoryError, HomeDirectoryLive, HomeDirectoryTag, writeSecureFile } from "./ConfigPaths.js";
6
+ export { ensureConfigDir, getAuthPath, getConfigDir, getOAuthConfigPath, getProfilesPath, type HomeDirectory, HomeDirectoryError, HomeDirectoryLive, HomeDirectoryTag, writeSecureFile } from "./ConfigPaths.js";
7
7
  export { type AtlassianSite, AtlassianSiteSchema, type AtlassianUser, AtlassianUserSchema, type OAuthConfig, OAuthConfigSchema, type OAuthToken, OAuthTokenSchema, type OAuthUser, OAuthUserSchema } from "./OAuthSchemas.js";
8
8
  export { deleteToken, FileSystemError, isTokenExpired, loadOAuthConfig, loadToken, saveOAuthConfig, saveToken } from "./TokenStorage.js";
9
+ export { type AuthProfile, AuthProfileSchema, type AuthProfilesFile, AuthProfilesFileSchema, deleteActiveProfile, deleteProfile, deleteProfileBySelector, findProfile, loadActiveProfile, loadActiveProfileToken, loadProfiles, profileFromToken, profileIdFromToken, profileNameFromToken, saveProfiles, saveProfileToken, setActiveProfile, setActiveProfileBySelector } from "./AuthProfiles.js";
10
+ export { ATLASSIAN_TOOLS, type AtlassianToolDefinition, CONFLUENCE_REQUIRED_SCOPES, inspectAllToolProfiles, inspectToolProfiles, JIRA_REQUIRED_SCOPES, migrateLegacyProfiles, MissingOAuthConfigError, missingScopes, ProfileNotFoundError, type ProfileTokenStatus, refreshActiveProfiles, tokenScopes, type ToolProfileStatus, useProfileForAllTools } from "./ProfileManager.js";
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,eAAe,EACf,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,KAAK,aAAa,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,KAAK,aAAa,EAClB,mBAAmB,EACnB,KAAK,aAAa,EAClB,mBAAmB,EACnB,KAAK,WAAW,EAChB,iBAAiB,EACjB,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,SAAS,EACd,eAAe,EAChB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,SAAS,EACT,eAAe,EACf,SAAS,EACV,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,eAAe,EACf,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,KAAK,aAAa,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,KAAK,aAAa,EAClB,mBAAmB,EACnB,KAAK,aAAa,EAClB,mBAAmB,EACnB,KAAK,WAAW,EAChB,iBAAiB,EACjB,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,SAAS,EACd,eAAe,EAChB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,SAAS,EACT,eAAe,EACf,SAAS,EACV,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,KAAK,WAAW,EAChB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,aAAa,EACb,uBAAuB,EACvB,WAAW,EACX,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,0BAA0B,EAC3B,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,eAAe,EACf,KAAK,uBAAuB,EAC5B,0BAA0B,EAC1B,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,qBAAqB,EACrB,WAAW,EACX,KAAK,iBAAiB,EACtB,qBAAqB,EACtB,MAAM,qBAAqB,CAAA"}
@@ -4,9 +4,13 @@
4
4
  * @module
5
5
  */
6
6
  // Config paths
7
- export { ensureConfigDir, getAuthPath, getConfigDir, getOAuthConfigPath, HomeDirectoryError, HomeDirectoryLive, HomeDirectoryTag, writeSecureFile } from "./ConfigPaths.js";
7
+ export { ensureConfigDir, getAuthPath, getConfigDir, getOAuthConfigPath, getProfilesPath, HomeDirectoryError, HomeDirectoryLive, HomeDirectoryTag, writeSecureFile } from "./ConfigPaths.js";
8
8
  // OAuth schemas
9
9
  export { AtlassianSiteSchema, AtlassianUserSchema, OAuthConfigSchema, OAuthTokenSchema, OAuthUserSchema } from "./OAuthSchemas.js";
10
10
  // Token storage
11
11
  export { deleteToken, FileSystemError, isTokenExpired, loadOAuthConfig, loadToken, saveOAuthConfig, saveToken } from "./TokenStorage.js";
12
+ // Auth profiles
13
+ export { AuthProfileSchema, AuthProfilesFileSchema, deleteActiveProfile, deleteProfile, deleteProfileBySelector, findProfile, loadActiveProfile, loadActiveProfileToken, loadProfiles, profileFromToken, profileIdFromToken, profileNameFromToken, saveProfiles, saveProfileToken, setActiveProfile, setActiveProfileBySelector } from "./AuthProfiles.js";
14
+ // Unified profile manager
15
+ export { ATLASSIAN_TOOLS, CONFLUENCE_REQUIRED_SCOPES, inspectAllToolProfiles, inspectToolProfiles, JIRA_REQUIRED_SCOPES, migrateLegacyProfiles, MissingOAuthConfigError, missingScopes, ProfileNotFoundError, refreshActiveProfiles, tokenScopes, useProfileForAllTools } from "./ProfileManager.js";
12
16
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAe;AACf,OAAO,EACL,eAAe,EACf,WAAW,EACX,YAAY,EACZ,kBAAkB,EAElB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAEzB,gBAAgB;AAChB,OAAO,EAEL,mBAAmB,EAEnB,mBAAmB,EAEnB,iBAAiB,EAEjB,gBAAgB,EAEhB,eAAe,EAChB,MAAM,mBAAmB,CAAA;AAE1B,gBAAgB;AAChB,OAAO,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,SAAS,EACT,eAAe,EACf,SAAS,EACV,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAe;AACf,OAAO,EACL,eAAe,EACf,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,eAAe,EAEf,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAEzB,gBAAgB;AAChB,OAAO,EAEL,mBAAmB,EAEnB,mBAAmB,EAEnB,iBAAiB,EAEjB,gBAAgB,EAEhB,eAAe,EAChB,MAAM,mBAAmB,CAAA;AAE1B,gBAAgB;AAChB,OAAO,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,SAAS,EACT,eAAe,EACf,SAAS,EACV,MAAM,mBAAmB,CAAA;AAE1B,gBAAgB;AAChB,OAAO,EAEL,iBAAiB,EAEjB,sBAAsB,EACtB,mBAAmB,EACnB,aAAa,EACb,uBAAuB,EACvB,WAAW,EACX,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,0BAA0B,EAC3B,MAAM,mBAAmB,CAAA;AAE1B,0BAA0B;AAC1B,OAAO,EACL,eAAe,EAEf,0BAA0B,EAC1B,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EAEpB,qBAAqB,EACrB,WAAW,EAEX,qBAAqB,EACtB,MAAM,qBAAqB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knpkv/atlassian-common",
3
- "version": "0.3.0",
3
+ "version": "1.0.0",
4
4
  "description": "Shared utilities for Atlassian tools (AST, serializers, auth, config)",
5
5
  "license": "MIT",
6
6
  "author": "knpkv",
@@ -41,6 +41,10 @@
41
41
  "./config": {
42
42
  "import": "./dist/config/index.js",
43
43
  "types": "./dist/config/index.d.ts"
44
+ },
45
+ "./profile-manager": {
46
+ "import": "./dist/config/ProfileManager.js",
47
+ "types": "./dist/config/ProfileManager.d.ts"
44
48
  }
45
49
  },
46
50
  "publishConfig": {
@@ -53,7 +57,8 @@
53
57
  "remark-gfm": "^4.0.1",
54
58
  "remark-parse": "^11.0.0",
55
59
  "remark-stringify": "^11.0.0",
56
- "unified": "^11.0.5"
60
+ "unified": "^11.0.5",
61
+ "@effect/platform-node": "4.0.0-beta.87"
57
62
  },
58
63
  "devDependencies": {
59
64
  "@effect/platform-node": "4.0.0-beta.87",
@@ -72,8 +77,11 @@
72
77
  "ast",
73
78
  "markdown"
74
79
  ],
80
+ "bin": {
81
+ "atlassian": "./dist/bin.js"
82
+ },
75
83
  "scripts": {
76
- "build": "tsc",
84
+ "build": "tsc -b --force && chmod +x dist/bin.js",
77
85
  "clean": "rimraf dist dist-test .tsbuildinfo",
78
86
  "test": "vitest run",
79
87
  "test:watch": "vitest",
package/src/Hash.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * **Mental model**
5
5
  *
6
- * - **Service-backed crypto**: {@link hashContent} and {@link hashBuffer} use
7
- * the `Crypto` service from Effect context, so applications provide the
6
+ * - **Service-backed cryptography**: {@link hashContent} and {@link hashBuffer}
7
+ * use the `Crypto` service from Effect context, so applications provide the
8
8
  * platform implementation at the runtime edge.
9
9
  *
10
10
  * **Common tasks**
@@ -27,8 +27,8 @@ const digestSha256 = (
27
27
  bytes: Uint8Array
28
28
  ): Effect.Effect<ContentHash, PlatformError.PlatformError, Crypto.Crypto> =>
29
29
  Effect.gen(function*() {
30
- const crypto = yield* Crypto.Crypto
31
- const digest = yield* crypto.digest("SHA-256", bytes)
30
+ const cryptoService = yield* Crypto.Crypto
31
+ const digest = yield* cryptoService.digest("SHA-256", bytes)
32
32
  return ContentHash(Encoding.encodeHex(digest))
33
33
  })
34
34
 
@@ -41,8 +41,8 @@ const digestSha256 = (
41
41
  * import * as Effect from "effect/Effect"
42
42
  * import { hashContent } from "@knpkv/atlassian-common"
43
43
  *
44
- * declare const crypto: Crypto.Crypto
45
- * const hash = Effect.runSync(hashContent("hello world").pipe(Effect.provideService(Crypto.Crypto, crypto)))
44
+ * declare const cryptoService: Crypto.Crypto
45
+ * const hash = Effect.runSync(hashContent("hello world").pipe(Effect.provideService(Crypto.Crypto, cryptoService)))
46
46
  * // => "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
47
47
  * ```
48
48
  *
@@ -12,8 +12,10 @@
12
12
  *
13
13
  * @module
14
14
  */
15
+ import * as Crypto from "effect/Crypto"
15
16
  import * as Effect from "effect/Effect"
16
17
  import * as Encoding from "effect/Encoding"
18
+ import type * as PlatformError from "effect/PlatformError"
17
19
 
18
20
  /**
19
21
  * OAuth2 authorization endpoint.
@@ -120,23 +122,28 @@ export const buildAuthUrl = (options: BuildAuthUrlOptions): string => {
120
122
 
121
123
  /**
122
124
  * Generate a cryptographically random PKCE code verifier (RFC 7636).
123
- * Uses Web Crypto API (available in Node 18+, Deno, browsers).
125
+ * Uses Effect's platform Crypto service.
124
126
  *
125
127
  * @category PKCE
126
128
  */
127
- export const generateCodeVerifier = (): string => {
128
- const bytes = new Uint8Array(32)
129
- globalThis.crypto.getRandomValues(bytes)
130
- return Encoding.encodeBase64Url(bytes)
131
- }
129
+ export const generateCodeVerifier = (): Effect.Effect<string, PlatformError.PlatformError, Crypto.Crypto> =>
130
+ Effect.gen(function*() {
131
+ const cryptoService = yield* Crypto.Crypto
132
+ const bytes = yield* cryptoService.randomBytes(32)
133
+ return Encoding.encodeBase64Url(bytes)
134
+ })
132
135
 
133
136
  /**
134
137
  * Compute S256 code challenge from a code verifier (RFC 7636).
135
- * Uses Web Crypto `subtle.digest` — returns Effect since digest is async.
138
+ * Uses Effect's platform Crypto service.
136
139
  *
137
140
  * @category PKCE
138
141
  */
139
- export const computeCodeChallenge = (verifier: string): Effect.Effect<string> =>
140
- Effect.promise(() => globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier))).pipe(
141
- Effect.map((hash) => Encoding.encodeBase64Url(new Uint8Array(hash)))
142
- )
142
+ export const computeCodeChallenge = (
143
+ verifier: string
144
+ ): Effect.Effect<string, PlatformError.PlatformError, Crypto.Crypto> =>
145
+ Effect.gen(function*() {
146
+ const cryptoService = yield* Crypto.Crypto
147
+ const hash = yield* cryptoService.digest("SHA-256", new TextEncoder().encode(verifier))
148
+ return Encoding.encodeBase64Url(hash)
149
+ })
@@ -16,6 +16,7 @@
16
16
  * @module
17
17
  */
18
18
  import * as Data from "effect/Data"
19
+ import * as Predicate from "effect/Predicate"
19
20
 
20
21
  /**
21
22
  * OAuth flow step for error context.
@@ -48,12 +49,12 @@ export class OAuthError extends Data.TaggedError("OAuthError")<{
48
49
  readonly cause?: unknown
49
50
  }> {
50
51
  override get message(): string {
51
- if (this.cause instanceof Error) {
52
- return `OAuth ${this.step} failed: ${this.cause.message}`
53
- }
54
52
  if (typeof this.cause === "string") {
55
53
  return `OAuth ${this.step} failed: ${this.cause}`
56
54
  }
55
+ if (Predicate.hasProperty(this.cause, "message")) {
56
+ return `OAuth ${this.step} failed: ${String(this.cause.message)}`
57
+ }
57
58
  return `OAuth ${this.step} failed`
58
59
  }
59
60
  }
@@ -18,6 +18,7 @@
18
18
  *
19
19
  * @module
20
20
  */
21
+ import * as Clock from "effect/Clock"
21
22
  import * as Effect from "effect/Effect"
22
23
  import * as Schema from "effect/Schema"
23
24
  import { HttpClient, HttpClientRequest } from "effect/unstable/http"
@@ -199,12 +200,13 @@ export const refreshToken = (
199
200
  const tokenResponse = yield* Schema.decodeUnknownEffect(TokenResponseSchema)(body).pipe(
200
201
  Effect.mapError((cause) => new OAuthError({ step: "refresh", cause }))
201
202
  )
203
+ const nowMs = yield* Clock.currentTimeMillis
202
204
 
203
205
  return {
204
206
  ...token,
205
207
  access_token: tokenResponse.access_token,
206
208
  refresh_token: tokenResponse.refresh_token,
207
- expires_at: Date.now() + tokenResponse.expires_in * 1000,
209
+ expires_at: nowMs + tokenResponse.expires_in * 1000,
208
210
  scope: tokenResponse.scope
209
211
  }
210
212
  })
package/src/auth/uuid.ts CHANGED
@@ -1,14 +1,20 @@
1
1
  /**
2
- * Cryptographic UUID v4 generation via Web Crypto API.
2
+ * Cryptographic UUID v4 generation via Effect's platform Crypto service.
3
3
  *
4
4
  * @internal
5
5
  */
6
+ import * as Crypto from "effect/Crypto"
6
7
  import * as Effect from "effect/Effect"
8
+ import type * as PlatformError from "effect/PlatformError"
7
9
 
8
10
  /**
9
11
  * Generate a cryptographically secure UUID v4.
10
- * Uses Web Crypto API randomUUID (Node.js 19+, all modern browsers).
12
+ * Uses Effect's platform Crypto service.
11
13
  *
12
14
  * @category Utilities
13
15
  */
14
- export const generateUUID = (): Effect.Effect<string> => Effect.sync(() => globalThis.crypto.randomUUID())
16
+ export const generateUUID = (): Effect.Effect<string, PlatformError.PlatformError, Crypto.Crypto> =>
17
+ Effect.gen(function*() {
18
+ const cryptoService = yield* Crypto.Crypto
19
+ return yield* cryptoService.randomUUIDv4
20
+ })