latchkey 0.1.4 → 0.2.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/LICENSE +1 -1
- package/README.md +4 -4
- package/dist/integrations/SKILL.md +71 -0
- package/dist/package.json +67 -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/src/apiCredentials.d.ts +83 -1
- package/dist/src/apiCredentials.d.ts.map +1 -1
- package/dist/src/apiCredentials.js +83 -1
- package/dist/src/apiCredentials.js.map +1 -1
- 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.js +2 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/cliCommands.d.ts.map +1 -1
- package/dist/src/cliCommands.js +122 -17
- package/dist/src/cliCommands.js.map +1 -1
- package/dist/src/oauthUtils.d.ts +49 -0
- package/dist/src/oauthUtils.d.ts.map +1 -0
- package/dist/src/oauthUtils.js +183 -0
- package/dist/src/oauthUtils.js.map +1 -0
- package/dist/src/playwrightUtils.d.ts +8 -1
- package/dist/src/playwrightUtils.d.ts.map +1 -1
- package/dist/src/playwrightUtils.js +25 -8
- package/dist/src/playwrightUtils.js.map +1 -1
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +2 -2
- package/dist/src/registry.js.map +1 -1
- package/dist/src/services/base.d.ts +31 -5
- package/dist/src/services/base.d.ts.map +1 -1
- package/dist/src/services/base.js +12 -8
- package/dist/src/services/base.js.map +1 -1
- package/dist/src/services/discord.d.ts +2 -0
- package/dist/src/services/discord.d.ts.map +1 -1
- package/dist/src/services/discord.js +3 -0
- package/dist/src/services/discord.js.map +1 -1
- package/dist/src/services/dropbox.d.ts +3 -1
- package/dist/src/services/dropbox.d.ts.map +1 -1
- package/dist/src/services/dropbox.js +7 -5
- package/dist/src/services/dropbox.js.map +1 -1
- package/dist/src/services/github.d.ts +3 -1
- package/dist/src/services/github.d.ts.map +1 -1
- package/dist/src/services/github.js +18 -8
- package/dist/src/services/github.js.map +1 -1
- package/dist/src/services/google.d.ts +35 -0
- package/dist/src/services/google.d.ts.map +1 -0
- package/dist/src/services/google.js +358 -0
- package/dist/src/services/google.js.map +1 -0
- package/dist/src/services/index.d.ts +2 -0
- package/dist/src/services/index.d.ts.map +1 -1
- package/dist/src/services/index.js +2 -0
- package/dist/src/services/index.js.map +1 -1
- package/dist/src/services/linear.d.ts +3 -1
- package/dist/src/services/linear.d.ts.map +1 -1
- package/dist/src/services/linear.js +7 -6
- package/dist/src/services/linear.js.map +1 -1
- package/dist/src/services/notion.d.ts +30 -0
- package/dist/src/services/notion.d.ts.map +1 -0
- package/dist/src/services/notion.js +121 -0
- package/dist/src/services/notion.js.map +1 -0
- package/dist/src/services/slack.d.ts +2 -0
- package/dist/src/services/slack.d.ts.map +1 -1
- package/dist/src/services/slack.js +3 -0
- package/dist/src/services/slack.js.map +1 -1
- package/dist/src/skillMd.d.ts +2 -0
- package/dist/src/skillMd.d.ts.map +1 -0
- package/dist/src/skillMd.js +19 -0
- package/dist/src/skillMd.js.map +1 -0
- package/dist/tests/cli.test.js +38 -1
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/registry.test.js +16 -3
- package/dist/tests/registry.test.js.map +1 -1
- package/package.json +5 -5
package/LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright 2026 Imbue
|
|
1
|
+
Copyright 2026 Imbue, Inc.
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
4
|
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ latchkey curl -X POST 'https://slack.com/api/conversations.create' \
|
|
|
15
15
|
Latchkey is a command-line tool that injects credentials to curl requests to known public APIs.
|
|
16
16
|
|
|
17
17
|
- `latchkey services`
|
|
18
|
-
- Get a list of known and supported third-party services (Slack,
|
|
18
|
+
- Get a list of known and supported third-party services (Slack, Google Workspace, Linear, GitHub, etc.).
|
|
19
19
|
- `latchkey curl <arguments>`
|
|
20
20
|
- Automatically inject credentials to your otherwise standard curl calls to public APIs.
|
|
21
21
|
- (The first time you access a service, a browser pop-up with a login screen appears.)
|
|
@@ -63,19 +63,19 @@ you're willing to accept the risks.
|
|
|
63
63
|
### OpenCode
|
|
64
64
|
```
|
|
65
65
|
mkdir -p ~/.opencode/skills/latchkey
|
|
66
|
-
|
|
66
|
+
latchkey skill-md > ~/.opencode/skills/latchkey/SKILL.md
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
### Claude Code
|
|
70
70
|
```
|
|
71
71
|
mkdir -p ~/.claude/skills/latchkey
|
|
72
|
-
|
|
72
|
+
latchkey skill-md > ~/.claude/skills/latchkey/SKILL.md
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
### Codex
|
|
76
76
|
```
|
|
77
77
|
mkdir -p ~/.codex/skills/latchkey
|
|
78
|
-
|
|
78
|
+
latchkey skill-md > ~/.codex/skills/latchkey/SKILL.md
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
### Passepartout
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: latchkey
|
|
3
|
+
description: Interact with third-party services (Slack, Google Workspace, Dropbox, GitHub, Linear...) on user's behalf using their public APIs.
|
|
4
|
+
compatibility: Requires node.js, curl, latchkey (npm install -g latchkey) and a desktop/GUI environment.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Latchkey
|
|
8
|
+
|
|
9
|
+
## Instructions
|
|
10
|
+
|
|
11
|
+
Latchkey is a CLI tool that automatically injects credentials into curl commands for supported public APIs. Instead of manually managing API tokens, latchkey opens a browser for login, extracts credentials from the session, and injects them into your curl requests.
|
|
12
|
+
|
|
13
|
+
Use this skill when the user asks you to work with third-party services like Slack, Discord, Dropbox, Github, Linear and others on their behalf.
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
|
|
17
|
+
1. **Use `latchkey curl`** instead of regular `curl` for supported services.
|
|
18
|
+
2. **Use `latchkey info <service_name>`** to get developer notes about a specific service (API docs links, special requirements, etc.).
|
|
19
|
+
3. **Look for the newest documentation of the desired public API online.** Avoid bot-only endpoints if such a distinction exists.
|
|
20
|
+
4. **Pass through all regular curl arguments** - latchkey is a transparent wrapper.
|
|
21
|
+
5. **Use `latchkey status <service_name>`** when you notice potentially expired credentials.
|
|
22
|
+
6. When the status is `invalid`, **force a new login by calling `latchkey clear <service_name>`**, then retry the curl command.
|
|
23
|
+
7. **Do not force a new login if the status is `valid`** - the user might just not have the necessary permissions.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### Make an authenticated curl request
|
|
29
|
+
```bash
|
|
30
|
+
latchkey curl [curl arguments]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Creating a Slack channel
|
|
34
|
+
```bash
|
|
35
|
+
latchkey curl -X POST 'https://slack.com/api/conversations.create' \
|
|
36
|
+
-H 'Content-Type: application/json' \
|
|
37
|
+
-d '{"name":"my-channel"}'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
(Notice that `-H 'Authorization: Bearer` is not present in the invocation.)
|
|
41
|
+
|
|
42
|
+
### Getting Discord user info
|
|
43
|
+
```bash
|
|
44
|
+
latchkey curl 'https://discord.com/api/v10/users/@me'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Clear expired credentials and force a new login to Discord
|
|
48
|
+
```bash
|
|
49
|
+
latchkey status discord # Returns "invalid"
|
|
50
|
+
latchkey clear discord
|
|
51
|
+
latchkey curl 'https://discord.com/api/v10/users/@me'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Only do this when you notice that your previous call ended up not being authenticated (HTTP 401 or 403). The next `latchkey curl` call will trigger a new login flow.
|
|
55
|
+
|
|
56
|
+
### List supported services
|
|
57
|
+
```bash
|
|
58
|
+
latchkey services
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Get service-specific info
|
|
62
|
+
```bash
|
|
63
|
+
latchkey info slack
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Returns developer notes about the service, including API documentation links and any special requirements.
|
|
67
|
+
|
|
68
|
+
## Notes
|
|
69
|
+
|
|
70
|
+
- All curl arguments are passed through unchanged
|
|
71
|
+
- Return codes, stdin, and stdout are passed back from curl
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "latchkey",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "A CLI tool that injects API credentials into curl requests for known third-party services",
|
|
5
|
+
"author": "Imbue <hynek@imbue.com>",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/imbue-ai/latchkey.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/imbue-ai/latchkey#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/imbue-ai/latchkey/issues"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "dist/src/index.js",
|
|
16
|
+
"types": "dist/src/index.d.ts",
|
|
17
|
+
"bin": {
|
|
18
|
+
"latchkey": "./dist/src/cli.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
27
|
+
"build": "tsc && node -e \"require('fs').cpSync('integrations', 'dist/integrations', {recursive:true})\" ",
|
|
28
|
+
"dev": "tsc --watch",
|
|
29
|
+
"lint": "eslint src tests scripts",
|
|
30
|
+
"lint:fix": "eslint src tests scripts --fix",
|
|
31
|
+
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\"",
|
|
32
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\"",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:watch": "vitest",
|
|
36
|
+
"start": "node dist/cli.js",
|
|
37
|
+
"bun-compile": "bun build ./src/cli.ts --compile --external chromium-bidi --external electron --outfile latchkey"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"cli",
|
|
41
|
+
"curl",
|
|
42
|
+
"api",
|
|
43
|
+
"credentials",
|
|
44
|
+
"authentication",
|
|
45
|
+
"agents",
|
|
46
|
+
"imbue"
|
|
47
|
+
],
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=20"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@napi-rs/keyring": "^1.2.0",
|
|
54
|
+
"commander": "^12.0.0",
|
|
55
|
+
"playwright": "^1.49.1",
|
|
56
|
+
"zod": "^3.22.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@eslint/js": "^9.39.2",
|
|
60
|
+
"@types/node": "^20.0.0",
|
|
61
|
+
"eslint": "^9.39.2",
|
|
62
|
+
"prettier": "^3.8.1",
|
|
63
|
+
"typescript": "^5.3.0",
|
|
64
|
+
"typescript-eslint": "^8.53.1",
|
|
65
|
+
"vitest": "^2.0.0"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* CLI tool for encrypting and decrypting latchkey files.
|
|
4
|
+
*
|
|
5
|
+
* This is a developer utility for inspecting and modifying encrypted
|
|
6
|
+
* credential and browser state files.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx tsx scripts/encryptFile.ts decrypt <file> # Decrypt file to stdout
|
|
10
|
+
* npx tsx scripts/encryptFile.ts encrypt <file> # Encrypt file in place
|
|
11
|
+
*
|
|
12
|
+
* The encryption key is sourced from:
|
|
13
|
+
* 1. LATCHKEY_ENCRYPTION_KEY environment variable
|
|
14
|
+
* 2. System keychain
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* npx tsx scripts/encryptFile.ts decrypt ~/.latchkey/credentials.json
|
|
18
|
+
* npx tsx scripts/encryptFile.ts encrypt ~/.latchkey/credentials.json
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=encryptFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryptFile.d.ts","sourceRoot":"","sources":["../../scripts/encryptFile.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* CLI tool for encrypting and decrypting latchkey files.
|
|
4
|
+
*
|
|
5
|
+
* This is a developer utility for inspecting and modifying encrypted
|
|
6
|
+
* credential and browser state files.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx tsx scripts/encryptFile.ts decrypt <file> # Decrypt file to stdout
|
|
10
|
+
* npx tsx scripts/encryptFile.ts encrypt <file> # Encrypt file in place
|
|
11
|
+
*
|
|
12
|
+
* The encryption key is sourced from:
|
|
13
|
+
* 1. LATCHKEY_ENCRYPTION_KEY environment variable
|
|
14
|
+
* 2. System keychain
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* npx tsx scripts/encryptFile.ts decrypt ~/.latchkey/credentials.json
|
|
18
|
+
* npx tsx scripts/encryptFile.ts encrypt ~/.latchkey/credentials.json
|
|
19
|
+
*/
|
|
20
|
+
import { program } from 'commander';
|
|
21
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import { CONFIG } from '../src/config.js';
|
|
23
|
+
import { EncryptedStorage } from '../src/encryptedStorage.js';
|
|
24
|
+
import { encrypt, generateKey } from '../src/encryption.js';
|
|
25
|
+
import { isKeychainAvailable, retrieveFromKeychain } from '../src/keychain.js';
|
|
26
|
+
const ENCRYPTED_FILE_PREFIX = 'LATCHKEY_ENCRYPTED:';
|
|
27
|
+
function getEncryptionKey() {
|
|
28
|
+
// 1. Check environment variable via Config
|
|
29
|
+
if (CONFIG.encryptionKeyOverride) {
|
|
30
|
+
return CONFIG.encryptionKeyOverride;
|
|
31
|
+
}
|
|
32
|
+
// 2. Check keychain
|
|
33
|
+
if (isKeychainAvailable(CONFIG.serviceName, CONFIG.accountName)) {
|
|
34
|
+
const keychainKey = retrieveFromKeychain(CONFIG.serviceName, CONFIG.accountName);
|
|
35
|
+
if (keychainKey) {
|
|
36
|
+
return keychainKey;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
console.error(`\
|
|
40
|
+
Error: No encryption key available.
|
|
41
|
+
Set LATCHKEY_ENCRYPTION_KEY or ensure the system keychain has a stored key.
|
|
42
|
+
|
|
43
|
+
To generate a new key:
|
|
44
|
+
export LATCHKEY_ENCRYPTION_KEY="${generateKey()}"`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
function decryptCommand(filePath) {
|
|
48
|
+
if (!existsSync(filePath)) {
|
|
49
|
+
console.error(`Error: File not found: ${filePath}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const storage = new EncryptedStorage({
|
|
53
|
+
serviceName: CONFIG.serviceName,
|
|
54
|
+
accountName: CONFIG.accountName,
|
|
55
|
+
});
|
|
56
|
+
const content = storage.readFile(filePath);
|
|
57
|
+
if (content === null) {
|
|
58
|
+
console.error(`Error: Could not read file: ${filePath}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
// Output to stdout
|
|
62
|
+
process.stdout.write(content);
|
|
63
|
+
}
|
|
64
|
+
function encryptCommand(filePath) {
|
|
65
|
+
if (!existsSync(filePath)) {
|
|
66
|
+
console.error(`Error: File not found: ${filePath}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
70
|
+
if (content.startsWith(ENCRYPTED_FILE_PREFIX)) {
|
|
71
|
+
console.error(`Error: File is already encrypted: ${filePath}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const key = getEncryptionKey();
|
|
75
|
+
const encryptedData = encrypt(content, key);
|
|
76
|
+
const dataToWrite = ENCRYPTED_FILE_PREFIX + encryptedData;
|
|
77
|
+
writeFileSync(filePath, dataToWrite, { encoding: 'utf-8', mode: 0o600 });
|
|
78
|
+
console.error(`Encrypted: ${filePath}`);
|
|
79
|
+
}
|
|
80
|
+
program.name('encryptFile').description(`\
|
|
81
|
+
CLI tool for encrypting and decrypting latchkey files.
|
|
82
|
+
|
|
83
|
+
The encryption key is sourced from:
|
|
84
|
+
1. LATCHKEY_ENCRYPTION_KEY environment variable
|
|
85
|
+
2. System keychain`);
|
|
86
|
+
program
|
|
87
|
+
.command('decrypt')
|
|
88
|
+
.description('Decrypt file and print to stdout')
|
|
89
|
+
.argument('<file>', 'Path to the encrypted file')
|
|
90
|
+
.action((filePath) => {
|
|
91
|
+
decryptCommand(filePath);
|
|
92
|
+
});
|
|
93
|
+
program
|
|
94
|
+
.command('encrypt')
|
|
95
|
+
.description('Encrypt an unencrypted file in place')
|
|
96
|
+
.argument('<file>', 'Path to the file to encrypt')
|
|
97
|
+
.action((filePath) => {
|
|
98
|
+
encryptCommand(filePath);
|
|
99
|
+
});
|
|
100
|
+
program.parse();
|
|
101
|
+
//# sourceMappingURL=encryptFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryptFile.js","sourceRoot":"","sources":["../../scripts/encryptFile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* API credentials types and utilities
|
|
2
|
+
* Serialized API credentials types and utilities.
|
|
3
|
+
*
|
|
3
4
|
*/
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
export declare enum ApiCredentialStatus {
|
|
@@ -14,6 +15,11 @@ export declare enum ApiCredentialStatus {
|
|
|
14
15
|
export interface ApiCredentials {
|
|
15
16
|
readonly objectType: string;
|
|
16
17
|
asCurlArguments(): readonly string[];
|
|
18
|
+
/**
|
|
19
|
+
* Check if the credentials are expired.
|
|
20
|
+
* Returns true if expired, false if valid, or undefined if expiration is unknown.
|
|
21
|
+
*/
|
|
22
|
+
isExpired(): boolean | undefined;
|
|
17
23
|
}
|
|
18
24
|
/**
|
|
19
25
|
* Bearer token authentication (Authorization: Bearer <token>).
|
|
@@ -34,6 +40,7 @@ export declare class AuthorizationBearer implements ApiCredentials {
|
|
|
34
40
|
readonly token: string;
|
|
35
41
|
constructor(token: string);
|
|
36
42
|
asCurlArguments(): readonly string[];
|
|
43
|
+
isExpired(): boolean | undefined;
|
|
37
44
|
toJSON(): AuthorizationBearerData;
|
|
38
45
|
static fromJSON(data: AuthorizationBearerData): AuthorizationBearer;
|
|
39
46
|
}
|
|
@@ -56,6 +63,7 @@ export declare class AuthorizationBare implements ApiCredentials {
|
|
|
56
63
|
readonly token: string;
|
|
57
64
|
constructor(token: string);
|
|
58
65
|
asCurlArguments(): readonly string[];
|
|
66
|
+
isExpired(): boolean | undefined;
|
|
59
67
|
toJSON(): AuthorizationBareData;
|
|
60
68
|
static fromJSON(data: AuthorizationBareData): AuthorizationBare;
|
|
61
69
|
}
|
|
@@ -82,9 +90,59 @@ export declare class SlackApiCredentials implements ApiCredentials {
|
|
|
82
90
|
readonly dCookie: string;
|
|
83
91
|
constructor(token: string, dCookie: string);
|
|
84
92
|
asCurlArguments(): readonly string[];
|
|
93
|
+
isExpired(): boolean | undefined;
|
|
85
94
|
toJSON(): SlackApiCredentialsData;
|
|
86
95
|
static fromJSON(data: SlackApiCredentialsData): SlackApiCredentials;
|
|
87
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* OAuth 2.0 credentials (access token, refresh token, client ID, and client secret).
|
|
99
|
+
* Used by services that implement OAuth 2.0 authorization flows.
|
|
100
|
+
* Token attributes are optional - when only clientId and clientSecret are present,
|
|
101
|
+
* this represents credentials from the prepare() step before obtaining user tokens.
|
|
102
|
+
*/
|
|
103
|
+
export declare const OAuthCredentialsSchema: z.ZodObject<{
|
|
104
|
+
objectType: z.ZodLiteral<"oauth">;
|
|
105
|
+
accessToken: z.ZodOptional<z.ZodString>;
|
|
106
|
+
refreshToken: z.ZodOptional<z.ZodString>;
|
|
107
|
+
clientId: z.ZodString;
|
|
108
|
+
clientSecret: z.ZodString;
|
|
109
|
+
accessTokenExpiresAt: z.ZodOptional<z.ZodString>;
|
|
110
|
+
refreshTokenExpiresAt: z.ZodOptional<z.ZodString>;
|
|
111
|
+
}, "strip", z.ZodTypeAny, {
|
|
112
|
+
objectType: "oauth";
|
|
113
|
+
clientId: string;
|
|
114
|
+
clientSecret: string;
|
|
115
|
+
accessToken?: string | undefined;
|
|
116
|
+
refreshToken?: string | undefined;
|
|
117
|
+
accessTokenExpiresAt?: string | undefined;
|
|
118
|
+
refreshTokenExpiresAt?: string | undefined;
|
|
119
|
+
}, {
|
|
120
|
+
objectType: "oauth";
|
|
121
|
+
clientId: string;
|
|
122
|
+
clientSecret: string;
|
|
123
|
+
accessToken?: string | undefined;
|
|
124
|
+
refreshToken?: string | undefined;
|
|
125
|
+
accessTokenExpiresAt?: string | undefined;
|
|
126
|
+
refreshTokenExpiresAt?: string | undefined;
|
|
127
|
+
}>;
|
|
128
|
+
export type OAuthCredentialsData = z.infer<typeof OAuthCredentialsSchema>;
|
|
129
|
+
export declare class OAuthCredentials implements ApiCredentials {
|
|
130
|
+
readonly objectType: "oauth";
|
|
131
|
+
readonly accessToken?: string;
|
|
132
|
+
readonly refreshToken?: string;
|
|
133
|
+
readonly clientId: string;
|
|
134
|
+
readonly clientSecret: string;
|
|
135
|
+
readonly accessTokenExpiresAt?: string;
|
|
136
|
+
readonly refreshTokenExpiresAt?: string;
|
|
137
|
+
constructor(clientId: string, clientSecret: string, accessToken?: string, refreshToken?: string, accessTokenExpiresAt?: string, refreshTokenExpiresAt?: string);
|
|
138
|
+
asCurlArguments(): readonly string[];
|
|
139
|
+
isExpired(): boolean | undefined;
|
|
140
|
+
toJSON(): OAuthCredentialsData;
|
|
141
|
+
static fromJSON(data: OAuthCredentialsData): OAuthCredentials;
|
|
142
|
+
}
|
|
143
|
+
export declare class ApiCredentialsUsageError extends Error {
|
|
144
|
+
constructor(message: string);
|
|
145
|
+
}
|
|
88
146
|
/**
|
|
89
147
|
* Union schema for all credential types.
|
|
90
148
|
*/
|
|
@@ -118,6 +176,30 @@ export declare const ApiCredentialsSchema: z.ZodDiscriminatedUnion<"objectType",
|
|
|
118
176
|
objectType: "slack";
|
|
119
177
|
token: string;
|
|
120
178
|
dCookie: string;
|
|
179
|
+
}>, z.ZodObject<{
|
|
180
|
+
objectType: z.ZodLiteral<"oauth">;
|
|
181
|
+
accessToken: z.ZodOptional<z.ZodString>;
|
|
182
|
+
refreshToken: z.ZodOptional<z.ZodString>;
|
|
183
|
+
clientId: z.ZodString;
|
|
184
|
+
clientSecret: z.ZodString;
|
|
185
|
+
accessTokenExpiresAt: z.ZodOptional<z.ZodString>;
|
|
186
|
+
refreshTokenExpiresAt: z.ZodOptional<z.ZodString>;
|
|
187
|
+
}, "strip", z.ZodTypeAny, {
|
|
188
|
+
objectType: "oauth";
|
|
189
|
+
clientId: string;
|
|
190
|
+
clientSecret: string;
|
|
191
|
+
accessToken?: string | undefined;
|
|
192
|
+
refreshToken?: string | undefined;
|
|
193
|
+
accessTokenExpiresAt?: string | undefined;
|
|
194
|
+
refreshTokenExpiresAt?: string | undefined;
|
|
195
|
+
}, {
|
|
196
|
+
objectType: "oauth";
|
|
197
|
+
clientId: string;
|
|
198
|
+
clientSecret: string;
|
|
199
|
+
accessToken?: string | undefined;
|
|
200
|
+
refreshToken?: string | undefined;
|
|
201
|
+
accessTokenExpiresAt?: string | undefined;
|
|
202
|
+
refreshTokenExpiresAt?: string | undefined;
|
|
121
203
|
}>]>;
|
|
122
204
|
export type ApiCredentialsData = z.infer<typeof ApiCredentialsSchema>;
|
|
123
205
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiCredentials.d.ts","sourceRoot":"","sources":["../../src/apiCredentials.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"apiCredentials.d.ts","sourceRoot":"","sources":["../../src/apiCredentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* API credentials types and utilities
|
|
2
|
+
* Serialized API credentials types and utilities.
|
|
3
|
+
*
|
|
3
4
|
*/
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
export var ApiCredentialStatus;
|
|
@@ -24,6 +25,9 @@ export class AuthorizationBearer {
|
|
|
24
25
|
asCurlArguments() {
|
|
25
26
|
return ['-H', `Authorization: Bearer ${this.token}`];
|
|
26
27
|
}
|
|
28
|
+
isExpired() {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
27
31
|
toJSON() {
|
|
28
32
|
return {
|
|
29
33
|
objectType: this.objectType,
|
|
@@ -50,6 +54,9 @@ export class AuthorizationBare {
|
|
|
50
54
|
asCurlArguments() {
|
|
51
55
|
return ['-H', `Authorization: ${this.token}`];
|
|
52
56
|
}
|
|
57
|
+
isExpired() {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
53
60
|
toJSON() {
|
|
54
61
|
return {
|
|
55
62
|
objectType: this.objectType,
|
|
@@ -79,6 +86,9 @@ export class SlackApiCredentials {
|
|
|
79
86
|
asCurlArguments() {
|
|
80
87
|
return ['-H', `Authorization: Bearer ${this.token}`, '-H', `Cookie: d=${this.dCookie}`];
|
|
81
88
|
}
|
|
89
|
+
isExpired() {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
82
92
|
toJSON() {
|
|
83
93
|
return {
|
|
84
94
|
objectType: this.objectType,
|
|
@@ -90,6 +100,72 @@ export class SlackApiCredentials {
|
|
|
90
100
|
return new SlackApiCredentials(data.token, data.dCookie);
|
|
91
101
|
}
|
|
92
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* OAuth 2.0 credentials (access token, refresh token, client ID, and client secret).
|
|
105
|
+
* Used by services that implement OAuth 2.0 authorization flows.
|
|
106
|
+
* Token attributes are optional - when only clientId and clientSecret are present,
|
|
107
|
+
* this represents credentials from the prepare() step before obtaining user tokens.
|
|
108
|
+
*/
|
|
109
|
+
export const OAuthCredentialsSchema = z.object({
|
|
110
|
+
objectType: z.literal('oauth'),
|
|
111
|
+
accessToken: z.string().optional(),
|
|
112
|
+
refreshToken: z.string().optional(),
|
|
113
|
+
clientId: z.string(),
|
|
114
|
+
clientSecret: z.string(),
|
|
115
|
+
accessTokenExpiresAt: z.string().optional(),
|
|
116
|
+
refreshTokenExpiresAt: z.string().optional(),
|
|
117
|
+
});
|
|
118
|
+
export class OAuthCredentials {
|
|
119
|
+
objectType = 'oauth';
|
|
120
|
+
accessToken;
|
|
121
|
+
refreshToken;
|
|
122
|
+
clientId;
|
|
123
|
+
clientSecret;
|
|
124
|
+
accessTokenExpiresAt;
|
|
125
|
+
refreshTokenExpiresAt;
|
|
126
|
+
constructor(clientId, clientSecret, accessToken, refreshToken, accessTokenExpiresAt, refreshTokenExpiresAt) {
|
|
127
|
+
this.clientId = clientId;
|
|
128
|
+
this.clientSecret = clientSecret;
|
|
129
|
+
this.accessToken = accessToken;
|
|
130
|
+
this.refreshToken = refreshToken;
|
|
131
|
+
this.accessTokenExpiresAt = accessTokenExpiresAt;
|
|
132
|
+
this.refreshTokenExpiresAt = refreshTokenExpiresAt;
|
|
133
|
+
}
|
|
134
|
+
asCurlArguments() {
|
|
135
|
+
if (this.accessToken === undefined) {
|
|
136
|
+
throw new ApiCredentialsUsageError('OAuth credentials missing access token. Run login to obtain access tokens.');
|
|
137
|
+
}
|
|
138
|
+
return ['-H', `Authorization: Bearer ${this.accessToken}`];
|
|
139
|
+
}
|
|
140
|
+
isExpired() {
|
|
141
|
+
if (this.accessTokenExpiresAt === undefined) {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
const expirationDate = new Date(this.accessTokenExpiresAt);
|
|
145
|
+
return Date.now() >= expirationDate.getTime();
|
|
146
|
+
}
|
|
147
|
+
toJSON() {
|
|
148
|
+
const result = {
|
|
149
|
+
objectType: this.objectType,
|
|
150
|
+
clientId: this.clientId,
|
|
151
|
+
clientSecret: this.clientSecret,
|
|
152
|
+
accessToken: this.accessToken,
|
|
153
|
+
refreshToken: this.refreshToken,
|
|
154
|
+
accessTokenExpiresAt: this.accessTokenExpiresAt,
|
|
155
|
+
refreshTokenExpiresAt: this.refreshTokenExpiresAt,
|
|
156
|
+
};
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
static fromJSON(data) {
|
|
160
|
+
return new OAuthCredentials(data.clientId, data.clientSecret, data.accessToken, data.refreshToken, data.accessTokenExpiresAt, data.refreshTokenExpiresAt);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
export class ApiCredentialsUsageError extends Error {
|
|
164
|
+
constructor(message) {
|
|
165
|
+
super(message);
|
|
166
|
+
this.name = 'ApiCredentialsUsageError';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
93
169
|
/**
|
|
94
170
|
* Union schema for all credential types.
|
|
95
171
|
*/
|
|
@@ -97,6 +173,7 @@ export const ApiCredentialsSchema = z.discriminatedUnion('objectType', [
|
|
|
97
173
|
AuthorizationBearerSchema,
|
|
98
174
|
AuthorizationBareSchema,
|
|
99
175
|
SlackApiCredentialsSchema,
|
|
176
|
+
OAuthCredentialsSchema,
|
|
100
177
|
]);
|
|
101
178
|
/**
|
|
102
179
|
* Deserialize credentials from JSON data.
|
|
@@ -109,6 +186,8 @@ export function deserializeCredentials(data) {
|
|
|
109
186
|
return AuthorizationBare.fromJSON(data);
|
|
110
187
|
case 'slack':
|
|
111
188
|
return SlackApiCredentials.fromJSON(data);
|
|
189
|
+
case 'oauth':
|
|
190
|
+
return OAuthCredentials.fromJSON(data);
|
|
112
191
|
default: {
|
|
113
192
|
const exhaustiveCheck = data;
|
|
114
193
|
throw new ApiCredentialsSerializationError(`Unknown credential type: ${exhaustiveCheck.objectType}`);
|
|
@@ -128,6 +207,9 @@ export function serializeCredentials(credentials) {
|
|
|
128
207
|
if (credentials instanceof SlackApiCredentials) {
|
|
129
208
|
return credentials.toJSON();
|
|
130
209
|
}
|
|
210
|
+
if (credentials instanceof OAuthCredentials) {
|
|
211
|
+
return credentials.toJSON();
|
|
212
|
+
}
|
|
131
213
|
throw new ApiCredentialsSerializationError(`Unknown credential type: ${credentials.objectType}`);
|
|
132
214
|
}
|
|
133
215
|
export class ApiCredentialsSerializationError extends Error {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiCredentials.js","sourceRoot":"","sources":["../../src/apiCredentials.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"apiCredentials.js","sourceRoot":"","sources":["../../src/apiCredentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserState.d.ts","sourceRoot":"","sources":["../../src/browserState.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAUnD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser state management utilities.
|
|
3
|
+
*/
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
const LATCHKEY_BROWSER_STATE_ENV_VAR = 'LATCHKEY_BROWSER_STATE';
|
|
7
|
+
/**
|
|
8
|
+
* Get the browser state path from the LATCHKEY_BROWSER_STATE environment variable.
|
|
9
|
+
*/
|
|
10
|
+
export function getBrowserStatePath() {
|
|
11
|
+
const envValue = process.env[LATCHKEY_BROWSER_STATE_ENV_VAR];
|
|
12
|
+
if (envValue) {
|
|
13
|
+
// Expand ~ to home directory
|
|
14
|
+
if (envValue.startsWith('~')) {
|
|
15
|
+
return resolve(homedir(), envValue.slice(2));
|
|
16
|
+
}
|
|
17
|
+
return resolve(envValue);
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=browserState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserState.js","sourceRoot":"","sources":["../../src/browserState.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,8BAA8B,GAAG,wBAAwB,CAAC;AAEhE;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC7D,IAAI,QAAQ,EAAE,CAAC;QACb,6BAA6B;QAC7B,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/src/cli.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { program } from 'commander';
|
|
6
6
|
import { registerCommands, createDefaultDependencies } from './cliCommands.js';
|
|
7
7
|
import { InsecureFilePermissionsError } from './config.js';
|
|
8
|
+
import packageJson from '../package.json' with { type: 'json' };
|
|
8
9
|
const deps = createDefaultDependencies();
|
|
9
10
|
try {
|
|
10
11
|
deps.config.checkSensitiveFilePermissions();
|
|
@@ -19,7 +20,7 @@ catch (error) {
|
|
|
19
20
|
program
|
|
20
21
|
.name('latchkey')
|
|
21
22
|
.description('A command-line tool that injects API credentials to curl requests to known public APIs.')
|
|
22
|
-
.version(
|
|
23
|
+
.version(packageJson.version);
|
|
23
24
|
registerCommands(program, deps);
|
|
24
25
|
program.parse();
|
|
25
26
|
//# sourceMappingURL=cli.js.map
|