@atlassian-dc-mcp/common 0.16.0 → 0.17.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 (96) hide show
  1. package/CHANGELOG.md +11 -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__/sources/env-file.test.d.ts +2 -0
  13. package/build/config/__tests__/sources/env-file.test.d.ts.map +1 -0
  14. package/build/config/__tests__/sources/env-file.test.js +93 -0
  15. package/build/config/__tests__/sources/env-file.test.js.map +1 -0
  16. package/build/config/__tests__/sources/home-file.test.d.ts +2 -0
  17. package/build/config/__tests__/sources/home-file.test.d.ts.map +1 -0
  18. package/build/config/__tests__/sources/home-file.test.js +114 -0
  19. package/build/config/__tests__/sources/home-file.test.js.map +1 -0
  20. package/build/config/__tests__/sources/macos-keychain.test.d.ts +2 -0
  21. package/build/config/__tests__/sources/macos-keychain.test.d.ts.map +1 -0
  22. package/build/config/__tests__/sources/macos-keychain.test.js +109 -0
  23. package/build/config/__tests__/sources/macos-keychain.test.js.map +1 -0
  24. package/build/config/__tests__/sources/process-env.test.d.ts +2 -0
  25. package/build/config/__tests__/sources/process-env.test.d.ts.map +1 -0
  26. package/build/config/__tests__/sources/process-env.test.js +51 -0
  27. package/build/config/__tests__/sources/process-env.test.js.map +1 -0
  28. package/build/config/index.d.ts +8 -0
  29. package/build/config/index.d.ts.map +1 -0
  30. package/build/config/index.js +8 -0
  31. package/build/config/index.js.map +1 -0
  32. package/build/config/registry.d.ts +26 -0
  33. package/build/config/registry.d.ts.map +1 -0
  34. package/build/config/registry.js +51 -0
  35. package/build/config/registry.js.map +1 -0
  36. package/build/config/runtime-config.d.ts +14 -0
  37. package/build/config/runtime-config.d.ts.map +1 -0
  38. package/build/config/runtime-config.js +41 -0
  39. package/build/config/runtime-config.js.map +1 -0
  40. package/build/config/source.d.ts +28 -0
  41. package/build/config/source.d.ts.map +1 -0
  42. package/build/config/source.js +11 -0
  43. package/build/config/source.js.map +1 -0
  44. package/build/config/sources/dotenv-file-cache.d.ts +12 -0
  45. package/build/config/sources/dotenv-file-cache.d.ts.map +1 -0
  46. package/build/config/sources/dotenv-file-cache.js +41 -0
  47. package/build/config/sources/dotenv-file-cache.js.map +1 -0
  48. package/build/config/sources/env-file.d.ts +16 -0
  49. package/build/config/sources/env-file.d.ts.map +1 -0
  50. package/build/config/sources/env-file.js +48 -0
  51. package/build/config/sources/env-file.js.map +1 -0
  52. package/build/config/sources/home-file.d.ts +19 -0
  53. package/build/config/sources/home-file.d.ts.map +1 -0
  54. package/build/config/sources/home-file.js +102 -0
  55. package/build/config/sources/home-file.js.map +1 -0
  56. package/build/config/sources/macos-keychain.d.ts +26 -0
  57. package/build/config/sources/macos-keychain.d.ts.map +1 -0
  58. package/build/config/sources/macos-keychain.js +88 -0
  59. package/build/config/sources/macos-keychain.js.map +1 -0
  60. package/build/config/sources/process-env.d.ts +8 -0
  61. package/build/config/sources/process-env.d.ts.map +1 -0
  62. package/build/config/sources/process-env.js +12 -0
  63. package/build/config/sources/process-env.js.map +1 -0
  64. package/build/index.d.ts +2 -1
  65. package/build/index.d.ts.map +1 -1
  66. package/build/index.js +2 -1
  67. package/build/index.js.map +1 -1
  68. package/build/setup-cli.d.ts +25 -0
  69. package/build/setup-cli.d.ts.map +1 -0
  70. package/build/setup-cli.js +215 -0
  71. package/build/setup-cli.js.map +1 -0
  72. package/package.json +5 -4
  73. package/src/__tests__/runtime-config.test.ts +75 -27
  74. package/src/__tests__/setup-cli.test.ts +175 -0
  75. package/src/config/__tests__/registry.test.ts +118 -0
  76. package/src/config/__tests__/sources/env-file.test.ts +113 -0
  77. package/src/config/__tests__/sources/home-file.test.ts +129 -0
  78. package/src/config/__tests__/sources/macos-keychain.test.ts +136 -0
  79. package/src/config/__tests__/sources/process-env.test.ts +59 -0
  80. package/src/config/index.ts +7 -0
  81. package/src/config/registry.ts +79 -0
  82. package/src/config/runtime-config.ts +60 -0
  83. package/src/config/source.ts +37 -0
  84. package/src/config/sources/dotenv-file-cache.ts +54 -0
  85. package/src/config/sources/env-file.ts +61 -0
  86. package/src/config/sources/home-file.ts +121 -0
  87. package/src/config/sources/macos-keychain.ts +117 -0
  88. package/src/config/sources/process-env.ts +15 -0
  89. package/src/index.ts +2 -1
  90. package/src/setup-cli.ts +308 -0
  91. package/tsconfig.tsbuildinfo +1 -1
  92. package/build/runtime-config.d.ts +0 -14
  93. package/build/runtime-config.d.ts.map +0 -1
  94. package/build/runtime-config.js +0 -123
  95. package/build/runtime-config.js.map +0 -1
  96. package/src/runtime-config.ts +0 -176
