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.
- package/.nvmrc +1 -0
- package/.pre-commit-config.yaml +22 -0
- package/.prettierignore +4 -0
- package/.prettierrc +7 -0
- package/CLAUDE.md +13 -0
- package/LICENSE +7 -0
- package/README.md +167 -0
- package/dist/scripts/cryptFile.d.ts +21 -0
- package/dist/scripts/cryptFile.d.ts.map +1 -0
- package/dist/scripts/cryptFile.js +106 -0
- package/dist/scripts/cryptFile.js.map +1 -0
- package/dist/scripts/encryptFile.d.ts +21 -0
- package/dist/scripts/encryptFile.d.ts.map +1 -0
- package/dist/scripts/encryptFile.js +101 -0
- package/dist/scripts/encryptFile.js.map +1 -0
- package/dist/scripts/recordBrowserSession.d.ts +18 -0
- package/dist/scripts/recordBrowserSession.d.ts.map +1 -0
- package/dist/scripts/recordBrowserSession.js +213 -0
- package/dist/scripts/recordBrowserSession.js.map +1 -0
- package/dist/src/apiCredentialStore.d.ts +19 -0
- package/dist/src/apiCredentialStore.d.ts.map +1 -0
- package/dist/src/apiCredentialStore.js +65 -0
- package/dist/src/apiCredentialStore.js.map +1 -0
- package/dist/src/apiCredentials.d.ts +134 -0
- package/dist/src/apiCredentials.d.ts.map +1 -0
- package/dist/src/apiCredentials.js +139 -0
- package/dist/src/apiCredentials.js.map +1 -0
- package/dist/src/browserConfig.d.ts +90 -0
- package/dist/src/browserConfig.d.ts.map +1 -0
- package/dist/src/browserConfig.js +259 -0
- package/dist/src/browserConfig.js.map +1 -0
- package/dist/src/browserState.d.ts +8 -0
- package/dist/src/browserState.d.ts.map +1 -0
- package/dist/src/browserState.js +21 -0
- package/dist/src/browserState.js.map +1 -0
- package/dist/src/cli.d.ts +6 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +25 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/cliCommands.d.ts +29 -0
- package/dist/src/cliCommands.d.ts.map +1 -0
- package/dist/src/cliCommands.js +264 -0
- package/dist/src/cliCommands.js.map +1 -0
- package/dist/src/config.d.ts +35 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +96 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/curl.d.ts +29 -0
- package/dist/src/curl.d.ts.map +1 -0
- package/dist/src/curl.js +53 -0
- package/dist/src/curl.js.map +1 -0
- package/dist/src/encryptedStorage.d.ts +39 -0
- package/dist/src/encryptedStorage.d.ts.map +1 -0
- package/dist/src/encryptedStorage.js +128 -0
- package/dist/src/encryptedStorage.js.map +1 -0
- package/dist/src/encryption.d.ts +28 -0
- package/dist/src/encryption.d.ts.map +1 -0
- package/dist/src/encryption.js +86 -0
- package/dist/src/encryption.js.map +1 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +17 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/keychain.d.ts +33 -0
- package/dist/src/keychain.d.ts.map +1 -0
- package/dist/src/keychain.js +94 -0
- package/dist/src/keychain.js.map +1 -0
- package/dist/src/playwrightUtils.d.ts +27 -0
- package/dist/src/playwrightUtils.d.ts.map +1 -0
- package/dist/src/playwrightUtils.js +122 -0
- package/dist/src/playwrightUtils.js.map +1 -0
- package/dist/src/registry.d.ts +12 -0
- package/dist/src/registry.d.ts.map +1 -0
- package/dist/src/registry.js +30 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/src/services/base.d.ts +98 -0
- package/dist/src/services/base.d.ts.map +1 -0
- package/dist/src/services/base.js +137 -0
- package/dist/src/services/base.js.map +1 -0
- package/dist/src/services/discord.d.ts +20 -0
- package/dist/src/services/discord.d.ts.map +1 -0
- package/dist/src/services/discord.js +55 -0
- package/dist/src/services/discord.js.map +1 -0
- package/dist/src/services/dropbox.d.ts +23 -0
- package/dist/src/services/dropbox.d.ts.map +1 -0
- package/dist/src/services/dropbox.js +136 -0
- package/dist/src/services/dropbox.js.map +1 -0
- package/dist/src/services/github.d.ts +23 -0
- package/dist/src/services/github.d.ts.map +1 -0
- package/dist/src/services/github.js +110 -0
- package/dist/src/services/github.js.map +1 -0
- package/dist/src/services/index.d.ts +12 -0
- package/dist/src/services/index.d.ts.map +1 -0
- package/dist/src/services/index.js +11 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/linear.d.ts +23 -0
- package/dist/src/services/linear.d.ts.map +1 -0
- package/dist/src/services/linear.js +110 -0
- package/dist/src/services/linear.js.map +1 -0
- package/dist/src/services/slack.d.ts +21 -0
- package/dist/src/services/slack.d.ts.map +1 -0
- package/dist/src/services/slack.js +67 -0
- package/dist/src/services/slack.js.map +1 -0
- package/dist/tests/apiCredentialStore.test.d.ts +2 -0
- package/dist/tests/apiCredentialStore.test.d.ts.map +1 -0
- package/dist/tests/apiCredentialStore.test.js +130 -0
- package/dist/tests/apiCredentialStore.test.js.map +1 -0
- package/dist/tests/apiCredentials.test.d.ts +2 -0
- package/dist/tests/apiCredentials.test.d.ts.map +1 -0
- package/dist/tests/apiCredentials.test.js +169 -0
- package/dist/tests/apiCredentials.test.js.map +1 -0
- package/dist/tests/cli.test.d.ts +2 -0
- package/dist/tests/cli.test.d.ts.map +1 -0
- package/dist/tests/cli.test.js +584 -0
- package/dist/tests/cli.test.js.map +1 -0
- package/dist/tests/encryptedStorage.test.d.ts +2 -0
- package/dist/tests/encryptedStorage.test.d.ts.map +1 -0
- package/dist/tests/encryptedStorage.test.js +126 -0
- package/dist/tests/encryptedStorage.test.js.map +1 -0
- package/dist/tests/encryption.test.d.ts +2 -0
- package/dist/tests/encryption.test.d.ts.map +1 -0
- package/dist/tests/encryption.test.js +121 -0
- package/dist/tests/encryption.test.js.map +1 -0
- package/dist/tests/lint.test.d.ts +2 -0
- package/dist/tests/lint.test.d.ts.map +1 -0
- package/dist/tests/lint.test.js +18 -0
- package/dist/tests/lint.test.js.map +1 -0
- package/dist/tests/registry.test.d.ts +2 -0
- package/dist/tests/registry.test.d.ts.map +1 -0
- package/dist/tests/registry.test.js +85 -0
- package/dist/tests/registry.test.js.map +1 -0
- package/dist/tests/servicesAgainstRecordings.test.d.ts +20 -0
- package/dist/tests/servicesAgainstRecordings.test.d.ts.map +1 -0
- package/dist/tests/servicesAgainstRecordings.test.js +157 -0
- package/dist/tests/servicesAgainstRecordings.test.js.map +1 -0
- package/dist/tests/typecheck.test.d.ts +2 -0
- package/dist/tests/typecheck.test.d.ts.map +1 -0
- package/dist/tests/typecheck.test.js +18 -0
- package/dist/tests/typecheck.test.js.map +1 -0
- package/docs/development.md +94 -0
- package/eslint.config.js +30 -0
- package/integrations/SKILL.md +62 -0
- package/package.json +68 -0
- package/scripts/cryptFile.ts +123 -0
- package/scripts/recordBrowserSession.ts +280 -0
- package/scripts/tsconfig.json +10 -0
- package/src/apiCredentialStore.ts +87 -0
- package/src/apiCredentials.ts +180 -0
- package/src/cli.ts +32 -0
- package/src/cliCommands.ts +321 -0
- package/src/config.ts +115 -0
- package/src/curl.ts +78 -0
- package/src/encryptedStorage.ts +161 -0
- package/src/encryption.ts +106 -0
- package/src/index.ts +65 -0
- package/src/keychain.ts +105 -0
- package/src/playwrightUtils.ts +143 -0
- package/src/registry.ts +35 -0
- package/src/services/base.ts +234 -0
- package/src/services/discord.ts +73 -0
- package/src/services/dropbox.ts +173 -0
- package/src/services/github.ts +139 -0
- package/src/services/index.ts +13 -0
- package/src/services/linear.ts +134 -0
- package/src/services/slack.ts +85 -0
- package/tests/apiCredentialStore.test.ts +162 -0
- package/tests/apiCredentials.test.ts +195 -0
- package/tests/cli.test.ts +798 -0
- package/tests/encryptedStorage.test.ts +173 -0
- package/tests/encryption.test.ts +169 -0
- package/tests/lint.test.ts +19 -0
- package/tests/registry.test.ts +103 -0
- package/tests/servicesAgainstRecordings.test.ts +230 -0
- package/tests/typecheck.test.ts +19 -0
- package/tsconfig.json +24 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command implementations with dependency injection for testability.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, unlinkSync } from 'node:fs';
|
|
5
|
+
import { createInterface } from 'node:readline';
|
|
6
|
+
import { ApiCredentialStore } from './apiCredentialStore.js';
|
|
7
|
+
import { ApiCredentialStatus } from './apiCredentials.js';
|
|
8
|
+
import { CONFIG } from './config.js';
|
|
9
|
+
import { EncryptedStorage } from './encryptedStorage.js';
|
|
10
|
+
import { REGISTRY } from './registry.js';
|
|
11
|
+
import { LoginCancelledError, LoginFailedError } from './services/index.js';
|
|
12
|
+
import { run as curlRun } from './curl.js';
|
|
13
|
+
// Curl flags that don't affect the HTTP request semantics but may not be supported by URL extraction.
|
|
14
|
+
const CURL_PASSTHROUGH_FLAGS = new Set(['-v', '--verbose']);
|
|
15
|
+
/**
|
|
16
|
+
* Default implementation of CLI dependencies.
|
|
17
|
+
*/
|
|
18
|
+
export function createDefaultDependencies() {
|
|
19
|
+
return {
|
|
20
|
+
registry: REGISTRY,
|
|
21
|
+
config: CONFIG,
|
|
22
|
+
runCurl: curlRun,
|
|
23
|
+
confirm: defaultConfirm,
|
|
24
|
+
exit: (code) => process.exit(code),
|
|
25
|
+
log: (message) => {
|
|
26
|
+
console.log(message);
|
|
27
|
+
},
|
|
28
|
+
errorLog: (message) => {
|
|
29
|
+
console.error(message);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function filterPassthroughFlags(args) {
|
|
34
|
+
return args.filter((arg) => !CURL_PASSTHROUGH_FLAGS.has(arg));
|
|
35
|
+
}
|
|
36
|
+
export function extractUrlFromCurlArguments(args) {
|
|
37
|
+
const filteredArgs = filterPassthroughFlags(args);
|
|
38
|
+
// Simple URL extraction: look for arguments that look like URLs
|
|
39
|
+
// or parse known curl argument patterns
|
|
40
|
+
for (let i = 0; i < filteredArgs.length; i++) {
|
|
41
|
+
const arg = filteredArgs[i];
|
|
42
|
+
if (arg === undefined)
|
|
43
|
+
continue;
|
|
44
|
+
// Skip flags and their values
|
|
45
|
+
if (arg.startsWith('-')) {
|
|
46
|
+
// Skip flags that take a value
|
|
47
|
+
if (['-H', '-d', '-X', '-o', '-w', '-u', '-A', '-e', '-b', '-c', '-F', '-T'].includes(arg)) {
|
|
48
|
+
i++; // Skip the next argument which is the value
|
|
49
|
+
}
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
// This looks like a URL
|
|
53
|
+
if (arg.startsWith('http://') || arg.startsWith('https://')) {
|
|
54
|
+
return arg;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
async function defaultConfirm(message) {
|
|
60
|
+
const readline = createInterface({
|
|
61
|
+
input: process.stdin,
|
|
62
|
+
output: process.stdout,
|
|
63
|
+
});
|
|
64
|
+
return new Promise((resolve) => {
|
|
65
|
+
readline.question(`${message} (y/N) `, (answer) => {
|
|
66
|
+
readline.close();
|
|
67
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
async function clearAll(deps, yes) {
|
|
72
|
+
const latchkeyStore = deps.config.credentialStorePath;
|
|
73
|
+
const browserState = deps.config.browserStatePath;
|
|
74
|
+
const filesToDelete = [];
|
|
75
|
+
if (existsSync(latchkeyStore)) {
|
|
76
|
+
filesToDelete.push(latchkeyStore);
|
|
77
|
+
}
|
|
78
|
+
if (existsSync(browserState)) {
|
|
79
|
+
filesToDelete.push(browserState);
|
|
80
|
+
}
|
|
81
|
+
if (filesToDelete.length === 0) {
|
|
82
|
+
deps.log('No files to delete.');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (!yes) {
|
|
86
|
+
deps.log('This will delete the following files:');
|
|
87
|
+
for (const filePath of filesToDelete) {
|
|
88
|
+
deps.log(` ${filePath}`);
|
|
89
|
+
}
|
|
90
|
+
const confirmed = await deps.confirm('Are you sure you want to continue?');
|
|
91
|
+
if (!confirmed) {
|
|
92
|
+
deps.log('Aborted.');
|
|
93
|
+
deps.exit(1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (const filePath of filesToDelete) {
|
|
97
|
+
unlinkSync(filePath);
|
|
98
|
+
if (filePath === latchkeyStore) {
|
|
99
|
+
deps.log(`Deleted credentials store: ${filePath}`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
deps.log(`Deleted browser state: ${filePath}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function createEncryptedStorageFromConfig(config) {
|
|
107
|
+
return new EncryptedStorage({
|
|
108
|
+
encryptionKeyOverride: config.encryptionKeyOverride,
|
|
109
|
+
serviceName: config.serviceName,
|
|
110
|
+
accountName: config.accountName,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function clearService(deps, serviceName) {
|
|
114
|
+
const service = deps.registry.getByName(serviceName);
|
|
115
|
+
if (service === null) {
|
|
116
|
+
deps.errorLog(`Error: Unknown service: ${serviceName}`);
|
|
117
|
+
deps.errorLog("Use 'latchkey services' to see available services.");
|
|
118
|
+
deps.exit(1);
|
|
119
|
+
}
|
|
120
|
+
const encryptedStorage = createEncryptedStorageFromConfig(deps.config);
|
|
121
|
+
const apiCredentialStore = new ApiCredentialStore(deps.config.credentialStorePath, encryptedStorage);
|
|
122
|
+
const deleted = apiCredentialStore.delete(serviceName);
|
|
123
|
+
if (deleted) {
|
|
124
|
+
deps.log(`API credentials for ${serviceName} have been cleared.`);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
deps.log(`No API credentials found for ${serviceName}.`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Register all CLI commands on the given program.
|
|
132
|
+
*/
|
|
133
|
+
export function registerCommands(program, deps) {
|
|
134
|
+
program
|
|
135
|
+
.command('services')
|
|
136
|
+
.description('List known and supported third-party services.')
|
|
137
|
+
.action(() => {
|
|
138
|
+
const serviceNames = deps.registry.services.map((service) => service.name);
|
|
139
|
+
deps.log(serviceNames.join(' '));
|
|
140
|
+
});
|
|
141
|
+
program
|
|
142
|
+
.command('clear')
|
|
143
|
+
.description('Clear stored API credentials.')
|
|
144
|
+
.argument('[service_name]', 'Name of the service to clear API credentials for')
|
|
145
|
+
.option('-y, --yes', 'Skip confirmation prompt when clearing all data')
|
|
146
|
+
.action(async (serviceName, options) => {
|
|
147
|
+
if (serviceName === undefined) {
|
|
148
|
+
await clearAll(deps, options.yes ?? false);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
clearService(deps, serviceName);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
program
|
|
155
|
+
.command('status')
|
|
156
|
+
.description('Check the API credential status for a service.')
|
|
157
|
+
.argument('[service_name]', 'Name of the service to check status for')
|
|
158
|
+
.action((serviceName) => {
|
|
159
|
+
const encryptedStorage = createEncryptedStorageFromConfig(deps.config);
|
|
160
|
+
const apiCredentialStore = new ApiCredentialStore(deps.config.credentialStorePath, encryptedStorage);
|
|
161
|
+
if (serviceName === undefined) {
|
|
162
|
+
for (const service of deps.registry.services) {
|
|
163
|
+
const apiCredentials = apiCredentialStore.get(service.name);
|
|
164
|
+
if (apiCredentials === null) {
|
|
165
|
+
deps.log(`${service.name}: ${ApiCredentialStatus.Missing}`);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
const status = service.checkApiCredentials(apiCredentials);
|
|
169
|
+
deps.log(`${service.name}: ${status}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const service = deps.registry.getByName(serviceName);
|
|
175
|
+
if (service === null) {
|
|
176
|
+
deps.errorLog(`Error: Unknown service: ${serviceName}`);
|
|
177
|
+
deps.errorLog("Use 'latchkey services' to see available services.");
|
|
178
|
+
deps.exit(1);
|
|
179
|
+
}
|
|
180
|
+
const apiCredentials = apiCredentialStore.get(serviceName);
|
|
181
|
+
if (apiCredentials === null) {
|
|
182
|
+
deps.log(ApiCredentialStatus.Missing);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const apiCredentialStatus = service.checkApiCredentials(apiCredentials);
|
|
186
|
+
deps.log(apiCredentialStatus);
|
|
187
|
+
});
|
|
188
|
+
program
|
|
189
|
+
.command('login')
|
|
190
|
+
.description('Login to a service and store the API credentials.')
|
|
191
|
+
.argument('<service_name>', 'Name of the service to login to')
|
|
192
|
+
.action(async (serviceName) => {
|
|
193
|
+
const service = deps.registry.getByName(serviceName);
|
|
194
|
+
if (service === null) {
|
|
195
|
+
deps.errorLog(`Error: Unknown service: ${serviceName}`);
|
|
196
|
+
deps.errorLog("Use 'latchkey services' to see available services.");
|
|
197
|
+
deps.exit(1);
|
|
198
|
+
}
|
|
199
|
+
const encryptedStorage = createEncryptedStorageFromConfig(deps.config);
|
|
200
|
+
const apiCredentialStore = new ApiCredentialStore(deps.config.credentialStorePath, encryptedStorage);
|
|
201
|
+
try {
|
|
202
|
+
const apiCredentials = await service
|
|
203
|
+
.getSession()
|
|
204
|
+
.login(encryptedStorage, deps.config.browserStatePath);
|
|
205
|
+
apiCredentialStore.save(service.name, apiCredentials);
|
|
206
|
+
deps.log('Done');
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
if (error instanceof LoginCancelledError) {
|
|
210
|
+
deps.errorLog('Login cancelled.');
|
|
211
|
+
deps.exit(1);
|
|
212
|
+
}
|
|
213
|
+
if (error instanceof LoginFailedError) {
|
|
214
|
+
deps.errorLog(error.message);
|
|
215
|
+
deps.exit(1);
|
|
216
|
+
}
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
program
|
|
221
|
+
.command('curl')
|
|
222
|
+
.description('Run curl with API credential injection.')
|
|
223
|
+
.allowUnknownOption()
|
|
224
|
+
.allowExcessArguments()
|
|
225
|
+
.action(async (_options, command) => {
|
|
226
|
+
const curlArguments = command.args;
|
|
227
|
+
const url = extractUrlFromCurlArguments(curlArguments);
|
|
228
|
+
if (url === null) {
|
|
229
|
+
deps.errorLog('Error: Could not extract URL from curl arguments.');
|
|
230
|
+
deps.exit(1);
|
|
231
|
+
}
|
|
232
|
+
const service = deps.registry.getByUrl(url);
|
|
233
|
+
if (service === null) {
|
|
234
|
+
deps.errorLog(`Error: No service matches URL: ${url}`);
|
|
235
|
+
deps.exit(1);
|
|
236
|
+
}
|
|
237
|
+
const encryptedStorage = createEncryptedStorageFromConfig(deps.config);
|
|
238
|
+
const apiCredentialStore = new ApiCredentialStore(deps.config.credentialStorePath, encryptedStorage);
|
|
239
|
+
let apiCredentials = apiCredentialStore.get(service.name);
|
|
240
|
+
if (apiCredentials === null) {
|
|
241
|
+
try {
|
|
242
|
+
apiCredentials = await service
|
|
243
|
+
.getSession()
|
|
244
|
+
.login(encryptedStorage, deps.config.browserStatePath);
|
|
245
|
+
apiCredentialStore.save(service.name, apiCredentials);
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
if (error instanceof LoginCancelledError) {
|
|
249
|
+
deps.errorLog('Login cancelled.');
|
|
250
|
+
deps.exit(1);
|
|
251
|
+
}
|
|
252
|
+
if (error instanceof LoginFailedError) {
|
|
253
|
+
deps.errorLog(error.message);
|
|
254
|
+
deps.exit(1);
|
|
255
|
+
}
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const allArguments = [...apiCredentials.asCurlArguments(), ...curlArguments];
|
|
260
|
+
const result = deps.runCurl(allArguments);
|
|
261
|
+
deps.exit(result.returncode);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=cliCommands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliCommands.js","sourceRoot":"","sources":["../../src/cliCommands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for Latchkey.
|
|
3
|
+
*/
|
|
4
|
+
export declare class InsecureFilePermissionsError extends Error {
|
|
5
|
+
constructor(filePath: string, permissions: number);
|
|
6
|
+
}
|
|
7
|
+
export declare const DEFAULT_KEYRING_SERVICE_NAME = "latchkey";
|
|
8
|
+
export declare const DEFAULT_KEYRING_ACCOUNT_NAME = "encryption-key";
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for Latchkey, sourced from environment variables with sensible defaults.
|
|
11
|
+
*/
|
|
12
|
+
export declare class Config {
|
|
13
|
+
readonly credentialStorePath: string;
|
|
14
|
+
readonly browserStatePath: string;
|
|
15
|
+
readonly curlCommand: string;
|
|
16
|
+
/**
|
|
17
|
+
* Encryption key override from environment variable.
|
|
18
|
+
* If set, this key will be used instead of the system keychain.
|
|
19
|
+
* The key should be a base64-encoded 256-bit (32-byte) value.
|
|
20
|
+
*/
|
|
21
|
+
readonly encryptionKeyOverride: string | null;
|
|
22
|
+
readonly serviceName: string;
|
|
23
|
+
readonly accountName: string;
|
|
24
|
+
constructor(getEnv?: (name: string) => string | undefined);
|
|
25
|
+
/**
|
|
26
|
+
* Check that sensitive files have secure permissions.
|
|
27
|
+
* Throws InsecureFilePermissionsError if any file is readable by group or others.
|
|
28
|
+
*/
|
|
29
|
+
checkSensitiveFilePermissions(): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Global configuration singleton, initialized from process.env at import time.
|
|
33
|
+
*/
|
|
34
|
+
export declare const CONFIG: Config;
|
|
35
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,qBAAa,4BAA6B,SAAQ,KAAK;gBACzC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CAOlD;AASD,eAAO,MAAM,4BAA4B,aAAa,CAAC;AACvD,eAAO,MAAM,4BAA4B,mBAAmB,CAAC;AAmB7D;;GAEG;AACH,qBAAa,MAAM;IACjB,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAuC;IAwBtF;;;OAGG;IACH,6BAA6B,IAAI,IAAI;CAmBtC;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,QAAe,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for Latchkey.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, statSync } from 'node:fs';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { join, resolve } from 'node:path';
|
|
7
|
+
import { isKeychainAvailable } from './keychain.js';
|
|
8
|
+
export class InsecureFilePermissionsError extends Error {
|
|
9
|
+
constructor(filePath, permissions) {
|
|
10
|
+
const permissionsOctal = permissions.toString(8).padStart(3, '0');
|
|
11
|
+
super(`File ${filePath} has insecure permissions (${permissionsOctal}). Run: chmod 600 ${filePath}`);
|
|
12
|
+
this.name = 'InsecureFilePermissionsError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const LATCHKEY_STORE_ENV_VAR = 'LATCHKEY_STORE';
|
|
16
|
+
const LATCHKEY_BROWSER_STATE_ENV_VAR = 'LATCHKEY_BROWSER_STATE';
|
|
17
|
+
const LATCHKEY_CURL_PATH_ENV_VAR = 'LATCHKEY_CURL_PATH';
|
|
18
|
+
const LATCHKEY_ENCRYPTION_KEY_ENV_VAR = 'LATCHKEY_ENCRYPTION_KEY';
|
|
19
|
+
const LATCHKEY_KEYRING_SERVICE_NAME_ENV_VAR = 'LATCHKEY_KEYRING_SERVICE_NAME';
|
|
20
|
+
const LATCHKEY_KEYRING_ACCOUNT_NAME_ENV_VAR = 'LATCHKEY_KEYRING_ACCOUNT_NAME';
|
|
21
|
+
export const DEFAULT_KEYRING_SERVICE_NAME = 'latchkey';
|
|
22
|
+
export const DEFAULT_KEYRING_ACCOUNT_NAME = 'encryption-key';
|
|
23
|
+
function getDefaultCredentialStorePath(encryptionEnabled) {
|
|
24
|
+
const filename = encryptionEnabled ? 'credentials.json.enc' : 'credentials.json';
|
|
25
|
+
return join(homedir(), '.latchkey', filename);
|
|
26
|
+
}
|
|
27
|
+
function getDefaultBrowserStatePath(encryptionEnabled) {
|
|
28
|
+
const filename = encryptionEnabled ? 'browser_state.json.enc' : 'browser_state.json';
|
|
29
|
+
return join(homedir(), '.latchkey', filename);
|
|
30
|
+
}
|
|
31
|
+
function resolvePathWithTildeExpansion(path) {
|
|
32
|
+
if (path.startsWith('~')) {
|
|
33
|
+
return resolve(homedir(), path.slice(2));
|
|
34
|
+
}
|
|
35
|
+
return resolve(path);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Configuration for Latchkey, sourced from environment variables with sensible defaults.
|
|
39
|
+
*/
|
|
40
|
+
export class Config {
|
|
41
|
+
credentialStorePath;
|
|
42
|
+
browserStatePath;
|
|
43
|
+
curlCommand;
|
|
44
|
+
/**
|
|
45
|
+
* Encryption key override from environment variable.
|
|
46
|
+
* If set, this key will be used instead of the system keychain.
|
|
47
|
+
* The key should be a base64-encoded 256-bit (32-byte) value.
|
|
48
|
+
*/
|
|
49
|
+
encryptionKeyOverride;
|
|
50
|
+
serviceName;
|
|
51
|
+
accountName;
|
|
52
|
+
constructor(getEnv = (name) => process.env[name]) {
|
|
53
|
+
this.curlCommand = getEnv(LATCHKEY_CURL_PATH_ENV_VAR) ?? 'curl';
|
|
54
|
+
this.encryptionKeyOverride = getEnv(LATCHKEY_ENCRYPTION_KEY_ENV_VAR) ?? null;
|
|
55
|
+
this.serviceName =
|
|
56
|
+
getEnv(LATCHKEY_KEYRING_SERVICE_NAME_ENV_VAR) ?? DEFAULT_KEYRING_SERVICE_NAME;
|
|
57
|
+
this.accountName =
|
|
58
|
+
getEnv(LATCHKEY_KEYRING_ACCOUNT_NAME_ENV_VAR) ?? DEFAULT_KEYRING_ACCOUNT_NAME;
|
|
59
|
+
// Determine if encryption will be enabled (either via key override or keychain)
|
|
60
|
+
const encryptionEnabled = this.encryptionKeyOverride !== null ||
|
|
61
|
+
isKeychainAvailable(this.serviceName, this.accountName);
|
|
62
|
+
const credentialStoreEnv = getEnv(LATCHKEY_STORE_ENV_VAR);
|
|
63
|
+
this.credentialStorePath = credentialStoreEnv
|
|
64
|
+
? resolvePathWithTildeExpansion(credentialStoreEnv)
|
|
65
|
+
: getDefaultCredentialStorePath(encryptionEnabled);
|
|
66
|
+
const browserStateEnv = getEnv(LATCHKEY_BROWSER_STATE_ENV_VAR);
|
|
67
|
+
this.browserStatePath = browserStateEnv
|
|
68
|
+
? resolvePathWithTildeExpansion(browserStateEnv)
|
|
69
|
+
: getDefaultBrowserStatePath(encryptionEnabled);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check that sensitive files have secure permissions.
|
|
73
|
+
* Throws InsecureFilePermissionsError if any file is readable by group or others.
|
|
74
|
+
*/
|
|
75
|
+
checkSensitiveFilePermissions() {
|
|
76
|
+
const filesToCheck = [this.credentialStorePath, this.browserStatePath];
|
|
77
|
+
for (const filePath of filesToCheck) {
|
|
78
|
+
if (!existsSync(filePath)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const stats = statSync(filePath);
|
|
82
|
+
if (stats.isDirectory()) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const permissions = stats.mode & 0o777;
|
|
86
|
+
if ((permissions & 0o077) !== 0) {
|
|
87
|
+
throw new InsecureFilePermissionsError(filePath, permissions);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Global configuration singleton, initialized from process.env at import time.
|
|
94
|
+
*/
|
|
95
|
+
export const CONFIG = new Config();
|
|
96
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curl subprocess utilities.
|
|
3
|
+
*/
|
|
4
|
+
export interface CurlResult {
|
|
5
|
+
readonly returncode: number;
|
|
6
|
+
readonly stdout: string;
|
|
7
|
+
readonly stderr: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Type for the subprocess runner function (no output capture, for interactive use).
|
|
11
|
+
*/
|
|
12
|
+
export type SubprocessRunner = (args: readonly string[]) => CurlResult;
|
|
13
|
+
/**
|
|
14
|
+
* Type for the capturing subprocess runner function (captures output).
|
|
15
|
+
*/
|
|
16
|
+
export type CapturingSubprocessRunner = (args: readonly string[], timeout: number) => CurlResult;
|
|
17
|
+
export declare function setSubprocessRunner(runner: SubprocessRunner): void;
|
|
18
|
+
export declare function resetSubprocessRunner(): void;
|
|
19
|
+
export declare function setCapturingSubprocessRunner(runner: CapturingSubprocessRunner): void;
|
|
20
|
+
export declare function resetCapturingSubprocessRunner(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Run curl without capturing output (for interactive CLI use).
|
|
23
|
+
*/
|
|
24
|
+
export declare function run(args: readonly string[]): CurlResult;
|
|
25
|
+
/**
|
|
26
|
+
* Run curl with output capture (for credential checking).
|
|
27
|
+
*/
|
|
28
|
+
export declare function runCaptured(args: readonly string[], timeout?: number): CurlResult;
|
|
29
|
+
//# sourceMappingURL=curl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curl.d.ts","sourceRoot":"","sources":["../../src/curl.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,UAAU,CAAC;AAEvE;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,KAAK,UAAU,CAAC;AA4BjG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAElE;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI,CAEpF;AAED,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAEvD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,SAAK,GAAG,UAAU,CAE7E"}
|
package/dist/src/curl.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curl subprocess utilities.
|
|
3
|
+
*/
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
import { CONFIG } from './config.js';
|
|
6
|
+
function defaultSubprocessRunner(args) {
|
|
7
|
+
const result = spawnSync(CONFIG.curlCommand, args, {
|
|
8
|
+
stdio: ['inherit', 'inherit', 'inherit'],
|
|
9
|
+
});
|
|
10
|
+
return {
|
|
11
|
+
returncode: result.status ?? 1,
|
|
12
|
+
stdout: '',
|
|
13
|
+
stderr: '',
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function defaultCapturingSubprocessRunner(args, timeout) {
|
|
17
|
+
const result = spawnSync(CONFIG.curlCommand, args, {
|
|
18
|
+
encoding: 'utf-8',
|
|
19
|
+
timeout: timeout * 1000,
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
returncode: result.status ?? 1,
|
|
23
|
+
stdout: result.stdout,
|
|
24
|
+
stderr: result.stderr,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
let subprocessRunner = defaultSubprocessRunner;
|
|
28
|
+
let capturingSubprocessRunner = defaultCapturingSubprocessRunner;
|
|
29
|
+
export function setSubprocessRunner(runner) {
|
|
30
|
+
subprocessRunner = runner;
|
|
31
|
+
}
|
|
32
|
+
export function resetSubprocessRunner() {
|
|
33
|
+
subprocessRunner = defaultSubprocessRunner;
|
|
34
|
+
}
|
|
35
|
+
export function setCapturingSubprocessRunner(runner) {
|
|
36
|
+
capturingSubprocessRunner = runner;
|
|
37
|
+
}
|
|
38
|
+
export function resetCapturingSubprocessRunner() {
|
|
39
|
+
capturingSubprocessRunner = defaultCapturingSubprocessRunner;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Run curl without capturing output (for interactive CLI use).
|
|
43
|
+
*/
|
|
44
|
+
export function run(args) {
|
|
45
|
+
return subprocessRunner(args);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Run curl with output capture (for credential checking).
|
|
49
|
+
*/
|
|
50
|
+
export function runCaptured(args, timeout = 10) {
|
|
51
|
+
return capturingSubprocessRunner(args, timeout);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=curl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curl.js","sourceRoot":"","sources":["../../src/curl.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAoB,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAkBrC,SAAS,uBAAuB,CAAC,IAAuB;IACtD,MAAM,MAAM,GAA6B,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,IAAgB,EAAE;QACvF,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;KACzC,CAAC,CAAC;IACH,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC;QAC9B,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC;AAED,SAAS,gCAAgC,CAAC,IAAuB,EAAE,OAAe;IAChF,MAAM,MAAM,GAA6B,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,IAAgB,EAAE;QACvF,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,OAAO,GAAG,IAAI;KACxB,CAAC,CAAC;IACH,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC;QAC9B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC;AACJ,CAAC;AAED,IAAI,gBAAgB,GAAqB,uBAAuB,CAAC;AACjE,IAAI,yBAAyB,GAA8B,gCAAgC,CAAC;AAE5F,MAAM,UAAU,mBAAmB,CAAC,MAAwB;IAC1D,gBAAgB,GAAG,MAAM,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,gBAAgB,GAAG,uBAAuB,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,MAAiC;IAC5E,yBAAyB,GAAG,MAAM,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC5C,yBAAyB,GAAG,gCAAgC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,CAAC,IAAuB;IACzC,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,IAAuB,EAAE,OAAO,GAAG,EAAE;IAC/D,OAAO,yBAAyB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encrypted file storage with automatic key management.
|
|
3
|
+
* Encryption keys are retrieved from:
|
|
4
|
+
* 1. Provided encryptionKeyOverride option
|
|
5
|
+
* 2. System keychain
|
|
6
|
+
* 3. Generated and stored in keychain (first run)
|
|
7
|
+
*
|
|
8
|
+
* Falls back to unencrypted storage with chmod 600 if keychain is unavailable.
|
|
9
|
+
*/
|
|
10
|
+
export declare class EncryptedStorageError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class PathIsDirectoryError extends Error {
|
|
14
|
+
constructor(filePath: string);
|
|
15
|
+
}
|
|
16
|
+
export interface EncryptedStorageOptions {
|
|
17
|
+
encryptionKeyOverride?: string | null;
|
|
18
|
+
serviceName?: string;
|
|
19
|
+
accountName?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Manages encrypted file storage with automatic key handling.
|
|
23
|
+
*/
|
|
24
|
+
export declare class EncryptedStorage {
|
|
25
|
+
private readonly key;
|
|
26
|
+
constructor(options?: EncryptedStorageOptions);
|
|
27
|
+
private static initializeKey;
|
|
28
|
+
private isEncryptionEnabled;
|
|
29
|
+
/**
|
|
30
|
+
* Read and decrypt a file.
|
|
31
|
+
*/
|
|
32
|
+
readFile(filePath: string): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Encrypt and write data to a file.
|
|
35
|
+
* Creates parent directories. New files are created with chmod 600.
|
|
36
|
+
*/
|
|
37
|
+
writeFile(filePath: string, content: string): void;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=encryptedStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryptedStorage.d.ts","sourceRoot":"","sources":["../../src/encryptedStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAeH,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,QAAQ,EAAE,MAAM;CAI7B;AAED,MAAM,WAAW,uBAAuB;IACtC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;gBAExB,OAAO,GAAE,uBAA4B;IAIjD,OAAO,CAAC,MAAM,CAAC,aAAa;IAkC5B,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAsCzC;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CAwBnD"}
|