@atlassian-dc-mcp/common 0.16.0 → 0.17.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 (106) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/build/__tests__/runtime-config.test.js +65 -14
  3. package/build/__tests__/runtime-config.test.js.map +1 -1
  4. package/build/__tests__/setup-cli.test.d.ts +2 -0
  5. package/build/__tests__/setup-cli.test.d.ts.map +1 -0
  6. package/build/__tests__/setup-cli.test.js +166 -0
  7. package/build/__tests__/setup-cli.test.js.map +1 -0
  8. package/build/config/__tests__/registry.test.d.ts +2 -0
  9. package/build/config/__tests__/registry.test.d.ts.map +1 -0
  10. package/build/config/__tests__/registry.test.js +105 -0
  11. package/build/config/__tests__/registry.test.js.map +1 -0
  12. package/build/config/__tests__/resolve-base.test.d.ts +2 -0
  13. package/build/config/__tests__/resolve-base.test.d.ts.map +1 -0
  14. package/build/config/__tests__/resolve-base.test.js +89 -0
  15. package/build/config/__tests__/resolve-base.test.js.map +1 -0
  16. package/build/config/__tests__/sources/env-file.test.d.ts +2 -0
  17. package/build/config/__tests__/sources/env-file.test.d.ts.map +1 -0
  18. package/build/config/__tests__/sources/env-file.test.js +93 -0
  19. package/build/config/__tests__/sources/env-file.test.js.map +1 -0
  20. package/build/config/__tests__/sources/home-file.test.d.ts +2 -0
  21. package/build/config/__tests__/sources/home-file.test.d.ts.map +1 -0
  22. package/build/config/__tests__/sources/home-file.test.js +114 -0
  23. package/build/config/__tests__/sources/home-file.test.js.map +1 -0
  24. package/build/config/__tests__/sources/macos-keychain.test.d.ts +2 -0
  25. package/build/config/__tests__/sources/macos-keychain.test.d.ts.map +1 -0
  26. package/build/config/__tests__/sources/macos-keychain.test.js +109 -0
  27. package/build/config/__tests__/sources/macos-keychain.test.js.map +1 -0
  28. package/build/config/__tests__/sources/process-env.test.d.ts +2 -0
  29. package/build/config/__tests__/sources/process-env.test.d.ts.map +1 -0
  30. package/build/config/__tests__/sources/process-env.test.js +51 -0
  31. package/build/config/__tests__/sources/process-env.test.js.map +1 -0
  32. package/build/config/index.d.ts +9 -0
  33. package/build/config/index.d.ts.map +1 -0
  34. package/build/config/index.js +9 -0
  35. package/build/config/index.js.map +1 -0
  36. package/build/config/registry.d.ts +26 -0
  37. package/build/config/registry.d.ts.map +1 -0
  38. package/build/config/registry.js +51 -0
  39. package/build/config/registry.js.map +1 -0
  40. package/build/config/resolve-base.d.ts +8 -0
  41. package/build/config/resolve-base.d.ts.map +1 -0
  42. package/build/config/resolve-base.js +31 -0
  43. package/build/config/resolve-base.js.map +1 -0
  44. package/build/config/runtime-config.d.ts +14 -0
  45. package/build/config/runtime-config.d.ts.map +1 -0
  46. package/build/config/runtime-config.js +41 -0
  47. package/build/config/runtime-config.js.map +1 -0
  48. package/build/config/source.d.ts +28 -0
  49. package/build/config/source.d.ts.map +1 -0
  50. package/build/config/source.js +11 -0
  51. package/build/config/source.js.map +1 -0
  52. package/build/config/sources/dotenv-file-cache.d.ts +12 -0
  53. package/build/config/sources/dotenv-file-cache.d.ts.map +1 -0
  54. package/build/config/sources/dotenv-file-cache.js +41 -0
  55. package/build/config/sources/dotenv-file-cache.js.map +1 -0
  56. package/build/config/sources/env-file.d.ts +16 -0
  57. package/build/config/sources/env-file.d.ts.map +1 -0
  58. package/build/config/sources/env-file.js +48 -0
  59. package/build/config/sources/env-file.js.map +1 -0
  60. package/build/config/sources/home-file.d.ts +19 -0
  61. package/build/config/sources/home-file.d.ts.map +1 -0
  62. package/build/config/sources/home-file.js +102 -0
  63. package/build/config/sources/home-file.js.map +1 -0
  64. package/build/config/sources/macos-keychain.d.ts +26 -0
  65. package/build/config/sources/macos-keychain.d.ts.map +1 -0
  66. package/build/config/sources/macos-keychain.js +88 -0
  67. package/build/config/sources/macos-keychain.js.map +1 -0
  68. package/build/config/sources/process-env.d.ts +8 -0
  69. package/build/config/sources/process-env.d.ts.map +1 -0
  70. package/build/config/sources/process-env.js +12 -0
  71. package/build/config/sources/process-env.js.map +1 -0
  72. package/build/index.d.ts +2 -1
  73. package/build/index.d.ts.map +1 -1
  74. package/build/index.js +2 -1
  75. package/build/index.js.map +1 -1
  76. package/build/setup-cli.d.ts +25 -0
  77. package/build/setup-cli.d.ts.map +1 -0
  78. package/build/setup-cli.js +215 -0
  79. package/build/setup-cli.js.map +1 -0
  80. package/package.json +5 -4
  81. package/src/__tests__/runtime-config.test.ts +75 -27
  82. package/src/__tests__/setup-cli.test.ts +175 -0
  83. package/src/config/__tests__/registry.test.ts +118 -0
  84. package/src/config/__tests__/resolve-base.test.ts +101 -0
  85. package/src/config/__tests__/sources/env-file.test.ts +113 -0
  86. package/src/config/__tests__/sources/home-file.test.ts +129 -0
  87. package/src/config/__tests__/sources/macos-keychain.test.ts +136 -0
  88. package/src/config/__tests__/sources/process-env.test.ts +59 -0
  89. package/src/config/index.ts +8 -0
  90. package/src/config/registry.ts +79 -0
  91. package/src/config/resolve-base.ts +43 -0
  92. package/src/config/runtime-config.ts +60 -0
  93. package/src/config/source.ts +37 -0
  94. package/src/config/sources/dotenv-file-cache.ts +54 -0
  95. package/src/config/sources/env-file.ts +61 -0
  96. package/src/config/sources/home-file.ts +121 -0
  97. package/src/config/sources/macos-keychain.ts +117 -0
  98. package/src/config/sources/process-env.ts +15 -0
  99. package/src/index.ts +2 -1
  100. package/src/setup-cli.ts +308 -0
  101. package/tsconfig.tsbuildinfo +1 -1
  102. package/build/runtime-config.d.ts +0 -14
  103. package/build/runtime-config.d.ts.map +0 -1
  104. package/build/runtime-config.js +0 -123
  105. package/build/runtime-config.js.map +0 -1
  106. package/src/runtime-config.ts +0 -176