@@ -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,8 @@
1
+ export * from './source.js';
2
+ export * from './registry.js';
3
+ export * from './runtime-config.js';
4
+ export { ProcessEnvSource } from './sources/process-env.js';
5
+ export { EnvFileSource, ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR } from './sources/env-file.js';
6
+ export { HomeFileSource, getHomeFilePath, HOME_DIR_NAME } from './sources/home-file.js';
7
+ export { MacosKeychainSource, KEYCHAIN_SERVICE } from './sources/macos-keychain.js';
8
+ //# 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,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,8 @@
1
+ export * from './source.js';
2
+ export * from './registry.js';
3
+ export * from './runtime-config.js';
4
+ export { ProcessEnvSource } from './sources/process-env.js';
5
+ export { EnvFileSource, ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR } from './sources/env-file.js';
6
+ export { HomeFileSource, getHomeFilePath, HOME_DIR_NAME } from './sources/home-file.js';
7
+ export { MacosKeychainSource, KEYCHAIN_SERVICE } from './sources/macos-keychain.js';
8
+ //# 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,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,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"}
@@ -0,0 +1,41 @@
1
+ import { buildDefaultRegistry } from './registry.js';
2
+ const FALLBACK_PAGE_SIZE = 25;
3
+ export { ATLASSIAN_DC_MCP_CONFIG_FILE_ENV_VAR } from './sources/env-file.js';
4
+ let registry = buildDefaultRegistry();
5
+ export function initializeRuntimeConfig(options) {
6
+ registry.initialize(options);
7
+ }
8
+ function resolveString(product, key) {
9
+ return registry.resolve(product, key).value;
10
+ }
11
+ function parsePositiveInteger(value) {
12
+ if (!value) {
13
+ return undefined;
14
+ }
15
+ const trimmed = value.trim();
16
+ if (!/^\d+$/.test(trimmed)) {
17
+ return undefined;
18
+ }
19
+ const parsed = Number.parseInt(trimmed, 10);
20
+ return parsed > 0 ? parsed : undefined;
21
+ }
22
+ export function getProductRuntimeConfig(product) {
23
+ return {
24
+ host: resolveString(product, 'host'),
25
+ apiBasePath: resolveString(product, 'apiBasePath'),
26
+ token: resolveString(product, 'token'),
27
+ defaultPageSize: parsePositiveInteger(resolveString(product, 'defaultPageSize')) ?? FALLBACK_PAGE_SIZE,
28
+ };
29
+ }
30
+ export function validateProductRuntimeConfig(product) {
31
+ const config = getProductRuntimeConfig(product);
32
+ const missing = [];
33
+ if (!config.token) {
34
+ missing.push(product.envVars.token);
35
+ }
36
+ if (!config.host && !config.apiBasePath) {
37
+ missing.push(`${product.envVars.host} or ${product.envVars.apiBasePath}`);
38
+ }
39
+ return missing;
40
+ }
41
+ //# sourceMappingURL=runtime-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-config.js","sourceRoot":"","sources":["../../src/config/runtime-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAuB,MAAM,eAAe,CAAC;AAG1E,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAS9B,OAAO,EAAE,oCAAoC,EAAE,MAAM,uBAAuB,CAAC;AAE7E,IAAI,QAAQ,GAAmB,oBAAoB,EAAE,CAAC;AAEtD,MAAM,UAAU,uBAAuB,CAAC,OAA0B;IAChE,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,aAAa,CAAC,OAA0B,EAAE,GAAc;IAC/D,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC;AAC9C,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAyB;IACrD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAA0B;IAChE,OAAO;QACL,IAAI,EAAE,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC;QACpC,WAAW,EAAE,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC;QAClD,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC;QACtC,eAAe,EACb,oBAAoB,CAAC,aAAa,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,IAAI,kBAAkB;KACxF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAA0B;IACrE,MAAM,MAAM,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,28 @@
1
+ export type ConfigKey = 'host' | 'apiBasePath' | 'token' | 'defaultPageSize';
2
+ export type SourceId = 'process-env' | 'env-file' | 'home-file' | 'macos-keychain';
3
+ export type SourceLocation = {
4
+ sourceId: SourceId;
5
+ detail?: string;
6
+ };
7
+ export interface ProductDefinition {
8
+ readonly id: string;
9
+ readonly envVars: Record<ConfigKey, string>;
10
+ readonly defaultApiBasePath?: string;
11
+ }
12
+ export interface ReadableSource {
13
+ readonly id: SourceId;
14
+ readonly priority: number;
15
+ read(product: ProductDefinition, key: ConfigKey): string | undefined;
16
+ initialize?(options?: {
17
+ cwd?: string;
18
+ }): void;
19
+ describe(): string;
20
+ }
21
+ export interface WritableSource extends ReadableSource {
22
+ isAvailable(): boolean;
23
+ write(product: ProductDefinition, key: ConfigKey, value: string): void;
24
+ clear(product: ProductDefinition, key: ConfigKey): void;
25
+ }
26
+ export declare function isWritableSource(source: ReadableSource): source is WritableSource;
27
+ export declare function getNonEmptyValue(value: string | undefined): string | undefined;
28
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/config/source.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,aAAa,GAAG,OAAO,GAAG,iBAAiB,CAAC;AAE7E,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAEnF,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;IACrE,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC9C,QAAQ,IAAI,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,WAAW,IAAI,OAAO,CAAC;IACvB,KAAK,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACvE,KAAK,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;CACzD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,IAAI,cAAc,CAEjF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAM9E"}
@@ -0,0 +1,11 @@
1
+ export function isWritableSource(source) {
2
+ return typeof source.write === 'function';
3
+ }
4
+ export function getNonEmptyValue(value) {
5
+ if (!value) {
6
+ return undefined;
7
+ }
8
+ const trimmed = value.trim();
9
+ return trimmed.length > 0 ? trimmed : undefined;
10
+ }
11
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/config/source.ts"],"names":[],"mappings":"AA0BA,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO,OAAQ,MAAyB,CAAC,KAAK,KAAK,UAAU,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAyB;IACxD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC"}
@@ -0,0 +1,12 @@
1
+ export type ParsedEnvironment = Record<string, string>;
2
+ export declare class DotenvFileNotFoundError extends Error {
3
+ readonly filePath: string;
4
+ constructor(filePath: string);
5
+ }
6
+ export declare class DotenvFileCache {
7
+ private entry?;
8
+ get filePath(): string | undefined;
9
+ load(filePath: string): ParsedEnvironment;
10
+ invalidate(): void;
11
+ }
12
+ //# sourceMappingURL=dotenv-file-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dotenv-file-cache.d.ts","sourceRoot":"","sources":["../../../src/config/sources/dotenv-file-cache.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAQvD,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBACd,QAAQ,EAAE,MAAM;CAK7B;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAC,CAAa;IAE3B,IAAI,QAAQ,IAAI,MAAM,GAAG,SAAS,CAEjC;IAED,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB;IAuBzC,UAAU,IAAI,IAAI;CAGnB"}
@@ -0,0 +1,41 @@
1
+ import fs from 'node:fs';
2
+ import dotenv from 'dotenv';
3
+ export class DotenvFileNotFoundError extends Error {
4
+ filePath;
5
+ constructor(filePath) {
6
+ super(`Dotenv file not found: ${filePath}`);
7
+ this.name = 'DotenvFileNotFoundError';
8
+ this.filePath = filePath;
9
+ }
10
+ }
11
+ export class DotenvFileCache {
12
+ entry;
13
+ get filePath() {
14
+ return this.entry?.filePath;
15
+ }
16
+ load(filePath) {
17
+ let stats;
18
+ try {
19
+ stats = fs.statSync(filePath);
20
+ }
21
+ catch (error) {
22
+ if (error.code === 'ENOENT') {
23
+ if (this.entry?.filePath === filePath) {
24
+ this.entry = undefined;
25
+ }
26
+ throw new DotenvFileNotFoundError(filePath);
27
+ }
28
+ throw error;
29
+ }
30
+ if (this.entry && this.entry.filePath === filePath && this.entry.mtimeMs === stats.mtimeMs) {
31
+ return this.entry.values;
32
+ }
33
+ const values = dotenv.parse(fs.readFileSync(filePath));
34
+ this.entry = { filePath, mtimeMs: stats.mtimeMs, values };
35
+ return values;
36
+ }
37
+ invalidate() {
38
+ this.entry = undefined;
39
+ }
40
+ }
41
+ //# sourceMappingURL=dotenv-file-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dotenv-file-cache.js","sourceRoot":"","sources":["../../../src/config/sources/dotenv-file-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAU5B,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACvC,QAAQ,CAAS;IAC1B,YAAY,QAAgB;QAC1B,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,eAAe;IAClB,KAAK,CAAc;IAE3B,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,QAAgB;QACnB,IAAI,KAAe,CAAC;QACpB,IAAI,CAAC;YACH,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACvD,IAAI,IAAI,CAAC,KAAK,EAAE,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBACtC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;gBACzB,CAAC;gBACD,MAAM,IAAI,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YAC9C,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;YAC3F,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAC3B,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAC1D,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,UAAU;QACR,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;IACzB,CAAC;CACF"}