latchkey 0.1.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 (176) hide show
  1. package/.nvmrc +1 -0
  2. package/.pre-commit-config.yaml +22 -0
  3. package/.prettierignore +4 -0
  4. package/.prettierrc +7 -0
  5. package/CLAUDE.md +13 -0
  6. package/LICENSE +7 -0
  7. package/README.md +167 -0
  8. package/dist/scripts/cryptFile.d.ts +21 -0
  9. package/dist/scripts/cryptFile.d.ts.map +1 -0
  10. package/dist/scripts/cryptFile.js +106 -0
  11. package/dist/scripts/cryptFile.js.map +1 -0
  12. package/dist/scripts/encryptFile.d.ts +21 -0
  13. package/dist/scripts/encryptFile.d.ts.map +1 -0
  14. package/dist/scripts/encryptFile.js +101 -0
  15. package/dist/scripts/encryptFile.js.map +1 -0
  16. package/dist/scripts/recordBrowserSession.d.ts +18 -0
  17. package/dist/scripts/recordBrowserSession.d.ts.map +1 -0
  18. package/dist/scripts/recordBrowserSession.js +213 -0
  19. package/dist/scripts/recordBrowserSession.js.map +1 -0
  20. package/dist/src/apiCredentialStore.d.ts +19 -0
  21. package/dist/src/apiCredentialStore.d.ts.map +1 -0
  22. package/dist/src/apiCredentialStore.js +65 -0
  23. package/dist/src/apiCredentialStore.js.map +1 -0
  24. package/dist/src/apiCredentials.d.ts +134 -0
  25. package/dist/src/apiCredentials.d.ts.map +1 -0
  26. package/dist/src/apiCredentials.js +139 -0
  27. package/dist/src/apiCredentials.js.map +1 -0
  28. package/dist/src/browserConfig.d.ts +90 -0
  29. package/dist/src/browserConfig.d.ts.map +1 -0
  30. package/dist/src/browserConfig.js +259 -0
  31. package/dist/src/browserConfig.js.map +1 -0
  32. package/dist/src/browserState.d.ts +8 -0
  33. package/dist/src/browserState.d.ts.map +1 -0
  34. package/dist/src/browserState.js +21 -0
  35. package/dist/src/browserState.js.map +1 -0
  36. package/dist/src/cli.d.ts +6 -0
  37. package/dist/src/cli.d.ts.map +1 -0
  38. package/dist/src/cli.js +25 -0
  39. package/dist/src/cli.js.map +1 -0
  40. package/dist/src/cliCommands.d.ts +29 -0
  41. package/dist/src/cliCommands.d.ts.map +1 -0
  42. package/dist/src/cliCommands.js +264 -0
  43. package/dist/src/cliCommands.js.map +1 -0
  44. package/dist/src/config.d.ts +35 -0
  45. package/dist/src/config.d.ts.map +1 -0
  46. package/dist/src/config.js +96 -0
  47. package/dist/src/config.js.map +1 -0
  48. package/dist/src/curl.d.ts +29 -0
  49. package/dist/src/curl.d.ts.map +1 -0
  50. package/dist/src/curl.js +53 -0
  51. package/dist/src/curl.js.map +1 -0
  52. package/dist/src/encryptedStorage.d.ts +39 -0
  53. package/dist/src/encryptedStorage.d.ts.map +1 -0
  54. package/dist/src/encryptedStorage.js +128 -0
  55. package/dist/src/encryptedStorage.js.map +1 -0
  56. package/dist/src/encryption.d.ts +28 -0
  57. package/dist/src/encryption.d.ts.map +1 -0
  58. package/dist/src/encryption.js +86 -0
  59. package/dist/src/encryption.js.map +1 -0
  60. package/dist/src/index.d.ts +14 -0
  61. package/dist/src/index.d.ts.map +1 -0
  62. package/dist/src/index.js +17 -0
  63. package/dist/src/index.js.map +1 -0
  64. package/dist/src/keychain.d.ts +33 -0
  65. package/dist/src/keychain.d.ts.map +1 -0
  66. package/dist/src/keychain.js +94 -0
  67. package/dist/src/keychain.js.map +1 -0
  68. package/dist/src/playwrightUtils.d.ts +27 -0
  69. package/dist/src/playwrightUtils.d.ts.map +1 -0
  70. package/dist/src/playwrightUtils.js +122 -0
  71. package/dist/src/playwrightUtils.js.map +1 -0
  72. package/dist/src/registry.d.ts +12 -0
  73. package/dist/src/registry.d.ts.map +1 -0
  74. package/dist/src/registry.js +30 -0
  75. package/dist/src/registry.js.map +1 -0
  76. package/dist/src/services/base.d.ts +98 -0
  77. package/dist/src/services/base.d.ts.map +1 -0
  78. package/dist/src/services/base.js +137 -0
  79. package/dist/src/services/base.js.map +1 -0
  80. package/dist/src/services/discord.d.ts +20 -0
  81. package/dist/src/services/discord.d.ts.map +1 -0
  82. package/dist/src/services/discord.js +55 -0
  83. package/dist/src/services/discord.js.map +1 -0
  84. package/dist/src/services/dropbox.d.ts +23 -0
  85. package/dist/src/services/dropbox.d.ts.map +1 -0
  86. package/dist/src/services/dropbox.js +136 -0
  87. package/dist/src/services/dropbox.js.map +1 -0
  88. package/dist/src/services/github.d.ts +23 -0
  89. package/dist/src/services/github.d.ts.map +1 -0
  90. package/dist/src/services/github.js +110 -0
  91. package/dist/src/services/github.js.map +1 -0
  92. package/dist/src/services/index.d.ts +12 -0
  93. package/dist/src/services/index.d.ts.map +1 -0
  94. package/dist/src/services/index.js +11 -0
  95. package/dist/src/services/index.js.map +1 -0
  96. package/dist/src/services/linear.d.ts +23 -0
  97. package/dist/src/services/linear.d.ts.map +1 -0
  98. package/dist/src/services/linear.js +110 -0
  99. package/dist/src/services/linear.js.map +1 -0
  100. package/dist/src/services/slack.d.ts +21 -0
  101. package/dist/src/services/slack.d.ts.map +1 -0
  102. package/dist/src/services/slack.js +67 -0
  103. package/dist/src/services/slack.js.map +1 -0
  104. package/dist/tests/apiCredentialStore.test.d.ts +2 -0
  105. package/dist/tests/apiCredentialStore.test.d.ts.map +1 -0
  106. package/dist/tests/apiCredentialStore.test.js +130 -0
  107. package/dist/tests/apiCredentialStore.test.js.map +1 -0
  108. package/dist/tests/apiCredentials.test.d.ts +2 -0
  109. package/dist/tests/apiCredentials.test.d.ts.map +1 -0
  110. package/dist/tests/apiCredentials.test.js +169 -0
  111. package/dist/tests/apiCredentials.test.js.map +1 -0
  112. package/dist/tests/cli.test.d.ts +2 -0
  113. package/dist/tests/cli.test.d.ts.map +1 -0
  114. package/dist/tests/cli.test.js +584 -0
  115. package/dist/tests/cli.test.js.map +1 -0
  116. package/dist/tests/encryptedStorage.test.d.ts +2 -0
  117. package/dist/tests/encryptedStorage.test.d.ts.map +1 -0
  118. package/dist/tests/encryptedStorage.test.js +126 -0
  119. package/dist/tests/encryptedStorage.test.js.map +1 -0
  120. package/dist/tests/encryption.test.d.ts +2 -0
  121. package/dist/tests/encryption.test.d.ts.map +1 -0
  122. package/dist/tests/encryption.test.js +121 -0
  123. package/dist/tests/encryption.test.js.map +1 -0
  124. package/dist/tests/lint.test.d.ts +2 -0
  125. package/dist/tests/lint.test.d.ts.map +1 -0
  126. package/dist/tests/lint.test.js +18 -0
  127. package/dist/tests/lint.test.js.map +1 -0
  128. package/dist/tests/registry.test.d.ts +2 -0
  129. package/dist/tests/registry.test.d.ts.map +1 -0
  130. package/dist/tests/registry.test.js +85 -0
  131. package/dist/tests/registry.test.js.map +1 -0
  132. package/dist/tests/servicesAgainstRecordings.test.d.ts +20 -0
  133. package/dist/tests/servicesAgainstRecordings.test.d.ts.map +1 -0
  134. package/dist/tests/servicesAgainstRecordings.test.js +157 -0
  135. package/dist/tests/servicesAgainstRecordings.test.js.map +1 -0
  136. package/dist/tests/typecheck.test.d.ts +2 -0
  137. package/dist/tests/typecheck.test.d.ts.map +1 -0
  138. package/dist/tests/typecheck.test.js +18 -0
  139. package/dist/tests/typecheck.test.js.map +1 -0
  140. package/docs/development.md +94 -0
  141. package/eslint.config.js +30 -0
  142. package/integrations/SKILL.md +62 -0
  143. package/package.json +68 -0
  144. package/scripts/cryptFile.ts +123 -0
  145. package/scripts/recordBrowserSession.ts +280 -0
  146. package/scripts/tsconfig.json +10 -0
  147. package/src/apiCredentialStore.ts +87 -0
  148. package/src/apiCredentials.ts +180 -0
  149. package/src/cli.ts +32 -0
  150. package/src/cliCommands.ts +321 -0
  151. package/src/config.ts +115 -0
  152. package/src/curl.ts +78 -0
  153. package/src/encryptedStorage.ts +161 -0
  154. package/src/encryption.ts +106 -0
  155. package/src/index.ts +65 -0
  156. package/src/keychain.ts +105 -0
  157. package/src/playwrightUtils.ts +143 -0
  158. package/src/registry.ts +35 -0
  159. package/src/services/base.ts +234 -0
  160. package/src/services/discord.ts +73 -0
  161. package/src/services/dropbox.ts +173 -0
  162. package/src/services/github.ts +139 -0
  163. package/src/services/index.ts +13 -0
  164. package/src/services/linear.ts +134 -0
  165. package/src/services/slack.ts +85 -0
  166. package/tests/apiCredentialStore.test.ts +162 -0
  167. package/tests/apiCredentials.test.ts +195 -0
  168. package/tests/cli.test.ts +798 -0
  169. package/tests/encryptedStorage.test.ts +173 -0
  170. package/tests/encryption.test.ts +169 -0
  171. package/tests/lint.test.ts +19 -0
  172. package/tests/registry.test.ts +103 -0
  173. package/tests/servicesAgainstRecordings.test.ts +230 -0
  174. package/tests/typecheck.test.ts +19 -0
  175. package/tsconfig.json +24 -0
  176. package/vitest.config.ts +13 -0
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * Record browser requests and responses during a login session.
4
+ *
5
+ * This script opens a browser at a service's login URL and records all HTTP
6
+ * requests and responses (including their headers and timing). When you close the
7
+ * browser, the recording is saved. This is useful for recording login flows that
8
+ * can be replayed later for testing credentials extraction.
9
+ *
10
+ * Usage:
11
+ * npx tsx scripts/recordBrowserSession.ts <service_name> [recording_name]
12
+ *
13
+ * Examples:
14
+ * npx tsx scripts/recordBrowserSession.ts slack
15
+ * npx tsx scripts/recordBrowserSession.ts discord custom_session.json
16
+ */
17
+ import { mkdirSync, writeFileSync } from 'node:fs';
18
+ import { dirname, join, resolve } from 'node:path';
19
+ import { fileURLToPath } from 'node:url';
20
+ import { CONFIG } from '../src/config.js';
21
+ import { EncryptedStorage } from '../src/encryptedStorage.js';
22
+ import { withTempBrowserContext } from '../src/playwrightUtils.js';
23
+ import { REGISTRY } from '../src/registry.js';
24
+ // Get the directory of this file
25
+ const __filename = fileURLToPath(import.meta.url);
26
+ const __dirname = dirname(__filename);
27
+ // Recordings directory relative to this script
28
+ const RECORDINGS_DIRECTORY = resolve(__dirname, 'recordings');
29
+ // Default recording filename
30
+ const DEFAULT_RECORDING_NAME = 'login_session.json';
31
+ class UnknownServiceError extends Error {
32
+ constructor(serviceName) {
33
+ super(`Unknown service: ${serviceName}`);
34
+ this.name = 'UnknownServiceError';
35
+ }
36
+ }
37
+ // Resource types to skip (CSS, images, fonts, multimedia)
38
+ const SKIPPED_RESOURCE_TYPES = new Set(['stylesheet', 'image', 'media', 'font']);
39
+ // Common multi-part TLDs
40
+ const MULTI_PART_TLDS = new Set(['co.uk', 'com.au', 'co.nz', 'co.jp', 'com.br', 'co.in']);
41
+ /**
42
+ * Extract the base domain from a URL.
43
+ *
44
+ * For example:
45
+ * https://discord.com/login -> discord.com
46
+ * https://api.discord.com/v9/users -> discord.com
47
+ * https://www.example.co.uk/page -> example.co.uk
48
+ */
49
+ function extractBaseDomain(url) {
50
+ let hostname;
51
+ try {
52
+ hostname = new URL(url).hostname;
53
+ }
54
+ catch {
55
+ return '';
56
+ }
57
+ // Split the hostname into parts
58
+ const parts = hostname.split('.');
59
+ // Handle common multi-part TLDs (e.g., co.uk, com.au)
60
+ if (parts.length >= 3) {
61
+ const potentialTld = parts.slice(-2).join('.');
62
+ if (MULTI_PART_TLDS.has(potentialTld)) {
63
+ return parts.slice(-3).join('.');
64
+ }
65
+ }
66
+ if (parts.length >= 2) {
67
+ return parts.slice(-2).join('.');
68
+ }
69
+ return hostname;
70
+ }
71
+ /**
72
+ * Check if a request URL belongs to the same base domain.
73
+ */
74
+ function isSameBaseDomain(requestUrl, baseDomain) {
75
+ let requestHostname;
76
+ try {
77
+ requestHostname = new URL(requestUrl).hostname;
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ return requestHostname === baseDomain || requestHostname.endsWith('.' + baseDomain);
83
+ }
84
+ /**
85
+ * Handle a response and record both request and response details.
86
+ */
87
+ async function handleResponse(response, recordedEntries, startTime, baseDomain) {
88
+ const request = response.request();
89
+ // Skip CSS, images, fonts, and multimedia
90
+ if (SKIPPED_RESOURCE_TYPES.has(request.resourceType())) {
91
+ return;
92
+ }
93
+ // Skip requests to external domains
94
+ if (!isSameBaseDomain(request.url(), baseDomain)) {
95
+ return;
96
+ }
97
+ if (startTime.value === 0) {
98
+ startTime.value = Date.now();
99
+ }
100
+ const timestampMs = Date.now() - startTime.value;
101
+ const requestData = {
102
+ timestamp_ms: timestampMs,
103
+ method: request.method(),
104
+ url: request.url(),
105
+ headers: await request.allHeaders(),
106
+ resource_type: request.resourceType(),
107
+ };
108
+ // Include POST data if present
109
+ try {
110
+ const postData = request.postData();
111
+ if (postData !== null) {
112
+ requestData.post_data = postData;
113
+ }
114
+ }
115
+ catch {
116
+ // Post data not available or not decodable
117
+ }
118
+ const responseData = {
119
+ status: response.status(),
120
+ status_text: response.statusText(),
121
+ headers: await response.allHeaders(),
122
+ };
123
+ // Try to get response body as text (skip binary content)
124
+ try {
125
+ const body = await response.text();
126
+ responseData.body = body;
127
+ }
128
+ catch {
129
+ // Binary content or other error - skip body
130
+ }
131
+ recordedEntries.push({
132
+ request: requestData,
133
+ response: responseData,
134
+ });
135
+ }
136
+ /**
137
+ * Record browser requests and responses during a login session.
138
+ */
139
+ async function record(serviceName, recordingName = DEFAULT_RECORDING_NAME) {
140
+ const service = REGISTRY.getByName(serviceName);
141
+ if (service === null) {
142
+ throw new UnknownServiceError(serviceName);
143
+ }
144
+ const outputDirectory = join(RECORDINGS_DIRECTORY, serviceName);
145
+ mkdirSync(outputDirectory, { recursive: true });
146
+ const requestsPath = join(outputDirectory, recordingName);
147
+ const browserStatePath = CONFIG.browserStatePath;
148
+ const baseDomain = extractBaseDomain(service.loginUrl);
149
+ console.log(`Recording login for service: ${service.name}`);
150
+ console.log(`Login URL: ${service.loginUrl}`);
151
+ console.log(`Recording requests to: ${baseDomain} (and subdomains)`);
152
+ console.log(`Output directory: ${outputDirectory}`);
153
+ console.log(`Browser state: ${browserStatePath}`);
154
+ console.log("\nClose the browser window when you're done to save the recording.");
155
+ const recordedEntries = [];
156
+ const startTime = { value: 0 };
157
+ const encryptedStorage = new EncryptedStorage({
158
+ encryptionKeyOverride: CONFIG.encryptionKeyOverride,
159
+ serviceName: CONFIG.serviceName,
160
+ accountName: CONFIG.accountName,
161
+ });
162
+ await withTempBrowserContext(encryptedStorage, browserStatePath, async ({ context }) => {
163
+ const page = await context.newPage();
164
+ // Register response handler to capture all requests and responses
165
+ page.on('response', (response) => {
166
+ handleResponse(response, recordedEntries, startTime, baseDomain).catch(() => {
167
+ // Ignore errors in response handling
168
+ });
169
+ });
170
+ await page.goto(service.loginUrl);
171
+ // Wait for user to close the browser
172
+ await page.waitForEvent('close', { timeout: 0 });
173
+ });
174
+ // Save recorded entries
175
+ writeFileSync(requestsPath, JSON.stringify(recordedEntries, null, 2));
176
+ console.log('\nRecording saved successfully!');
177
+ console.log(` Requests file: ${requestsPath}`);
178
+ console.log(` Recorded ${String(recordedEntries.length)} request/response pairs`);
179
+ }
180
+ // Main entry point
181
+ async function main() {
182
+ const args = process.argv.slice(2);
183
+ if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
184
+ console.log('Usage: npx tsx scripts/recordBrowserSession.ts <service_name> [recording_name]');
185
+ console.log('');
186
+ console.log('Arguments:');
187
+ console.log(" service_name Name of the service to record login for (e.g., 'slack', 'discord')");
188
+ console.log(' recording_name Name of the recording file (default: login_session.json)');
189
+ console.log('');
190
+ console.log('Examples:');
191
+ console.log(' npx tsx scripts/recordBrowserSession.ts slack');
192
+ console.log(' npx tsx scripts/recordBrowserSession.ts discord custom_session.json');
193
+ process.exit(0);
194
+ }
195
+ const serviceName = args[0];
196
+ const recordingName = args[1] ?? DEFAULT_RECORDING_NAME;
197
+ try {
198
+ await record(serviceName, recordingName);
199
+ }
200
+ catch (error) {
201
+ if (error instanceof UnknownServiceError) {
202
+ console.error(`Error: ${error.message}`);
203
+ console.error('Available services:');
204
+ for (const service of REGISTRY.services) {
205
+ console.error(` - ${service.name}`);
206
+ }
207
+ process.exit(1);
208
+ }
209
+ throw error;
210
+ }
211
+ }
212
+ void main();
213
+ //# sourceMappingURL=recordBrowserSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recordBrowserSession.js","sourceRoot":"","sources":["../../scripts/recordBrowserSession.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * API credential store for persisting and loading API credentials.
3
+ */
4
+ import { ApiCredentials } from './apiCredentials.js';
5
+ import { EncryptedStorage } from './encryptedStorage.js';
6
+ export declare class ApiCredentialStoreError extends Error {
7
+ constructor(message: string);
8
+ }
9
+ export declare class ApiCredentialStore {
10
+ readonly path: string;
11
+ private readonly encryptedStorage;
12
+ constructor(path: string, encryptedStorage: EncryptedStorage);
13
+ private loadStoreData;
14
+ private saveStoreData;
15
+ get(serviceName: string): ApiCredentials | null;
16
+ save(serviceName: string, apiCredentials: ApiCredentials): void;
17
+ delete(serviceName: string): boolean;
18
+ }
19
+ //# sourceMappingURL=apiCredentialStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiCredentialStore.d.ts","sourceRoot":"","sources":["../../src/apiCredentialStore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAID,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;gBAExC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB;IAK5D,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,aAAa;IAUrB,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAiB/C,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,GAAG,IAAI;IAM/D,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;CASrC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * API credential store for persisting and loading API credentials.
3
+ */
4
+ import { ApiCredentialsSchema, deserializeCredentials, serializeCredentials, } from './apiCredentials.js';
5
+ export class ApiCredentialStoreError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = 'ApiCredentialStoreError';
9
+ }
10
+ }
11
+ export class ApiCredentialStore {
12
+ path;
13
+ encryptedStorage;
14
+ constructor(path, encryptedStorage) {
15
+ this.path = path;
16
+ this.encryptedStorage = encryptedStorage;
17
+ }
18
+ loadStoreData() {
19
+ try {
20
+ const content = this.encryptedStorage.readFile(this.path);
21
+ if (content === null) {
22
+ return {};
23
+ }
24
+ return JSON.parse(content);
25
+ }
26
+ catch (error) {
27
+ throw new ApiCredentialStoreError(`Failed to read credential store: ${error instanceof Error ? error.message : String(error)}`);
28
+ }
29
+ }
30
+ saveStoreData(data) {
31
+ try {
32
+ this.encryptedStorage.writeFile(this.path, JSON.stringify(data, null, 2));
33
+ }
34
+ catch (error) {
35
+ throw new ApiCredentialStoreError(`Failed to write credential store: ${error instanceof Error ? error.message : String(error)}`);
36
+ }
37
+ }
38
+ get(serviceName) {
39
+ const data = this.loadStoreData();
40
+ const credentialData = data[serviceName];
41
+ if (credentialData === undefined) {
42
+ return null;
43
+ }
44
+ const parseResult = ApiCredentialsSchema.safeParse(credentialData);
45
+ if (!parseResult.success) {
46
+ throw new ApiCredentialStoreError(`Invalid credential data for service ${serviceName}: ${parseResult.error.message}`);
47
+ }
48
+ return deserializeCredentials(parseResult.data);
49
+ }
50
+ save(serviceName, apiCredentials) {
51
+ const data = this.loadStoreData();
52
+ data[serviceName] = serializeCredentials(apiCredentials);
53
+ this.saveStoreData(data);
54
+ }
55
+ delete(serviceName) {
56
+ const data = this.loadStoreData();
57
+ if (!(serviceName in data)) {
58
+ return false;
59
+ }
60
+ const { [serviceName]: _, ...rest } = data;
61
+ this.saveStoreData(rest);
62
+ return true;
63
+ }
64
+ }
65
+ //# sourceMappingURL=apiCredentialStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiCredentialStore.js","sourceRoot":"","sources":["../../src/apiCredentialStore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAEL,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAID,MAAM,OAAO,kBAAkB;IACpB,IAAI,CAAS;IACL,gBAAgB,CAAmB;IAEpD,YAAY,IAAY,EAAE,gBAAkC;QAC1D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;IAC3C,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1D,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,uBAAuB,CAC/B,oCAAoC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC7F,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,IAAe;QACnC,IAAI,CAAC;YACH,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,uBAAuB,CAC/B,qCAAqC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC9F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,GAAG,CAAC,WAAmB;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;QACzC,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,WAAW,GAAG,oBAAoB,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QACnE,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACzB,MAAM,IAAI,uBAAuB,CAC/B,uCAAuC,WAAW,KAAK,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,CACnF,CAAC;QACJ,CAAC;QAED,OAAO,sBAAsB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,CAAC,WAAmB,EAAE,cAA8B;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,IAAI,CAAC,WAAW,CAAC,GAAG,oBAAoB,CAAC,cAAc,CAAC,CAAC;QACzD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,WAAmB;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QAC3C,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * API credentials types and utilities for authentication with various services.
3
+ */
4
+ import { z } from 'zod';
5
+ export declare enum ApiCredentialStatus {
6
+ Missing = "missing",
7
+ Valid = "valid",
8
+ Invalid = "invalid"
9
+ }
10
+ /**
11
+ * Base interface for all API credentials.
12
+ * Each credential type must specify how to convert itself to curl arguments.
13
+ */
14
+ export interface ApiCredentials {
15
+ readonly objectType: string;
16
+ asCurlArguments(): readonly string[];
17
+ }
18
+ /**
19
+ * Bearer token authentication (Authorization: Bearer <token>).
20
+ */
21
+ export declare const AuthorizationBearerSchema: z.ZodObject<{
22
+ objectType: z.ZodLiteral<"authorizationBearer">;
23
+ token: z.ZodString;
24
+ }, "strip", z.ZodTypeAny, {
25
+ objectType: "authorizationBearer";
26
+ token: string;
27
+ }, {
28
+ objectType: "authorizationBearer";
29
+ token: string;
30
+ }>;
31
+ export type AuthorizationBearerData = z.infer<typeof AuthorizationBearerSchema>;
32
+ export declare class AuthorizationBearer implements ApiCredentials {
33
+ readonly objectType: "authorizationBearer";
34
+ readonly token: string;
35
+ constructor(token: string);
36
+ asCurlArguments(): readonly string[];
37
+ toJSON(): AuthorizationBearerData;
38
+ static fromJSON(data: AuthorizationBearerData): AuthorizationBearer;
39
+ }
40
+ /**
41
+ * Raw authorization header (Authorization: <token>).
42
+ */
43
+ export declare const AuthorizationBareSchema: z.ZodObject<{
44
+ objectType: z.ZodLiteral<"authorizationBare">;
45
+ token: z.ZodString;
46
+ }, "strip", z.ZodTypeAny, {
47
+ objectType: "authorizationBare";
48
+ token: string;
49
+ }, {
50
+ objectType: "authorizationBare";
51
+ token: string;
52
+ }>;
53
+ export type AuthorizationBareData = z.infer<typeof AuthorizationBareSchema>;
54
+ export declare class AuthorizationBare implements ApiCredentials {
55
+ readonly objectType: "authorizationBare";
56
+ readonly token: string;
57
+ constructor(token: string);
58
+ asCurlArguments(): readonly string[];
59
+ toJSON(): AuthorizationBareData;
60
+ static fromJSON(data: AuthorizationBareData): AuthorizationBare;
61
+ }
62
+ /**
63
+ * Slack-specific credentials (token + d cookie).
64
+ */
65
+ export declare const SlackApiCredentialsSchema: z.ZodObject<{
66
+ objectType: z.ZodLiteral<"slack">;
67
+ token: z.ZodString;
68
+ dCookie: z.ZodString;
69
+ }, "strip", z.ZodTypeAny, {
70
+ objectType: "slack";
71
+ token: string;
72
+ dCookie: string;
73
+ }, {
74
+ objectType: "slack";
75
+ token: string;
76
+ dCookie: string;
77
+ }>;
78
+ export type SlackApiCredentialsData = z.infer<typeof SlackApiCredentialsSchema>;
79
+ export declare class SlackApiCredentials implements ApiCredentials {
80
+ readonly objectType: "slack";
81
+ readonly token: string;
82
+ readonly dCookie: string;
83
+ constructor(token: string, dCookie: string);
84
+ asCurlArguments(): readonly string[];
85
+ toJSON(): SlackApiCredentialsData;
86
+ static fromJSON(data: SlackApiCredentialsData): SlackApiCredentials;
87
+ }
88
+ /**
89
+ * Union schema for all credential types.
90
+ */
91
+ export declare const ApiCredentialsSchema: z.ZodDiscriminatedUnion<"objectType", [z.ZodObject<{
92
+ objectType: z.ZodLiteral<"authorizationBearer">;
93
+ token: z.ZodString;
94
+ }, "strip", z.ZodTypeAny, {
95
+ objectType: "authorizationBearer";
96
+ token: string;
97
+ }, {
98
+ objectType: "authorizationBearer";
99
+ token: string;
100
+ }>, z.ZodObject<{
101
+ objectType: z.ZodLiteral<"authorizationBare">;
102
+ token: z.ZodString;
103
+ }, "strip", z.ZodTypeAny, {
104
+ objectType: "authorizationBare";
105
+ token: string;
106
+ }, {
107
+ objectType: "authorizationBare";
108
+ token: string;
109
+ }>, z.ZodObject<{
110
+ objectType: z.ZodLiteral<"slack">;
111
+ token: z.ZodString;
112
+ dCookie: z.ZodString;
113
+ }, "strip", z.ZodTypeAny, {
114
+ objectType: "slack";
115
+ token: string;
116
+ dCookie: string;
117
+ }, {
118
+ objectType: "slack";
119
+ token: string;
120
+ dCookie: string;
121
+ }>]>;
122
+ export type ApiCredentialsData = z.infer<typeof ApiCredentialsSchema>;
123
+ /**
124
+ * Deserialize credentials from JSON data.
125
+ */
126
+ export declare function deserializeCredentials(data: ApiCredentialsData): ApiCredentials;
127
+ /**
128
+ * Serialize credentials to JSON data.
129
+ */
130
+ export declare function serializeCredentials(credentials: ApiCredentials): ApiCredentialsData;
131
+ export declare class ApiCredentialsSerializationError extends Error {
132
+ constructor(message: string);
133
+ }
134
+ //# sourceMappingURL=apiCredentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiCredentials.d.ts","sourceRoot":"","sources":["../../src/apiCredentials.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,oBAAY,mBAAmB;IAC7B,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,eAAe,IAAI,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;EAGpC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAEhF,qBAAa,mBAAoB,YAAW,cAAc;IACxD,QAAQ,CAAC,UAAU,EAAG,qBAAqB,CAAU;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM;IAIzB,eAAe,IAAI,SAAS,MAAM,EAAE;IAIpC,MAAM,IAAI,uBAAuB;IAOjC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,GAAG,mBAAmB;CAGpE;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;EAGlC,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE5E,qBAAa,iBAAkB,YAAW,cAAc;IACtD,QAAQ,CAAC,UAAU,EAAG,mBAAmB,CAAU;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM;IAIzB,eAAe,IAAI,SAAS,MAAM,EAAE;IAIpC,MAAM,IAAI,qBAAqB;IAO/B,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB;CAGhE;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;EAIpC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAEhF,qBAAa,mBAAoB,YAAW,cAAc;IACxD,QAAQ,CAAC,UAAU,EAAG,OAAO,CAAU;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAK1C,eAAe,IAAI,SAAS,MAAM,EAAE;IAIpC,MAAM,IAAI,uBAAuB;IAQjC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,GAAG,mBAAmB;CAGpE;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAI/B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CAe/E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,cAAc,GAAG,kBAAkB,CAWpF;AAED,qBAAa,gCAAiC,SAAQ,KAAK;gBAC7C,OAAO,EAAE,MAAM;CAI5B"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * API credentials types and utilities for authentication with various services.
3
+ */
4
+ import { z } from 'zod';
5
+ export var ApiCredentialStatus;
6
+ (function (ApiCredentialStatus) {
7
+ ApiCredentialStatus["Missing"] = "missing";
8
+ ApiCredentialStatus["Valid"] = "valid";
9
+ ApiCredentialStatus["Invalid"] = "invalid";
10
+ })(ApiCredentialStatus || (ApiCredentialStatus = {}));
11
+ /**
12
+ * Bearer token authentication (Authorization: Bearer <token>).
13
+ */
14
+ export const AuthorizationBearerSchema = z.object({
15
+ objectType: z.literal('authorizationBearer'),
16
+ token: z.string(),
17
+ });
18
+ export class AuthorizationBearer {
19
+ objectType = 'authorizationBearer';
20
+ token;
21
+ constructor(token) {
22
+ this.token = token;
23
+ }
24
+ asCurlArguments() {
25
+ return ['-H', `Authorization: Bearer ${this.token}`];
26
+ }
27
+ toJSON() {
28
+ return {
29
+ objectType: this.objectType,
30
+ token: this.token,
31
+ };
32
+ }
33
+ static fromJSON(data) {
34
+ return new AuthorizationBearer(data.token);
35
+ }
36
+ }
37
+ /**
38
+ * Raw authorization header (Authorization: <token>).
39
+ */
40
+ export const AuthorizationBareSchema = z.object({
41
+ objectType: z.literal('authorizationBare'),
42
+ token: z.string(),
43
+ });
44
+ export class AuthorizationBare {
45
+ objectType = 'authorizationBare';
46
+ token;
47
+ constructor(token) {
48
+ this.token = token;
49
+ }
50
+ asCurlArguments() {
51
+ return ['-H', `Authorization: ${this.token}`];
52
+ }
53
+ toJSON() {
54
+ return {
55
+ objectType: this.objectType,
56
+ token: this.token,
57
+ };
58
+ }
59
+ static fromJSON(data) {
60
+ return new AuthorizationBare(data.token);
61
+ }
62
+ }
63
+ /**
64
+ * Slack-specific credentials (token + d cookie).
65
+ */
66
+ export const SlackApiCredentialsSchema = z.object({
67
+ objectType: z.literal('slack'),
68
+ token: z.string(),
69
+ dCookie: z.string(),
70
+ });
71
+ export class SlackApiCredentials {
72
+ objectType = 'slack';
73
+ token;
74
+ dCookie;
75
+ constructor(token, dCookie) {
76
+ this.token = token;
77
+ this.dCookie = dCookie;
78
+ }
79
+ asCurlArguments() {
80
+ return ['-H', `Authorization: Bearer ${this.token}`, '-H', `Cookie: d=${this.dCookie}`];
81
+ }
82
+ toJSON() {
83
+ return {
84
+ objectType: this.objectType,
85
+ token: this.token,
86
+ dCookie: this.dCookie,
87
+ };
88
+ }
89
+ static fromJSON(data) {
90
+ return new SlackApiCredentials(data.token, data.dCookie);
91
+ }
92
+ }
93
+ /**
94
+ * Union schema for all credential types.
95
+ */
96
+ export const ApiCredentialsSchema = z.discriminatedUnion('objectType', [
97
+ AuthorizationBearerSchema,
98
+ AuthorizationBareSchema,
99
+ SlackApiCredentialsSchema,
100
+ ]);
101
+ /**
102
+ * Deserialize credentials from JSON data.
103
+ */
104
+ export function deserializeCredentials(data) {
105
+ switch (data.objectType) {
106
+ case 'authorizationBearer':
107
+ return AuthorizationBearer.fromJSON(data);
108
+ case 'authorizationBare':
109
+ return AuthorizationBare.fromJSON(data);
110
+ case 'slack':
111
+ return SlackApiCredentials.fromJSON(data);
112
+ default: {
113
+ const exhaustiveCheck = data;
114
+ throw new ApiCredentialsSerializationError(`Unknown credential type: ${exhaustiveCheck.objectType}`);
115
+ }
116
+ }
117
+ }
118
+ /**
119
+ * Serialize credentials to JSON data.
120
+ */
121
+ export function serializeCredentials(credentials) {
122
+ if (credentials instanceof AuthorizationBearer) {
123
+ return credentials.toJSON();
124
+ }
125
+ if (credentials instanceof AuthorizationBare) {
126
+ return credentials.toJSON();
127
+ }
128
+ if (credentials instanceof SlackApiCredentials) {
129
+ return credentials.toJSON();
130
+ }
131
+ throw new ApiCredentialsSerializationError(`Unknown credential type: ${credentials.objectType}`);
132
+ }
133
+ export class ApiCredentialsSerializationError extends Error {
134
+ constructor(message) {
135
+ super(message);
136
+ this.name = 'ApiCredentialsSerializationError';
137
+ }
138
+ }
139
+ //# sourceMappingURL=apiCredentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiCredentials.js","sourceRoot":"","sources":["../../src/apiCredentials.ts"],"names":[],"mappings":"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"}