@@ -0,0 +1,93 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { EnvFileSource, ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR } from '../../sources/env-file.js';
5
+ const JIRA = {
6
+ id: 'jira',
7
+ envVars: {
8
+ host: 'JIRA_HOST',
9
+ apiBasePath: 'JIRA_API_BASE_PATH',
10
+ token: 'JIRA_API_TOKEN',
11
+ defaultPageSize: 'JIRA_DEFAULT_PAGE_SIZE',
12
+ },
13
+ };
14
+ const BITBUCKET = {
15
+ id: 'bitbucket',
16
+ envVars: {
17
+ host: 'BITBUCKET_HOST',
18
+ apiBasePath: 'BITBUCKET_API_BASE_PATH',
19
+ token: 'BITBUCKET_API_TOKEN',
20
+ defaultPageSize: 'BITBUCKET_DEFAULT_PAGE_SIZE',
21
+ },
22
+ };
23
+ describe('EnvFileSource', () => {
24
+ const originalEnv = process.env;
25
+ let tempDir;
26
+ beforeEach(() => {
27
+ process.env = { ...originalEnv };
28
+ delete process.env[ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR];
29
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'env-file-src-'));
30
+ });
31
+ afterEach(() => {
32
+ fs.rmSync(tempDir, { recursive: true, force: true });
33
+ });
34
+ afterAll(() => {
35
+ process.env = originalEnv;
36
+ });
37
+ it('reads an explicit shared config file', () => {
38
+ const filePath = path.join(tempDir, 'shared.env');
39
+ fs.writeFileSync(filePath, 'JIRA_HOST=file-host\nJIRA_API_TOKEN=file-token\n');
40
+ process.env[ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR] = filePath;
41
+ const source = new EnvFileSource();
42
+ source.initialize({ cwd: tempDir });
43
+ expect(source.read(JIRA, 'host')).toBe('file-host');
44
+ expect(source.read(JIRA, 'token')).toBe('file-token');
45
+ });
46
+ it('reads cwd/.env when no explicit file is configured', () => {
47
+ fs.writeFileSync(path.join(tempDir, '.env'), 'BITBUCKET_HOST=cwd-host\n');
48
+ const source = new EnvFileSource();
49
+ source.initialize({ cwd: tempDir });
50
+ expect(source.read(BITBUCKET, 'host')).toBe('cwd-host');
51
+ });
52
+ it('throws when explicit file is relative', () => {
53
+ process.env[ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR] = 'relative/shared.env';
54
+ const source = new EnvFileSource();
55
+ expect(() => source.initialize({ cwd: tempDir })).toThrow(/must be an absolute path/);
56
+ });
57
+ it('throws when explicit file is missing', () => {
58
+ const missing = path.join(tempDir, 'missing.env');
59
+ process.env[ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR] = missing;
60
+ const source = new EnvFileSource();
61
+ expect(() => source.initialize({ cwd: tempDir })).toThrow(`${ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR} points to a missing file: ${missing}`);
62
+ });
63
+ it('revalidates cache when mtime changes', () => {
64
+ const filePath = path.join(tempDir, 'shared.env');
65
+ fs.writeFileSync(filePath, 'JIRA_API_TOKEN=token-a\n');
66
+ const initial = new Date('2026-01-01T00:00:00.000Z');
67
+ fs.utimesSync(filePath, initial, initial);
68
+ process.env[ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR] = filePath;
69
+ const source = new EnvFileSource();
70
+ source.initialize({ cwd: tempDir });
71
+ expect(source.read(JIRA, 'token')).toBe('token-a');
72
+ fs.writeFileSync(filePath, 'JIRA_API_TOKEN=token-b\n');
73
+ const updated = new Date('2026-01-01T00:00:01.000Z');
74
+ fs.utimesSync(filePath, updated, updated);
75
+ expect(source.read(JIRA, 'token')).toBe('token-b');
76
+ });
77
+ it('returns empty object when cwd/.env is missing', () => {
78
+ const source = new EnvFileSource();
79
+ source.initialize({ cwd: tempDir });
80
+ expect(source.read(JIRA, 'host')).toBeUndefined();
81
+ });
82
+ it('evicts cache when an explicit file disappears after a successful read', () => {
83
+ const filePath = path.join(tempDir, 'shared.env');
84
+ fs.writeFileSync(filePath, 'JIRA_API_TOKEN=token-a\n');
85
+ process.env[ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR] = filePath;
86
+ const source = new EnvFileSource();
87
+ source.initialize({ cwd: tempDir });
88
+ expect(source.read(JIRA, 'token')).toBe('token-a');
89
+ fs.unlinkSync(filePath);
90
+ expect(() => source.read(JIRA, 'token')).toThrow(`${ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR} points to a missing file: ${filePath}`);
91
+ });
92
+ });
93
+ //# sourceMappingURL=env-file.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-file.test.js","sourceRoot":"","sources":["../../../../src/config/__tests__/sources/env-file.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=home-file.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"home-file.test.d.ts","sourceRoot":"","sources":["../../../../src/config/__tests__/sources/home-file.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,114 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { HomeFileSource, getHomeFilePath, HOME_DIR_NAME } from '../../sources/home-file.js';
5
+ const JIRA = {
6
+ id: 'jira',
7
+ envVars: {
8
+ host: 'JIRA_HOST',
9
+ apiBasePath: 'JIRA_API_BASE_PATH',
10
+ token: 'JIRA_API_TOKEN',
11
+ defaultPageSize: 'JIRA_DEFAULT_PAGE_SIZE',
12
+ },
13
+ };
14
+ const CONFLUENCE = {
15
+ id: 'confluence',
16
+ envVars: {
17
+ host: 'CONFLUENCE_HOST',
18
+ apiBasePath: 'CONFLUENCE_API_BASE_PATH',
19
+ token: 'CONFLUENCE_API_TOKEN',
20
+ defaultPageSize: 'CONFLUENCE_DEFAULT_PAGE_SIZE',
21
+ },
22
+ };
23
+ describe('HomeFileSource', () => {
24
+ let tempHome;
25
+ let homedirSpy;
26
+ beforeEach(() => {
27
+ tempHome = fs.mkdtempSync(path.join(os.tmpdir(), 'home-file-src-'));
28
+ homedirSpy = jest.spyOn(os, 'homedir').mockReturnValue(tempHome);
29
+ });
30
+ afterEach(() => {
31
+ homedirSpy.mockRestore();
32
+ fs.rmSync(tempHome, { recursive: true, force: true });
33
+ });
34
+ it('returns undefined when the home file does not exist', () => {
35
+ expect(new HomeFileSource().read(JIRA, 'host')).toBeUndefined();
36
+ });
37
+ it('writes values and reads them back', () => {
38
+ const source = new HomeFileSource();
39
+ source.write(JIRA, 'host', 'j-host');
40
+ source.write(JIRA, 'token', 'j-token');
41
+ expect(source.read(JIRA, 'host')).toBe('j-host');
42
+ expect(source.read(JIRA, 'token')).toBe('j-token');
43
+ });
44
+ it('writes files with mode 0600 on POSIX', () => {
45
+ if (process.platform === 'win32') {
46
+ return;
47
+ }
48
+ const source = new HomeFileSource();
49
+ source.write(JIRA, 'host', 'j-host');
50
+ const stat = fs.statSync(getHomeFilePath(JIRA));
51
+ expect(stat.mode & 0o777).toBe(0o600);
52
+ });
53
+ it('merge preserves unrelated keys', () => {
54
+ const filePath = getHomeFilePath(JIRA);
55
+ fs.mkdirSync(path.join(tempHome, HOME_DIR_NAME), { recursive: true });
56
+ fs.writeFileSync(filePath, 'JIRA_HOST=old\nUNRELATED_KEY=keep-me\n', { mode: 0o600 });
57
+ const source = new HomeFileSource();
58
+ source.write(JIRA, 'host', 'new');
59
+ const contents = fs.readFileSync(filePath, 'utf8');
60
+ expect(contents).toContain('JIRA_HOST=new');
61
+ expect(contents).toContain('UNRELATED_KEY=keep-me');
62
+ });
63
+ it('clear removes only the specified key', () => {
64
+ const source = new HomeFileSource();
65
+ source.write(JIRA, 'host', 'j-host');
66
+ source.write(JIRA, 'token', 'j-token');
67
+ source.clear(JIRA, 'token');
68
+ expect(source.read(JIRA, 'host')).toBe('j-host');
69
+ expect(source.read(JIRA, 'token')).toBeUndefined();
70
+ });
71
+ it('quotes values that contain whitespace', () => {
72
+ const source = new HomeFileSource();
73
+ source.write(JIRA, 'host', 'value with spaces');
74
+ const contents = fs.readFileSync(getHomeFilePath(JIRA), 'utf8');
75
+ expect(contents).toMatch(/JIRA_HOST="value with spaces"/);
76
+ expect(source.read(JIRA, 'host')).toBe('value with spaces');
77
+ });
78
+ it('stores each product in its own file', () => {
79
+ const source = new HomeFileSource();
80
+ source.write(JIRA, 'host', 'j-host');
81
+ source.write(CONFLUENCE, 'host', 'c-host');
82
+ expect(fs.existsSync(getHomeFilePath(JIRA))).toBe(true);
83
+ expect(fs.existsSync(getHomeFilePath(CONFLUENCE))).toBe(true);
84
+ expect(source.read(JIRA, 'host')).toBe('j-host');
85
+ expect(source.read(CONFLUENCE, 'host')).toBe('c-host');
86
+ });
87
+ it('evicts cache when the home file is deleted externally so writes do not merge stale values', () => {
88
+ const source = new HomeFileSource();
89
+ source.write(JIRA, 'host', 'stale-host');
90
+ expect(source.read(JIRA, 'host')).toBe('stale-host');
91
+ fs.unlinkSync(getHomeFilePath(JIRA));
92
+ expect(source.read(JIRA, 'host')).toBeUndefined();
93
+ source.write(JIRA, 'token', 'fresh-token');
94
+ const contents = fs.readFileSync(getHomeFilePath(JIRA), 'utf8');
95
+ expect(contents).not.toContain('stale-host');
96
+ expect(contents).toContain('JIRA_API_TOKEN=fresh-token');
97
+ });
98
+ it('removes the temp file if rename fails', () => {
99
+ const source = new HomeFileSource();
100
+ const renameSpy = jest.spyOn(fs, 'renameSync').mockImplementation(() => {
101
+ throw new Error('boom');
102
+ });
103
+ try {
104
+ expect(() => source.write(JIRA, 'host', 'x')).toThrow('boom');
105
+ const dir = path.join(tempHome, HOME_DIR_NAME);
106
+ const entries = fs.existsSync(dir) ? fs.readdirSync(dir) : [];
107
+ expect(entries.filter((e) => e.includes('.tmp-'))).toEqual([]);
108
+ }
109
+ finally {
110
+ renameSpy.mockRestore();
111
+ }
112
+ });
113
+ });
114
+ //# sourceMappingURL=home-file.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"home-file.test.js","sourceRoot":"","sources":["../../../../src/config/__tests__/sources/home-file.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=macos-keychain.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macos-keychain.test.d.ts","sourceRoot":"","sources":["../../../../src/config/__tests__/sources/macos-keychain.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,109 @@
1
+ import { MacosKeychainSource, SECURITY_BINARY } from '../../sources/macos-keychain.js';
2
+ const JIRA = {
3
+ id: 'jira',
4
+ envVars: {
5
+ host: 'JIRA_HOST',
6
+ apiBasePath: 'JIRA_API_BASE_PATH',
7
+ token: 'JIRA_API_TOKEN',
8
+ defaultPageSize: 'JIRA_DEFAULT_PAGE_SIZE',
9
+ },
10
+ };
11
+ function makeDeps(overrides = {}) {
12
+ return {
13
+ execFileSync: jest.fn(),
14
+ existsSync: jest.fn(() => true),
15
+ getPlatform: () => 'darwin',
16
+ ...overrides,
17
+ };
18
+ }
19
+ describe('MacosKeychainSource', () => {
20
+ it('isAvailable is true on darwin when binary exists', () => {
21
+ expect(new MacosKeychainSource(makeDeps()).isAvailable()).toBe(true);
22
+ });
23
+ it('isAvailable is false off darwin', () => {
24
+ const deps = makeDeps({ getPlatform: () => 'linux' });
25
+ expect(new MacosKeychainSource(deps).isAvailable()).toBe(false);
26
+ });
27
+ it('isAvailable is false when binary is missing', () => {
28
+ const deps = makeDeps({ existsSync: jest.fn(() => false) });
29
+ expect(new MacosKeychainSource(deps).isAvailable()).toBe(false);
30
+ });
31
+ it('read returns token on success and strips trailing newline', () => {
32
+ const execFileSync = jest.fn().mockReturnValueOnce('secret-token\n');
33
+ const deps = makeDeps({ execFileSync: execFileSync });
34
+ const source = new MacosKeychainSource(deps);
35
+ expect(source.read(JIRA, 'token')).toBe('secret-token');
36
+ expect(execFileSync).toHaveBeenCalledWith(SECURITY_BINARY, ['find-generic-password', '-s', 'atlassian-dc-mcp', '-a', 'jira-token', '-w'], expect.objectContaining({ encoding: 'utf8', timeout: 5000 }));
37
+ });
38
+ it('read returns undefined when security exits non-zero (not found)', () => {
39
+ const execFileSync = jest.fn().mockImplementationOnce(() => {
40
+ const err = new Error('not found');
41
+ err.status = 44;
42
+ throw err;
43
+ });
44
+ const source = new MacosKeychainSource(makeDeps({ execFileSync: execFileSync }));
45
+ expect(source.read(JIRA, 'token')).toBeUndefined();
46
+ });
47
+ it('read returns undefined when keychain is locked (non-44)', () => {
48
+ const execFileSync = jest.fn().mockImplementationOnce(() => {
49
+ const err = new Error('auth failed');
50
+ err.status = 128;
51
+ throw err;
52
+ });
53
+ const source = new MacosKeychainSource(makeDeps({ execFileSync: execFileSync }));
54
+ expect(source.read(JIRA, 'token')).toBeUndefined();
55
+ });
56
+ it('read returns undefined for non-token keys without invoking security', () => {
57
+ const execFileSync = jest.fn();
58
+ const source = new MacosKeychainSource(makeDeps({ execFileSync: execFileSync }));
59
+ expect(source.read(JIRA, 'host')).toBeUndefined();
60
+ expect(execFileSync).not.toHaveBeenCalled();
61
+ });
62
+ it('caches reads', () => {
63
+ const execFileSync = jest.fn().mockReturnValueOnce('cached\n');
64
+ const source = new MacosKeychainSource(makeDeps({ execFileSync: execFileSync }));
65
+ source.read(JIRA, 'token');
66
+ source.read(JIRA, 'token');
67
+ source.read(JIRA, 'token');
68
+ expect(execFileSync).toHaveBeenCalledTimes(1);
69
+ });
70
+ it('write uses -U flag', () => {
71
+ const execFileSync = jest.fn().mockReturnValueOnce('');
72
+ const source = new MacosKeychainSource(makeDeps({ execFileSync: execFileSync }));
73
+ source.write(JIRA, 'token', 'abc');
74
+ expect(execFileSync).toHaveBeenCalledWith(SECURITY_BINARY, ['add-generic-password', '-U', '-s', 'atlassian-dc-mcp', '-a', 'jira-token', '-w', 'abc'], expect.objectContaining({ encoding: 'utf8' }));
75
+ });
76
+ it('write throws when the key is not token', () => {
77
+ const execFileSync = jest.fn();
78
+ const source = new MacosKeychainSource(makeDeps({ execFileSync: execFileSync }));
79
+ expect(() => source.write(JIRA, 'host', 'x')).toThrow(/only stores the token/);
80
+ expect(execFileSync).not.toHaveBeenCalled();
81
+ });
82
+ it('round-trips a token containing shell metacharacters', () => {
83
+ const tricky = 'a\'b"c$d`e';
84
+ const execFileSync = jest
85
+ .fn()
86
+ .mockImplementationOnce(() => '')
87
+ .mockImplementationOnce(() => `${tricky}\n`);
88
+ const source = new MacosKeychainSource(makeDeps({ execFileSync: execFileSync }));
89
+ source.write(JIRA, 'token', tricky);
90
+ expect(source.read(JIRA, 'token')).toBe(tricky);
91
+ const writeArgs = execFileSync.mock.calls[0][1];
92
+ expect(writeArgs[writeArgs.length - 1]).toBe(tricky);
93
+ });
94
+ it('clear invokes delete-generic-password and caches undefined', () => {
95
+ const execFileSync = jest.fn().mockImplementationOnce(() => '');
96
+ const source = new MacosKeychainSource(makeDeps({ execFileSync: execFileSync }));
97
+ source.clear(JIRA, 'token');
98
+ expect(execFileSync).toHaveBeenCalledWith(SECURITY_BINARY, ['delete-generic-password', '-s', 'atlassian-dc-mcp', '-a', 'jira-token'], expect.any(Object));
99
+ expect(source.read(JIRA, 'token')).toBeUndefined();
100
+ });
101
+ it('clear swallows errors', () => {
102
+ const execFileSync = jest.fn().mockImplementationOnce(() => {
103
+ throw new Error('not found');
104
+ });
105
+ const source = new MacosKeychainSource(makeDeps({ execFileSync: execFileSync }));
106
+ expect(() => source.clear(JIRA, 'token')).not.toThrow();
107
+ });
108
+ });
109
+ //# sourceMappingURL=macos-keychain.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macos-keychain.test.js","sourceRoot":"","sources":["../../../../src/config/__tests__/sources/macos-keychain.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=process-env.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-env.test.d.ts","sourceRoot":"","sources":["../../../../src/config/__tests__/sources/process-env.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ import { ProcessEnvSource } from '../../sources/process-env.js';
2
+ const JIRA = {
3
+ id: 'jira',
4
+ envVars: {
5
+ host: 'JIRA_HOST',
6
+ apiBasePath: 'JIRA_API_BASE_PATH',
7
+ token: 'JIRA_API_TOKEN',
8
+ defaultPageSize: 'JIRA_DEFAULT_PAGE_SIZE',
9
+ },
10
+ };
11
+ const CONFLUENCE = {
12
+ id: 'confluence',
13
+ envVars: {
14
+ host: 'CONFLUENCE_HOST',
15
+ apiBasePath: 'CONFLUENCE_API_BASE_PATH',
16
+ token: 'CONFLUENCE_API_TOKEN',
17
+ defaultPageSize: 'CONFLUENCE_DEFAULT_PAGE_SIZE',
18
+ },
19
+ };
20
+ describe('ProcessEnvSource', () => {
21
+ const originalEnv = process.env;
22
+ beforeEach(() => {
23
+ process.env = { ...originalEnv };
24
+ delete process.env.JIRA_HOST;
25
+ delete process.env.JIRA_API_TOKEN;
26
+ delete process.env.CONFLUENCE_HOST;
27
+ });
28
+ afterAll(() => {
29
+ process.env = originalEnv;
30
+ });
31
+ it('maps product+key to the correct env var', () => {
32
+ process.env.JIRA_HOST = 'j-host';
33
+ process.env.JIRA_API_TOKEN = 'j-token';
34
+ process.env.CONFLUENCE_HOST = 'c-host';
35
+ const source = new ProcessEnvSource();
36
+ expect(source.read(JIRA, 'host')).toBe('j-host');
37
+ expect(source.read(JIRA, 'token')).toBe('j-token');
38
+ expect(source.read(CONFLUENCE, 'host')).toBe('c-host');
39
+ });
40
+ it('returns undefined for absent or whitespace-only values', () => {
41
+ const source = new ProcessEnvSource();
42
+ expect(source.read(JIRA, 'host')).toBeUndefined();
43
+ process.env.JIRA_HOST = ' ';
44
+ expect(source.read(JIRA, 'host')).toBeUndefined();
45
+ });
46
+ it('trims surrounding whitespace', () => {
47
+ process.env.JIRA_HOST = ' j-host ';
48
+ expect(new ProcessEnvSource().read(JIRA, 'host')).toBe('j-host');
49
+ });
50
+ });
51
+ //# sourceMappingURL=process-env.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-env.test.js","sourceRoot":"","sources":["../../../../src/config/__tests__/sources/process-env.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGhE,MAAM,IAAI,GAAsB;IAC9B,EAAE,EAAE,MAAM;IACV,OAAO,EAAE;QACP,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,oBAAoB;QACjC,KAAK,EAAE,gBAAgB;QACvB,eAAe,EAAE,wBAAwB;KAC1C;CACF,CAAC;AAEF,MAAM,UAAU,GAAsB;IACpC,EAAE,EAAE,YAAY;IAChB,OAAO,EAAE;QACP,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,0BAA0B;QACvC,KAAK,EAAE,sBAAsB;QAC7B,eAAe,EAAE,8BAA8B;KAChD;CACF,CAAC;AAEF,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;IAEhC,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;QAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAClC,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,GAAG,EAAE;QACZ,OAAO,CAAC,GAAG,GAAG,WAAW,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,SAAS,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,QAAQ,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,YAAY,CAAC;QACrC,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export * from './source.js';
2
+ export * from './registry.js';
3
+ export * from './runtime-config.js';
4
+ export * from './resolve-base.js';
5
+ export { ProcessEnvSource } from './sources/process-env.js';
6
+ export { EnvFileSource, ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR } from './sources/env-file.js';
7
+ export { HomeFileSource, getHomeFilePath, HOME_DIR_NAME } from './sources/home-file.js';
8
+ export { MacosKeychainSource, KEYCHAIN_SERVICE } from './sources/macos-keychain.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,oCAAoC,EAAE,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,9 @@
1
+ export * from './source.js';
2
+ export * from './registry.js';
3
+ export * from './runtime-config.js';
4
+ export * from './resolve-base.js';
5
+ export { ProcessEnvSource } from './sources/process-env.js';
6
+ export { EnvFileSource, ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR } from './sources/env-file.js';
7
+ export { HomeFileSource, getHomeFilePath, HOME_DIR_NAME } from './sources/home-file.js';
8
+ export { MacosKeychainSource, KEYCHAIN_SERVICE } from './sources/macos-keychain.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,oCAAoC,EAAE,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ConfigKey, ProductDefinition, ReadableSource, SourceLocation, WritableSource } from './source.js';
2
+ export interface ResolvedValue {
3
+ value: string | undefined;
4
+ from?: SourceLocation;
5
+ }
6
+ export interface ConfigRegistry {
7
+ readonly sources: readonly ReadableSource[];
8
+ initialize(options?: {
9
+ cwd?: string;
10
+ }): void;
11
+ resolve(product: ProductDefinition, key: ConfigKey): ResolvedValue;
12
+ locate(product: ProductDefinition, key: ConfigKey): SourceLocation[];
13
+ getWritableSource<T extends WritableSource>(predicate: (s: WritableSource) => s is T): T | undefined;
14
+ }
15
+ export declare class DefaultConfigRegistry implements ConfigRegistry {
16
+ readonly sources: readonly ReadableSource[];
17
+ constructor(sources: ReadableSource[]);
18
+ initialize(options?: {
19
+ cwd?: string;
20
+ }): void;
21
+ resolve(product: ProductDefinition, key: ConfigKey): ResolvedValue;
22
+ locate(product: ProductDefinition, key: ConfigKey): SourceLocation[];
23
+ getWritableSource<T extends WritableSource>(predicate: (s: WritableSource) => s is T): T | undefined;
24
+ }
25
+ export declare function buildDefaultRegistry(): DefaultConfigRegistry;
26
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/config/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,cAAc,EACf,MAAM,aAAa,CAAC;AAOrB,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,UAAU,CAAC,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7C,OAAO,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,SAAS,GAAG,aAAa,CAAC;IACnE,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,SAAS,GAAG,cAAc,EAAE,CAAC;IACrE,iBAAiB,CAAC,CAAC,SAAS,cAAc,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;CACtG;AAED,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;gBAEhC,OAAO,EAAE,cAAc,EAAE;IAIrC,UAAU,CAAC,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAM5C,OAAO,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,SAAS,GAAG,aAAa;IAUlE,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,SAAS,GAAG,cAAc,EAAE;IAUpE,iBAAiB,CAAC,CAAC,SAAS,cAAc,EACxC,SAAS,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,CAAC,IAAI,CAAC,GACvC,CAAC,GAAG,SAAS;CAQjB;AAED,wBAAgB,oBAAoB,IAAI,qBAAqB,CAO5D"}
@@ -0,0 +1,51 @@
1
+ import { isWritableSource } from './source.js';
2
+ import { ProcessEnvSource } from './sources/process-env.js';
3
+ import { EnvFileSource } from './sources/env-file.js';
4
+ import { HomeFileSource } from './sources/home-file.js';
5
+ import { MacosKeychainSource } from './sources/macos-keychain.js';
6
+ export class DefaultConfigRegistry {
7
+ sources;
8
+ constructor(sources) {
9
+ this.sources = [...sources].sort((a, b) => b.priority - a.priority);
10
+ }
11
+ initialize(options) {
12
+ for (const source of this.sources) {
13
+ source.initialize?.(options);
14
+ }
15
+ }
16
+ resolve(product, key) {
17
+ for (const source of this.sources) {
18
+ const value = source.read(product, key);
19
+ if (value !== undefined) {
20
+ return { value, from: { sourceId: source.id, detail: source.describe() } };
21
+ }
22
+ }
23
+ return { value: undefined };
24
+ }
25
+ locate(product, key) {
26
+ const locations = [];
27
+ for (const source of this.sources) {
28
+ if (source.read(product, key) !== undefined) {
29
+ locations.push({ sourceId: source.id, detail: source.describe() });
30
+ }
31
+ }
32
+ return locations;
33
+ }
34
+ getWritableSource(predicate) {
35
+ for (const source of this.sources) {
36
+ if (isWritableSource(source) && predicate(source)) {
37
+ return source;
38
+ }
39
+ }
40
+ return undefined;
41
+ }
42
+ }
43
+ export function buildDefaultRegistry() {
44
+ return new DefaultConfigRegistry([
45
+ new ProcessEnvSource(),
46
+ new EnvFileSource(),
47
+ new HomeFileSource(),
48
+ new MacosKeychainSource(),
49
+ ]);
50
+ }
51
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/config/registry.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAelE,MAAM,OAAO,qBAAqB;IACvB,OAAO,CAA4B;IAE5C,YAAY,OAAyB;QACnC,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IACtE,CAAC;IAED,UAAU,CAAC,OAA0B;QACnC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,OAAO,CAAC,OAA0B,EAAE,GAAc;QAChD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACxC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;YAC7E,CAAC;QACH,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,CAAC,OAA0B,EAAE,GAAc;QAC/C,MAAM,SAAS,GAAqB,EAAE,CAAC;QACvC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC5C,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,iBAAiB,CACf,SAAwC;QAExC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,gBAAgB,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClD,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,qBAAqB,CAAC;QAC/B,IAAI,gBAAgB,EAAE;QACtB,IAAI,aAAa,EAAE;QACnB,IAAI,cAAc,EAAE;QACpB,IAAI,mBAAmB,EAAE;KAC1B,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type ResolveOpenApiBaseOptions = {
2
+ host?: string;
3
+ apiBasePath?: string;
4
+ defaultBasePath: string;
5
+ strippableSuffixes?: readonly string[];
6
+ };
7
+ export declare function resolveOpenApiBase(options: ResolveOpenApiBaseOptions): string;
8
+ //# sourceMappingURL=resolve-base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-base.d.ts","sourceRoot":"","sources":["../../src/config/resolve-base.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC,CAAC;AAuBF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM,CAc7E"}
@@ -0,0 +1,31 @@
1
+ function normalizeHost(host) {
2
+ const withScheme = /^https?:\/\//i.test(host) ? host : `https://${host}`;
3
+ return withScheme.replace(/\/+$/, '');
4
+ }
5
+ function stripGeneratedSuffix(path, suffixes) {
6
+ for (const suffix of suffixes) {
7
+ const escaped = suffix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
8
+ const re = new RegExp(`${escaped}\\/?$`, 'i');
9
+ if (re.test(path)) {
10
+ return path.replace(re, '');
11
+ }
12
+ }
13
+ return path;
14
+ }
15
+ function normalizeBasePath(path, suffixes) {
16
+ const stripped = stripGeneratedSuffix(path, suffixes).replace(/\/+$/, '');
17
+ return stripped === '/' ? '' : stripped;
18
+ }
19
+ export function resolveOpenApiBase(options) {
20
+ const { host, apiBasePath, defaultBasePath, strippableSuffixes = [] } = options;
21
+ if (apiBasePath && /^https?:\/\//i.test(apiBasePath)) {
22
+ const url = new URL(apiBasePath);
23
+ return `${url.origin}${normalizeBasePath(url.pathname, strippableSuffixes)}`;
24
+ }
25
+ if (!host) {
26
+ throw new Error('host or apiBasePath must be provided');
27
+ }
28
+ const basePath = apiBasePath ? normalizeBasePath(apiBasePath, strippableSuffixes) : defaultBasePath;
29
+ return `${normalizeHost(host)}${basePath}`;
30
+ }
31
+ //# sourceMappingURL=resolve-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-base.js","sourceRoot":"","sources":["../../src/config/resolve-base.ts"],"names":[],"mappings":"AAOA,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC;IACzE,OAAO,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY,EAAE,QAA2B;IACrE,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QAC9D,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,GAAG,OAAO,OAAO,EAAE,GAAG,CAAC,CAAC;QAC9C,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,QAA2B;IAClE,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1E,OAAO,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAkC;IACnE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAEhF,IAAI,WAAW,IAAI,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;QACjC,OAAO,GAAG,GAAG,CAAC,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE,CAAC;IAC/E,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,iBAAiB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;IACpG,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { ProductDefinition } from './source.js';
2
+ export type ProductRuntimeConfig = {
3
+ host?: string;
4
+ apiBasePath?: string;
5
+ token?: string;
6
+ defaultPageSize: number;
7
+ };
8
+ export { ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR } from './sources/env-file.js';
9
+ export declare function initializeRuntimeConfig(options?: {
10
+ cwd?: string;
11
+ }): void;
12
+ export declare function getProductRuntimeConfig(product: ProductDefinition): ProductRuntimeConfig;
13
+ export declare function validateProductRuntimeConfig(product: ProductDefinition): string[];
14
+ //# sourceMappingURL=runtime-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-config.d.ts","sourceRoot":"","sources":["../../src/config/runtime-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIhE,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,OAAO,EAAE,oCAAoC,EAAE,MAAM,uBAAuB,CAAC;AAI7E,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAExE;AAkBD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,GAAG,oBAAoB,CAQxF;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAajF"}