oauth.do 0.1.0 → 0.1.2
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/README.md +17 -19
- package/dist/cli.js +11 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +24 -31
- package/dist/index.js +47 -104
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,34 +51,32 @@ const url = buildAuthUrl({
|
|
|
51
51
|
})
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
###
|
|
54
|
+
### CLI Login Helper
|
|
55
|
+
|
|
56
|
+
For building CLIs that need authentication:
|
|
55
57
|
|
|
56
58
|
```typescript
|
|
57
|
-
import {
|
|
59
|
+
import { ensureLoggedIn } from 'oauth.do'
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
console.log('Code:', auth.user_code)
|
|
61
|
+
// Get token (prompts login if needed, auto-opens browser)
|
|
62
|
+
const { token, isNewLogin } = await ensureLoggedIn()
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
// Use token for API calls
|
|
65
|
+
const response = await fetch('https://api.example.com', {
|
|
66
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
67
|
+
})
|
|
64
68
|
```
|
|
65
69
|
|
|
66
|
-
|
|
70
|
+
### Device Authorization Flow
|
|
67
71
|
|
|
68
72
|
```typescript
|
|
69
|
-
import {
|
|
70
|
-
|
|
71
|
-
// Create
|
|
72
|
-
const key = await createApiKey({ name: 'my-key', expiresIn: '30d' })
|
|
73
|
-
|
|
74
|
-
// List
|
|
75
|
-
const keys = await listApiKeys()
|
|
73
|
+
import { authorizeDevice, pollForTokens } from 'oauth.do'
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
const auth = await authorizeDevice()
|
|
76
|
+
console.log('Visit:', auth.verification_uri)
|
|
77
|
+
console.log('Code:', auth.user_code)
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
await deleteApiKey(key.id)
|
|
79
|
+
const tokens = await pollForTokens(auth.device_code, auth.interval, auth.expires_in)
|
|
82
80
|
```
|
|
83
81
|
|
|
84
82
|
## Token Storage
|
|
@@ -118,7 +116,7 @@ configure({
|
|
|
118
116
|
|
|
119
117
|
- `DO_TOKEN` - Authentication token
|
|
120
118
|
- `OAUTH_API_URL` - API base URL (default: `https://apis.do`)
|
|
121
|
-
- `OAUTH_CLIENT_ID` - OAuth client ID
|
|
119
|
+
- `OAUTH_CLIENT_ID` - OAuth client ID
|
|
122
120
|
- `OAUTH_AUTHKIT_DOMAIN` - AuthKit domain (default: `login.oauth.do`)
|
|
123
121
|
|
|
124
122
|
## License
|
package/dist/cli.js
CHANGED
|
@@ -283,7 +283,7 @@ var require_package = __commonJS({
|
|
|
283
283
|
"package.json"(exports$1, module) {
|
|
284
284
|
module.exports = {
|
|
285
285
|
name: "oauth.do",
|
|
286
|
-
version: "0.1.
|
|
286
|
+
version: "0.1.2",
|
|
287
287
|
description: "OAuth authentication SDK and CLI for .do Platform",
|
|
288
288
|
type: "module",
|
|
289
289
|
main: "./dist/index.js",
|
|
@@ -360,7 +360,7 @@ function getEnv(key) {
|
|
|
360
360
|
}
|
|
361
361
|
var globalConfig = {
|
|
362
362
|
apiUrl: getEnv("OAUTH_API_URL") || getEnv("API_URL") || "https://apis.do",
|
|
363
|
-
clientId: getEnv("OAUTH_CLIENT_ID") || "
|
|
363
|
+
clientId: getEnv("OAUTH_CLIENT_ID") || "client_01JQYTRXK9ZPD8JPJTKDCRB656",
|
|
364
364
|
authKitDomain: getEnv("OAUTH_AUTHKIT_DOMAIN") || "login.oauth.do",
|
|
365
365
|
fetch: globalThis.fetch
|
|
366
366
|
};
|
|
@@ -381,17 +381,18 @@ async function authorizeDevice() {
|
|
|
381
381
|
throw new Error('Client ID is required for device authorization. Set OAUTH_CLIENT_ID or configure({ clientId: "..." })');
|
|
382
382
|
}
|
|
383
383
|
try {
|
|
384
|
-
const
|
|
384
|
+
const url = "https://auth.apis.do/user_management/authorize/device";
|
|
385
|
+
const body = new URLSearchParams({ client_id: config.clientId });
|
|
386
|
+
const response = await config.fetch(url, {
|
|
385
387
|
method: "POST",
|
|
386
388
|
headers: {
|
|
387
389
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
388
390
|
},
|
|
389
|
-
body
|
|
390
|
-
client_id: config.clientId
|
|
391
|
-
})
|
|
391
|
+
body
|
|
392
392
|
});
|
|
393
393
|
if (!response.ok) {
|
|
394
|
-
|
|
394
|
+
const errorText = await response.text();
|
|
395
|
+
throw new Error(`Device authorization failed: ${response.statusText} - ${errorText}`);
|
|
395
396
|
}
|
|
396
397
|
const data = await response.json();
|
|
397
398
|
return data;
|
|
@@ -414,7 +415,7 @@ async function pollForTokens(deviceCode, interval = 5, expiresIn = 600) {
|
|
|
414
415
|
}
|
|
415
416
|
await new Promise((resolve) => setTimeout(resolve, currentInterval));
|
|
416
417
|
try {
|
|
417
|
-
const response = await config.fetch(
|
|
418
|
+
const response = await config.fetch("https://auth.apis.do/user_management/authenticate", {
|
|
418
419
|
method: "POST",
|
|
419
420
|
headers: {
|
|
420
421
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
@@ -525,7 +526,7 @@ var storage = createSecureStorage();
|
|
|
525
526
|
function configureFromEnv() {
|
|
526
527
|
configure({
|
|
527
528
|
apiUrl: process.env.OAUTH_API_URL || process.env.API_URL || "https://apis.do",
|
|
528
|
-
clientId: process.env.OAUTH_CLIENT_ID || "
|
|
529
|
+
clientId: process.env.OAUTH_CLIENT_ID || "client_01JQYTRXK9ZPD8JPJTKDCRB656",
|
|
529
530
|
authKitDomain: process.env.OAUTH_AUTHKIT_DOMAIN || "login.oauth.do"
|
|
530
531
|
});
|
|
531
532
|
}
|
|
@@ -579,7 +580,7 @@ ${colors.cyan}Examples:${colors.reset}
|
|
|
579
580
|
oauth.do logout
|
|
580
581
|
|
|
581
582
|
${colors.cyan}Environment Variables:${colors.reset}
|
|
582
|
-
OAUTH_CLIENT_ID Client ID for OAuth
|
|
583
|
+
OAUTH_CLIENT_ID Client ID for OAuth
|
|
583
584
|
OAUTH_AUTHKIT_DOMAIN AuthKit domain (default: login.oauth.do)
|
|
584
585
|
OAUTH_API_URL API base URL (default: https://apis.do)
|
|
585
586
|
DEBUG Enable debug output
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/storage.ts","../package.json","../src/config.ts","../src/device.ts","../src/auth.ts","../src/cli.ts"],"names":["getEnv","storage","exports"],"mappings":"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","file":"cli.js","sourcesContent":["import type { TokenStorage } from './types.js'\n\n// Keychain service and account identifiers\nconst KEYCHAIN_SERVICE = 'oauth.do'\nconst KEYCHAIN_ACCOUNT = 'access_token'\n\n/**\n * Check if we're running in a Node.js environment\n */\nfunction isNode(): boolean {\n\treturn typeof process !== 'undefined' &&\n\t\tprocess.versions != null &&\n\t\tprocess.versions.node != null\n}\n\n/**\n * Safe environment variable access\n */\nfunction getEnv(key: string): string | undefined {\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Keychain-based token storage using OS credential manager\n * - macOS: Keychain\n * - Windows: Credential Manager\n * - Linux: Secret Service (libsecret)\n *\n * This is the most secure option for CLI token storage.\n */\nexport class KeychainTokenStorage implements TokenStorage {\n\tprivate keytar: typeof import('keytar') | null = null\n\tprivate initialized = false\n\n\t/**\n\t * Lazily load keytar module\n\t * Returns null if keytar is not available (e.g., missing native dependencies)\n\t */\n\tprivate async getKeytar(): Promise<typeof import('keytar') | null> {\n\t\tif (this.initialized) {\n\t\t\treturn this.keytar\n\t\t}\n\n\t\tthis.initialized = true\n\n\t\ttry {\n\t\t\t// Dynamic import to handle cases where keytar native module isn't available\n\t\t\tthis.keytar = await import('keytar')\n\t\t\treturn this.keytar\n\t\t} catch (error) {\n\t\t\t// keytar requires native dependencies that may not be available\n\t\t\t// Fall back gracefully\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain storage not available:', error)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn null\n\t\t}\n\n\t\ttry {\n\t\t\tconst token = await keytar.getPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)\n\t\t\treturn token\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Failed to get token from keychain:', error)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\tthrow new Error('Keychain storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to save token to keychain: ${error}`)\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn\n\t\t}\n\n\t\ttry {\n\t\t\tawait keytar.deletePassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)\n\t\t} catch {\n\t\t\t// Ignore errors if credential doesn't exist\n\t\t}\n\t}\n\n\t/**\n\t * Check if keychain storage is available on this system\n\t */\n\tasync isAvailable(): Promise<boolean> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn false\n\t\t}\n\n\t\ttry {\n\t\t\t// Try a read operation to verify keychain access\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n}\n\n/**\n * Secure file-based token storage for CLI\n * Stores token in ~/.oauth.do/token with restricted permissions (0600)\n *\n * This is used as a fallback when keychain storage is not available.\n * Only works in Node.js environment.\n */\nexport class SecureFileTokenStorage implements TokenStorage {\n\tprivate tokenPath: string | null = null\n\tprivate configDir: string | null = null\n\tprivate initialized = false\n\n\tprivate async init(): Promise<boolean> {\n\t\tif (this.initialized) return this.tokenPath !== null\n\t\tthis.initialized = true\n\n\t\tif (!isNode()) return false\n\n\t\ttry {\n\t\t\tconst os = await import('os')\n\t\t\tconst path = await import('path')\n\t\t\tthis.configDir = path.join(os.homedir(), '.oauth.do')\n\t\t\tthis.tokenPath = path.join(this.configDir, 'token')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (!(await this.init()) || !this.tokenPath) return null\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\t// Verify file permissions before reading\n\t\t\tconst stats = await fs.stat(this.tokenPath)\n\t\t\tconst mode = stats.mode & 0o777\n\n\t\t\t// Warn if file has insecure permissions\n\t\t\tif (mode !== 0o600 && getEnv('DEBUG')) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Warning: Token file has insecure permissions (${mode.toString(8)}). ` +\n\t\t\t\t\t\t`Expected 600. Run: chmod 600 ${this.tokenPath}`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst token = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\treturn token.trim()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath || !this.configDir) {\n\t\t\tthrow new Error('File storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\t// Create config directory with restricted permissions\n\t\t\tawait fs.mkdir(this.configDir, { recursive: true, mode: 0o700 })\n\n\t\t\t// Write token file\n\t\t\tawait fs.writeFile(this.tokenPath, token, { encoding: 'utf-8', mode: 0o600 })\n\n\t\t\t// Ensure permissions are correct (writeFile mode may be affected by umask)\n\t\t\tawait fs.chmod(this.tokenPath, 0o600)\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token:', error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath) return\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.unlink(this.tokenPath)\n\t\t} catch {\n\t\t\t// Ignore errors if file doesn't exist\n\t\t}\n\t}\n}\n\n/**\n * File-based token storage for CLI (legacy, less secure)\n * Stores token in ~/.oauth.do/token\n * Only works in Node.js environment.\n *\n * @deprecated Use SecureFileTokenStorage or KeychainTokenStorage instead\n */\nexport class FileTokenStorage implements TokenStorage {\n\tprivate tokenPath: string | null = null\n\tprivate configDir: string | null = null\n\tprivate initialized = false\n\n\tprivate async init(): Promise<boolean> {\n\t\tif (this.initialized) return this.tokenPath !== null\n\t\tthis.initialized = true\n\n\t\tif (!isNode()) return false\n\n\t\ttry {\n\t\t\tconst os = await import('os')\n\t\t\tconst path = await import('path')\n\t\t\tthis.configDir = path.join(os.homedir(), '.oauth.do')\n\t\t\tthis.tokenPath = path.join(this.configDir, 'token')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (!(await this.init()) || !this.tokenPath) return null\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tconst token = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\treturn token.trim()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath || !this.configDir) {\n\t\t\tthrow new Error('File storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.mkdir(this.configDir, { recursive: true })\n\t\t\tawait fs.writeFile(this.tokenPath, token, 'utf-8')\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token:', error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath) return\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.unlink(this.tokenPath)\n\t\t} catch {\n\t\t\t// Ignore errors if file doesn't exist\n\t\t}\n\t}\n}\n\n/**\n * In-memory token storage (for browser or testing)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n\tprivate token: string | null = null\n\n\tasync getToken(): Promise<string | null> {\n\t\treturn this.token\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tthis.token = token\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tthis.token = null\n\t}\n}\n\n/**\n * LocalStorage-based token storage (for browser)\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n\tprivate key = 'oauth.do:token'\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\treturn null\n\t\t}\n\t\treturn localStorage.getItem(this.key)\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\tthrow new Error('localStorage is not available')\n\t\t}\n\t\tlocalStorage.setItem(this.key, token)\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\treturn\n\t\t}\n\t\tlocalStorage.removeItem(this.key)\n\t}\n}\n\n/**\n * Composite token storage that tries multiple storage backends\n * Attempts keychain first, then falls back to secure file storage\n */\nexport class CompositeTokenStorage implements TokenStorage {\n\tprivate keychainStorage: KeychainTokenStorage\n\tprivate fileStorage: SecureFileTokenStorage\n\tprivate preferredStorage: TokenStorage | null = null\n\n\tconstructor() {\n\t\tthis.keychainStorage = new KeychainTokenStorage()\n\t\tthis.fileStorage = new SecureFileTokenStorage()\n\t}\n\n\t/**\n\t * Determine the best available storage backend\n\t */\n\tprivate async getPreferredStorage(): Promise<TokenStorage> {\n\t\tif (this.preferredStorage) {\n\t\t\treturn this.preferredStorage\n\t\t}\n\n\t\t// Try keychain first\n\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\tthis.preferredStorage = this.keychainStorage\n\t\t\treturn this.preferredStorage\n\t\t}\n\n\t\t// Fall back to secure file storage\n\t\tthis.preferredStorage = this.fileStorage\n\t\treturn this.preferredStorage\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\t// First, check keychain\n\t\tconst keychainToken = await this.keychainStorage.getToken()\n\t\tif (keychainToken) {\n\t\t\treturn keychainToken\n\t\t}\n\n\t\t// Fall back to file storage (for migration from old installations)\n\t\tconst fileToken = await this.fileStorage.getToken()\n\t\tif (fileToken) {\n\t\t\t// Migrate token to keychain if available\n\t\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.keychainStorage.setToken(fileToken)\n\t\t\t\t\tawait this.fileStorage.removeToken()\n\t\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\t\tconsole.log('Migrated token from file to keychain')\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Continue with file token if migration fails\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fileToken\n\t\t}\n\n\t\treturn null\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tconst storage = await this.getPreferredStorage()\n\t\tawait storage.setToken(token)\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\t// Remove from both storages to ensure complete logout\n\t\tawait Promise.all([this.keychainStorage.removeToken(), this.fileStorage.removeToken()])\n\t}\n\n\t/**\n\t * Get information about the current storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'keychain' | 'file'; secure: boolean }> {\n\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\treturn { type: 'keychain', secure: true }\n\t\t}\n\t\treturn { type: 'file', secure: true }\n\t}\n}\n\n/**\n * Create the default token storage\n * - Node.js: Uses OS keychain when available, falls back to secure file storage\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use keychain/file storage\n\tif (isNode()) {\n\t\treturn new CompositeTokenStorage()\n\t}\n\n\t// Browser - use localStorage\n\tif (typeof localStorage !== 'undefined') {\n\t\treturn new LocalStorageTokenStorage()\n\t}\n\n\t// Workers/other - use memory storage\n\treturn new MemoryTokenStorage()\n}\n","{\n\t\"name\": \"oauth.do\",\n\t\"version\": \"0.1.0\",\n\t\"description\": \"OAuth authentication SDK and CLI for .do Platform\",\n\t\"type\": \"module\",\n\t\"main\": \"./dist/index.js\",\n\t\"types\": \"./dist/index.d.ts\",\n\t\"bin\": {\n\t\t\"oauth.do\": \"./dist/cli.js\"\n\t},\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./dist/index.d.ts\",\n\t\t\t\"import\": \"./dist/index.js\"\n\t\t},\n\t\t\"./mdx/*\": \"./src/mdx/*\"\n\t},\n\t\"files\": [\n\t\t\"dist\",\n\t\t\"src/mdx\",\n\t\t\"README.md\",\n\t\t\"LICENSE\"\n\t],\n\t\"scripts\": {\n\t\t\"build\": \"tsup\",\n\t\t\"dev\": \"tsup --watch\",\n\t\t\"test\": \"vitest run\",\n\t\t\"test:watch\": \"vitest\",\n\t\t\"prepublishOnly\": \"pnpm build && pnpm test\"\n\t},\n\t\"keywords\": [\n\t\t\"oauth\",\n\t\t\"authentication\",\n\t\t\"auth\",\n\t\t\"login\",\n\t\t\"api-key\",\n\t\t\"cli\",\n\t\t\"sdk\",\n\t\t\"platform\",\n\t\t\"workos\"\n\t],\n\t\"author\": {\n\t\t\"name\": \"Platform.do\",\n\t\t\"email\": \"npm@platform.do\",\n\t\t\"url\": \"https://platform.do\"\n\t},\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/dot-do/oauth.do.git\"\n\t},\n\t\"bugs\": {\n\t\t\"url\": \"https://github.com/dot-do/oauth.do/issues\"\n\t},\n\t\"homepage\": \"https://oauth.do\",\n\t\"engines\": {\n\t\t\"node\": \">=18.0.0\"\n\t},\n\t\"dependencies\": {\n\t\t\"keytar\": \"^7.9.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/node\": \"^24.10.1\",\n\t\t\"tsup\": \"^8.0.0\",\n\t\t\"typescript\": \"^5.5.2\",\n\t\t\"vitest\": \"^2.1.8\"\n\t}\n}\n","import type { OAuthConfig } from './types.js'\n\n/**\n * Safe environment variable access (works in Node, browser, and Workers)\n */\nfunction getEnv(key: string): string | undefined {\n\t// Check globalThis first (Workers)\n\tif ((globalThis as any)[key]) return (globalThis as any)[key]\n\t// Check process.env (Node.js)\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Global OAuth configuration\n */\nlet globalConfig: Required<OAuthConfig> = {\n\tapiUrl: getEnv('OAUTH_API_URL') || getEnv('API_URL') || 'https://apis.do',\n\tclientId: getEnv('OAUTH_CLIENT_ID') || 'oauth.do',\n\tauthKitDomain: getEnv('OAUTH_AUTHKIT_DOMAIN') || 'login.oauth.do',\n\tfetch: globalThis.fetch,\n}\n\n/**\n * Configure OAuth settings\n */\nexport function configure(config: OAuthConfig): void {\n\tglobalConfig = {\n\t\t...globalConfig,\n\t\t...config,\n\t}\n}\n\n/**\n * Get current configuration\n */\nexport function getConfig(): Required<OAuthConfig> {\n\treturn globalConfig\n}\n","import { getConfig } from './config.js'\nimport type { DeviceAuthorizationResponse, TokenResponse, TokenError } from './types.js'\n\n/**\n * Initiate device authorization flow\n * Following OAuth 2.0 Device Authorization Grant (RFC 8628)\n *\n * @returns Device authorization response with codes and URIs\n */\nexport async function authorizeDevice(): Promise<DeviceAuthorizationResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for device authorization. Set OAUTH_CLIENT_ID or configure({ clientId: \"...\" })')\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`https://${config.authKitDomain}/device/authorize`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t},\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tclient_id: config.clientId,\n\t\t\t}),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Device authorization failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst data = (await response.json()) as DeviceAuthorizationResponse\n\t\treturn data\n\t} catch (error) {\n\t\tconsole.error('Device authorization error:', error)\n\t\tthrow error\n\t}\n}\n\n/**\n * Poll for tokens after device authorization\n *\n * @param deviceCode - Device code from authorization response\n * @param interval - Polling interval in seconds (default: 5)\n * @param expiresIn - Expiration time in seconds (default: 600)\n * @returns Token response with access token and user info\n */\nexport async function pollForTokens(\n\tdeviceCode: string,\n\tinterval: number = 5,\n\texpiresIn: number = 600\n): Promise<TokenResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for token polling')\n\t}\n\n\tconst startTime = Date.now()\n\tconst timeout = expiresIn * 1000\n\tlet currentInterval = interval * 1000\n\n\twhile (true) {\n\t\t// Check if expired\n\t\tif (Date.now() - startTime > timeout) {\n\t\t\tthrow new Error('Device authorization expired. Please try again.')\n\t\t}\n\n\t\t// Wait for interval\n\t\tawait new Promise((resolve) => setTimeout(resolve, currentInterval))\n\n\t\ttry {\n\t\t\tconst response = await config.fetch(`https://${config.authKitDomain}/device/token`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t\t},\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tgrant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n\t\t\t\t\tdevice_code: deviceCode,\n\t\t\t\t\tclient_id: config.clientId,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst data = (await response.json()) as TokenResponse\n\t\t\t\treturn data\n\t\t\t}\n\n\t\t\t// Handle error responses\n\t\t\tconst errorData = (await response.json().catch(() => ({ error: 'unknown' }))) as { error?: string }\n\t\t\tconst error = (errorData.error || 'unknown') as TokenError\n\n\t\t\tswitch (error) {\n\t\t\t\tcase 'authorization_pending':\n\t\t\t\t\t// Continue polling\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase 'slow_down':\n\t\t\t\t\t// Increase interval by 5 seconds\n\t\t\t\t\tcurrentInterval += 5000\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase 'access_denied':\n\t\t\t\t\tthrow new Error('Access denied by user')\n\n\t\t\t\tcase 'expired_token':\n\t\t\t\t\tthrow new Error('Device code expired')\n\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Token polling failed: ${error}`)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// If it's our thrown error, re-throw it\n\t\t\tif (error instanceof Error) {\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\t// Otherwise continue polling\n\t\t\tcontinue\n\t\t}\n\t}\n}\n","import { getConfig } from './config.js'\nimport type { User, AuthResult } from './types.js'\n\n/**\n * Safe environment variable access (works in Node, browser, and Workers)\n */\nfunction getEnv(key: string): string | undefined {\n\t// Check globalThis first (Workers)\n\tif ((globalThis as any)[key]) return (globalThis as any)[key]\n\t// Check process.env (Node.js)\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Get current authenticated user\n * Calls GET /me endpoint\n *\n * @param token - Optional authentication token (will use DO_TOKEN env var if not provided)\n * @returns Authentication result with user info or null if not authenticated\n */\nexport async function auth(token?: string): Promise<AuthResult> {\n\tconst config = getConfig()\n\tconst authToken = token || getEnv('DO_TOKEN') || ''\n\n\tif (!authToken) {\n\t\treturn { user: null }\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/me`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\t'Authorization': `Bearer ${authToken}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 401) {\n\t\t\t\treturn { user: null }\n\t\t\t}\n\t\t\tthrow new Error(`Authentication failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst user = (await response.json()) as User\n\t\treturn { user, token: authToken }\n\t} catch (error) {\n\t\tconsole.error('Auth error:', error)\n\t\treturn { user: null }\n\t}\n}\n\n/**\n * Initiate login flow\n * Calls POST /login endpoint\n *\n * @param credentials - Login credentials (email, password, etc.)\n * @returns Authentication result with user info and token\n */\nexport async function login(credentials: {\n\temail?: string\n\tpassword?: string\n\t[key: string]: any\n}): Promise<AuthResult> {\n\tconst config = getConfig()\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/login`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t\tbody: JSON.stringify(credentials),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Login failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst data = (await response.json()) as { user: User; token: string }\n\t\treturn { user: data.user, token: data.token }\n\t} catch (error) {\n\t\tconsole.error('Login error:', error)\n\t\tthrow error\n\t}\n}\n\n/**\n * Logout current user\n * Calls POST /logout endpoint\n *\n * @param token - Optional authentication token (will use DO_TOKEN env var if not provided)\n */\nexport async function logout(token?: string): Promise<void> {\n\tconst config = getConfig()\n\tconst authToken = token || getEnv('DO_TOKEN') || ''\n\n\tif (!authToken) {\n\t\treturn\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/logout`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Authorization': `Bearer ${authToken}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconsole.warn(`Logout warning: ${response.statusText}`)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('Logout error:', error)\n\t}\n}\n\n/**\n * Get token from environment or stored credentials\n *\n * Checks in order:\n * 1. process.env.DO_ADMIN_TOKEN\n * 2. process.env.DO_TOKEN\n * 3. Stored token (keychain/secure file)\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers, process.env for Node)\n\tconst adminToken = getEnv('DO_ADMIN_TOKEN')\n\tif (adminToken) return adminToken\n\tconst doToken = getEnv('DO_TOKEN')\n\tif (doToken) return doToken\n\n\t// Try stored token (Node.js only - uses keychain/file storage)\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\treturn await storage.getToken()\n\t} catch {\n\t\t// Storage not available (browser/worker) - return null\n\t\treturn null\n\t}\n}\n\n/**\n * Check if user is authenticated (has valid token)\n */\nexport async function isAuthenticated(token?: string): Promise<boolean> {\n\tconst result = await auth(token)\n\treturn result.user !== null\n}\n\n/**\n * Build OAuth authorization URL\n *\n * @example\n * const url = buildAuthUrl({\n * redirectUri: 'https://myapp.com/callback',\n * scope: 'openid profile email',\n * })\n */\nexport function buildAuthUrl(options: {\n\tredirectUri: string\n\tscope?: string\n\tstate?: string\n\tresponseType?: string\n\tclientId?: string\n\tauthDomain?: string\n}): string {\n\tconst config = getConfig()\n\tconst clientId = options.clientId || config.clientId\n\tconst authDomain = options.authDomain || config.authKitDomain\n\n\tconst params = new URLSearchParams({\n\t\tclient_id: clientId,\n\t\tredirect_uri: options.redirectUri,\n\t\tresponse_type: options.responseType || 'code',\n\t\tscope: options.scope || 'openid profile email',\n\t})\n\n\tif (options.state) {\n\t\tparams.set('state', options.state)\n\t}\n\n\treturn `https://${authDomain}/authorize?${params.toString()}`\n}\n","#!/usr/bin/env node\n/**\n * OAuth.do CLI\n * Authenticate with .do Platform using OAuth device flow\n *\n * Usage:\n * oauth.do login - Login using device authorization flow\n * oauth.do logout - Logout and remove stored credentials\n * oauth.do whoami - Show current authenticated user\n * oauth.do token - Display current authentication token\n */\n\nimport { authorizeDevice, pollForTokens } from './device.js'\nimport { auth, logout as logoutFn } from './auth.js'\nimport { createSecureStorage, CompositeTokenStorage } from './storage.js'\nimport { configure } from './config.js'\n\n// Color codes for terminal output\nconst colors = {\n\treset: '\\x1b[0m',\n\tbright: '\\x1b[1m',\n\tdim: '\\x1b[2m',\n\tgreen: '\\x1b[32m',\n\tyellow: '\\x1b[33m',\n\tred: '\\x1b[31m',\n\tcyan: '\\x1b[36m',\n\tgray: '\\x1b[90m',\n\tblue: '\\x1b[34m',\n}\n\n// Token storage - uses OS keychain when available, falls back to secure file storage\nconst storage = createSecureStorage()\n\n/**\n * Configure OAuth from environment variables\n */\nfunction configureFromEnv() {\n\tconfigure({\n\t\tapiUrl: process.env.OAUTH_API_URL || process.env.API_URL || 'https://apis.do',\n\t\tclientId: process.env.OAUTH_CLIENT_ID || 'oauth.do',\n\t\tauthKitDomain: process.env.OAUTH_AUTHKIT_DOMAIN || 'login.oauth.do',\n\t})\n}\n\n/**\n * Print error message\n */\nfunction printError(message: string, error?: Error) {\n\tconsole.error(`${colors.red}Error:${colors.reset} ${message}`)\n\tif (error && error.message) {\n\t\tconsole.error(error.message)\n\t}\n\tif (error && error.stack && process.env.DEBUG) {\n\t\tconsole.error(`\\n${colors.dim}Stack trace:${colors.reset}`)\n\t\tconsole.error(`${colors.dim}${error.stack}${colors.reset}`)\n\t}\n}\n\n/**\n * Print success message\n */\nfunction printSuccess(message: string) {\n\tconsole.log(`${colors.green}✓${colors.reset} ${message}`)\n}\n\n/**\n * Print info message\n */\nfunction printInfo(message: string) {\n\tconsole.log(`${colors.cyan}ℹ${colors.reset} ${message}`)\n}\n\n/**\n * Print help message\n */\nfunction printHelp() {\n\tconsole.log(`\n${colors.bright}OAuth.do CLI${colors.reset}\n\n${colors.cyan}Usage:${colors.reset}\n oauth.do <command> [options]\n\n${colors.cyan}Commands:${colors.reset}\n login Login using device authorization flow\n logout Logout and remove stored credentials\n whoami Show current authenticated user\n token Display current authentication token\n status Show authentication and storage status\n\n${colors.cyan}Options:${colors.reset}\n --help, -h Show this help message\n --version, -v Show version\n --debug Show debug information\n\n${colors.cyan}Examples:${colors.reset}\n ${colors.gray}# Login to your account${colors.reset}\n oauth.do login\n\n ${colors.gray}# Check who is logged in${colors.reset}\n oauth.do whoami\n\n ${colors.gray}# Get your authentication token${colors.reset}\n oauth.do token\n\n ${colors.gray}# Logout${colors.reset}\n oauth.do logout\n\n${colors.cyan}Environment Variables:${colors.reset}\n OAUTH_CLIENT_ID Client ID for OAuth (default: oauth.do)\n OAUTH_AUTHKIT_DOMAIN AuthKit domain (default: login.oauth.do)\n OAUTH_API_URL API base URL (default: https://apis.do)\n DEBUG Enable debug output\n`)\n}\n\n/**\n * Print version\n */\nfunction printVersion() {\n\ttry {\n\t\t// Dynamic import of package.json\n\t\timport('../package.json', { assert: { type: 'json' } }).then((pkg) => {\n\t\t\tconsole.log(`oauth.do v${pkg.default.version}`)\n\t\t})\n\t} catch {\n\t\tconsole.log('oauth.do')\n\t}\n}\n\n/**\n * Login command - device authorization flow\n */\nasync function loginCommand() {\n\ttry {\n\t\tconsole.log(`${colors.bright}Starting OAuth login...${colors.reset}\\n`)\n\n\t\t// Step 1: Authorize device\n\t\tprintInfo('Requesting device authorization...')\n\t\tconst authResponse = await authorizeDevice()\n\n\t\t// Step 2: Display instructions to user\n\t\tconsole.log(`\\n${colors.bright}To complete login:${colors.reset}`)\n\t\tconsole.log(`\\n 1. Visit: ${colors.cyan}${authResponse.verification_uri}${colors.reset}`)\n\t\tconsole.log(` 2. Enter code: ${colors.bright}${colors.yellow}${authResponse.user_code}${colors.reset}`)\n\t\tconsole.log(`\\n ${colors.dim}Or open this URL directly:${colors.reset}`)\n\t\tconsole.log(` ${colors.blue}${authResponse.verification_uri_complete}${colors.reset}\\n`)\n\n\t\t// Try to open browser automatically\n\t\tconst open = await import('open').catch(() => null)\n\t\tif (open) {\n\t\t\ttry {\n\t\t\t\tawait open.default(authResponse.verification_uri_complete)\n\t\t\t\tprintInfo('Opened browser for authentication')\n\t\t\t} catch {\n\t\t\t\t// Silently fail if can't open browser\n\t\t\t}\n\t\t}\n\n\t\t// Step 3: Poll for tokens\n\t\tconsole.log(`${colors.dim}Waiting for authorization...${colors.reset}\\n`)\n\t\tconst tokenResponse = await pollForTokens(\n\t\t\tauthResponse.device_code,\n\t\t\tauthResponse.interval,\n\t\t\tauthResponse.expires_in\n\t\t)\n\n\t\t// Step 4: Save token\n\t\tawait storage.setToken(tokenResponse.access_token)\n\n\t\t// Step 5: Get user info\n\t\tconst authResult = await auth(tokenResponse.access_token)\n\n\t\tprintSuccess('Login successful!')\n\t\tif (authResult.user) {\n\t\t\tconsole.log(`\\n${colors.dim}Logged in as:${colors.reset}`)\n\t\t\tif (authResult.user.name) {\n\t\t\t\tconsole.log(` ${colors.bright}${authResult.user.name}${colors.reset}`)\n\t\t\t}\n\t\t\tif (authResult.user.email) {\n\t\t\t\tconsole.log(` ${colors.gray}${authResult.user.email}${colors.reset}`)\n\t\t\t}\n\t\t}\n\n\t\t// Show storage info\n\t\tconst compositeStorage = storage as CompositeTokenStorage\n\t\tif (typeof compositeStorage.getStorageInfo === 'function') {\n\t\t\tconst storageInfo = await compositeStorage.getStorageInfo()\n\t\t\tconst storageLabel =\n\t\t\t\tstorageInfo.type === 'keychain' ? `${colors.green}OS Keychain${colors.reset}` : `${colors.yellow}Secure File${colors.reset}`\n\t\t\tconsole.log(`\\n${colors.dim}Token stored in: ${storageLabel}${colors.reset}`)\n\t\t}\n\t} catch (error) {\n\t\tprintError('Login failed', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Logout command\n */\nasync function logoutCommand() {\n\ttry {\n\t\t// Get current token\n\t\tconst token = await storage.getToken()\n\n\t\tif (!token) {\n\t\t\tprintInfo('Not logged in')\n\t\t\treturn\n\t\t}\n\n\t\t// Call logout endpoint\n\t\tawait logoutFn(token)\n\n\t\t// Remove stored token\n\t\tawait storage.removeToken()\n\n\t\tprintSuccess('Logged out successfully')\n\t} catch (error) {\n\t\tprintError('Logout failed', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Whoami command - show current user\n */\nasync function whoamiCommand() {\n\ttry {\n\t\tconst token = await storage.getToken()\n\n\t\tif (!token) {\n\t\t\tconsole.log(`${colors.dim}Not logged in${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to authenticate`)\n\t\t\treturn\n\t\t}\n\n\t\tconst authResult = await auth(token)\n\n\t\tif (!authResult.user) {\n\t\t\tconsole.log(`${colors.dim}Not authenticated${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to authenticate`)\n\t\t\treturn\n\t\t}\n\n\t\tconsole.log(`${colors.bright}Authenticated as:${colors.reset}`)\n\t\tif (authResult.user.name) {\n\t\t\tconsole.log(` ${colors.green}Name:${colors.reset} ${authResult.user.name}`)\n\t\t}\n\t\tif (authResult.user.email) {\n\t\t\tconsole.log(` ${colors.green}Email:${colors.reset} ${authResult.user.email}`)\n\t\t}\n\t\tif (authResult.user.id) {\n\t\t\tconsole.log(` ${colors.green}ID:${colors.reset} ${authResult.user.id}`)\n\t\t}\n\t} catch (error) {\n\t\tprintError('Failed to get user info', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Token command - display current token\n */\nasync function tokenCommand() {\n\ttry {\n\t\tconst token = await storage.getToken()\n\n\t\tif (!token) {\n\t\t\tconsole.log(`${colors.dim}No token found${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to authenticate`)\n\t\t\treturn\n\t\t}\n\n\t\tconsole.log(token)\n\t} catch (error) {\n\t\tprintError('Failed to get token', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Status command - show authentication and storage status\n */\nasync function statusCommand() {\n\ttry {\n\t\tconsole.log(`${colors.bright}OAuth.do Status${colors.reset}\\n`)\n\n\t\t// Get storage info\n\t\tconst compositeStorage = storage as CompositeTokenStorage\n\t\tif (typeof compositeStorage.getStorageInfo === 'function') {\n\t\t\tconst storageInfo = await compositeStorage.getStorageInfo()\n\t\t\tconst storageLabel =\n\t\t\t\tstorageInfo.type === 'keychain' ? `${colors.green}OS Keychain${colors.reset}` : `${colors.yellow}Secure File${colors.reset}`\n\n\t\t\tconsole.log(`${colors.cyan}Storage:${colors.reset} ${storageLabel}`)\n\n\t\t\tif (storageInfo.type === 'keychain') {\n\t\t\t\tconsole.log(` ${colors.dim}Using system credential manager (most secure)${colors.reset}`)\n\t\t\t} else {\n\t\t\t\tconsole.log(` ${colors.dim}Using ~/.oauth.do/token with 0600 permissions${colors.reset}`)\n\t\t\t}\n\t\t}\n\n\t\t// Get auth status\n\t\tconst token = await storage.getToken()\n\t\tif (!token) {\n\t\t\tconsole.log(`\\n${colors.cyan}Auth:${colors.reset} ${colors.dim}Not authenticated${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to authenticate`)\n\t\t\treturn\n\t\t}\n\n\t\tconst authResult = await auth(token)\n\t\tif (authResult.user) {\n\t\t\tconsole.log(`\\n${colors.cyan}Auth:${colors.reset} ${colors.green}Authenticated${colors.reset}`)\n\t\t\tif (authResult.user.email) {\n\t\t\t\tconsole.log(` ${colors.dim}${authResult.user.email}${colors.reset}`)\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(`\\n${colors.cyan}Auth:${colors.reset} ${colors.yellow}Token expired or invalid${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to re-authenticate`)\n\t\t}\n\t} catch (error) {\n\t\tprintError('Failed to get status', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Main CLI function\n */\nasync function main() {\n\tconfigureFromEnv()\n\n\tconst args = process.argv.slice(2)\n\n\t// Handle flags\n\tif (args.includes('--help') || args.includes('-h')) {\n\t\tprintHelp()\n\t\tprocess.exit(0)\n\t}\n\n\tif (args.includes('--version') || args.includes('-v')) {\n\t\tprintVersion()\n\t\tprocess.exit(0)\n\t}\n\n\tif (args.includes('--debug')) {\n\t\tprocess.env.DEBUG = 'true'\n\t}\n\n\t// Get command\n\tconst command = args.find((arg) => !arg.startsWith('--'))\n\n\tswitch (command) {\n\t\tcase 'login':\n\t\tcase undefined: // Default to login when no command specified\n\t\t\tawait loginCommand()\n\t\t\tbreak\n\n\t\tcase 'logout':\n\t\t\tawait logoutCommand()\n\t\t\tbreak\n\n\t\tcase 'whoami':\n\t\t\tawait whoamiCommand()\n\t\t\tbreak\n\n\t\tcase 'token':\n\t\t\tawait tokenCommand()\n\t\t\tbreak\n\n\t\tcase 'status':\n\t\t\tawait statusCommand()\n\t\t\tbreak\n\n\t\tdefault:\n\t\t\tprintError(`Unknown command: ${command}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do --help${colors.reset} for usage information`)\n\t\t\tprocess.exit(1)\n\t}\n}\n\n// Run CLI\nmain().catch((error) => {\n\tprintError('Unexpected error', error)\n\tprocess.exit(1)\n})\n\nexport { main }\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/storage.ts","../package.json","../src/config.ts","../src/device.ts","../src/auth.ts","../src/cli.ts"],"names":["getEnv","storage","exports"],"mappings":"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","file":"cli.js","sourcesContent":["import type { TokenStorage } from './types.js'\n\n// Keychain service and account identifiers\nconst KEYCHAIN_SERVICE = 'oauth.do'\nconst KEYCHAIN_ACCOUNT = 'access_token'\n\n/**\n * Check if we're running in a Node.js environment\n */\nfunction isNode(): boolean {\n\treturn typeof process !== 'undefined' &&\n\t\tprocess.versions != null &&\n\t\tprocess.versions.node != null\n}\n\n/**\n * Safe environment variable access\n */\nfunction getEnv(key: string): string | undefined {\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Keychain-based token storage using OS credential manager\n * - macOS: Keychain\n * - Windows: Credential Manager\n * - Linux: Secret Service (libsecret)\n *\n * This is the most secure option for CLI token storage.\n */\nexport class KeychainTokenStorage implements TokenStorage {\n\tprivate keytar: typeof import('keytar') | null = null\n\tprivate initialized = false\n\n\t/**\n\t * Lazily load keytar module\n\t * Returns null if keytar is not available (e.g., missing native dependencies)\n\t */\n\tprivate async getKeytar(): Promise<typeof import('keytar') | null> {\n\t\tif (this.initialized) {\n\t\t\treturn this.keytar\n\t\t}\n\n\t\tthis.initialized = true\n\n\t\ttry {\n\t\t\t// Dynamic import to handle cases where keytar native module isn't available\n\t\t\tthis.keytar = await import('keytar')\n\t\t\treturn this.keytar\n\t\t} catch (error) {\n\t\t\t// keytar requires native dependencies that may not be available\n\t\t\t// Fall back gracefully\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain storage not available:', error)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn null\n\t\t}\n\n\t\ttry {\n\t\t\tconst token = await keytar.getPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)\n\t\t\treturn token\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Failed to get token from keychain:', error)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\tthrow new Error('Keychain storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to save token to keychain: ${error}`)\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn\n\t\t}\n\n\t\ttry {\n\t\t\tawait keytar.deletePassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)\n\t\t} catch {\n\t\t\t// Ignore errors if credential doesn't exist\n\t\t}\n\t}\n\n\t/**\n\t * Check if keychain storage is available on this system\n\t */\n\tasync isAvailable(): Promise<boolean> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn false\n\t\t}\n\n\t\ttry {\n\t\t\t// Try a read operation to verify keychain access\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n}\n\n/**\n * Secure file-based token storage for CLI\n * Stores token in ~/.oauth.do/token with restricted permissions (0600)\n *\n * This is used as a fallback when keychain storage is not available.\n * Only works in Node.js environment.\n */\nexport class SecureFileTokenStorage implements TokenStorage {\n\tprivate tokenPath: string | null = null\n\tprivate configDir: string | null = null\n\tprivate initialized = false\n\n\tprivate async init(): Promise<boolean> {\n\t\tif (this.initialized) return this.tokenPath !== null\n\t\tthis.initialized = true\n\n\t\tif (!isNode()) return false\n\n\t\ttry {\n\t\t\tconst os = await import('os')\n\t\t\tconst path = await import('path')\n\t\t\tthis.configDir = path.join(os.homedir(), '.oauth.do')\n\t\t\tthis.tokenPath = path.join(this.configDir, 'token')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (!(await this.init()) || !this.tokenPath) return null\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\t// Verify file permissions before reading\n\t\t\tconst stats = await fs.stat(this.tokenPath)\n\t\t\tconst mode = stats.mode & 0o777\n\n\t\t\t// Warn if file has insecure permissions\n\t\t\tif (mode !== 0o600 && getEnv('DEBUG')) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Warning: Token file has insecure permissions (${mode.toString(8)}). ` +\n\t\t\t\t\t\t`Expected 600. Run: chmod 600 ${this.tokenPath}`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst token = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\treturn token.trim()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath || !this.configDir) {\n\t\t\tthrow new Error('File storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\t// Create config directory with restricted permissions\n\t\t\tawait fs.mkdir(this.configDir, { recursive: true, mode: 0o700 })\n\n\t\t\t// Write token file\n\t\t\tawait fs.writeFile(this.tokenPath, token, { encoding: 'utf-8', mode: 0o600 })\n\n\t\t\t// Ensure permissions are correct (writeFile mode may be affected by umask)\n\t\t\tawait fs.chmod(this.tokenPath, 0o600)\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token:', error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath) return\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.unlink(this.tokenPath)\n\t\t} catch {\n\t\t\t// Ignore errors if file doesn't exist\n\t\t}\n\t}\n}\n\n/**\n * File-based token storage for CLI (legacy, less secure)\n * Stores token in ~/.oauth.do/token\n * Only works in Node.js environment.\n *\n * @deprecated Use SecureFileTokenStorage or KeychainTokenStorage instead\n */\nexport class FileTokenStorage implements TokenStorage {\n\tprivate tokenPath: string | null = null\n\tprivate configDir: string | null = null\n\tprivate initialized = false\n\n\tprivate async init(): Promise<boolean> {\n\t\tif (this.initialized) return this.tokenPath !== null\n\t\tthis.initialized = true\n\n\t\tif (!isNode()) return false\n\n\t\ttry {\n\t\t\tconst os = await import('os')\n\t\t\tconst path = await import('path')\n\t\t\tthis.configDir = path.join(os.homedir(), '.oauth.do')\n\t\t\tthis.tokenPath = path.join(this.configDir, 'token')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (!(await this.init()) || !this.tokenPath) return null\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tconst token = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\treturn token.trim()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath || !this.configDir) {\n\t\t\tthrow new Error('File storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.mkdir(this.configDir, { recursive: true })\n\t\t\tawait fs.writeFile(this.tokenPath, token, 'utf-8')\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token:', error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath) return\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.unlink(this.tokenPath)\n\t\t} catch {\n\t\t\t// Ignore errors if file doesn't exist\n\t\t}\n\t}\n}\n\n/**\n * In-memory token storage (for browser or testing)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n\tprivate token: string | null = null\n\n\tasync getToken(): Promise<string | null> {\n\t\treturn this.token\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tthis.token = token\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tthis.token = null\n\t}\n}\n\n/**\n * LocalStorage-based token storage (for browser)\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n\tprivate key = 'oauth.do:token'\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\treturn null\n\t\t}\n\t\treturn localStorage.getItem(this.key)\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\tthrow new Error('localStorage is not available')\n\t\t}\n\t\tlocalStorage.setItem(this.key, token)\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\treturn\n\t\t}\n\t\tlocalStorage.removeItem(this.key)\n\t}\n}\n\n/**\n * Composite token storage that tries multiple storage backends\n * Attempts keychain first, then falls back to secure file storage\n */\nexport class CompositeTokenStorage implements TokenStorage {\n\tprivate keychainStorage: KeychainTokenStorage\n\tprivate fileStorage: SecureFileTokenStorage\n\tprivate preferredStorage: TokenStorage | null = null\n\n\tconstructor() {\n\t\tthis.keychainStorage = new KeychainTokenStorage()\n\t\tthis.fileStorage = new SecureFileTokenStorage()\n\t}\n\n\t/**\n\t * Determine the best available storage backend\n\t */\n\tprivate async getPreferredStorage(): Promise<TokenStorage> {\n\t\tif (this.preferredStorage) {\n\t\t\treturn this.preferredStorage\n\t\t}\n\n\t\t// Try keychain first\n\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\tthis.preferredStorage = this.keychainStorage\n\t\t\treturn this.preferredStorage\n\t\t}\n\n\t\t// Fall back to secure file storage\n\t\tthis.preferredStorage = this.fileStorage\n\t\treturn this.preferredStorage\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\t// First, check keychain\n\t\tconst keychainToken = await this.keychainStorage.getToken()\n\t\tif (keychainToken) {\n\t\t\treturn keychainToken\n\t\t}\n\n\t\t// Fall back to file storage (for migration from old installations)\n\t\tconst fileToken = await this.fileStorage.getToken()\n\t\tif (fileToken) {\n\t\t\t// Migrate token to keychain if available\n\t\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.keychainStorage.setToken(fileToken)\n\t\t\t\t\tawait this.fileStorage.removeToken()\n\t\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\t\tconsole.log('Migrated token from file to keychain')\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Continue with file token if migration fails\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fileToken\n\t\t}\n\n\t\treturn null\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tconst storage = await this.getPreferredStorage()\n\t\tawait storage.setToken(token)\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\t// Remove from both storages to ensure complete logout\n\t\tawait Promise.all([this.keychainStorage.removeToken(), this.fileStorage.removeToken()])\n\t}\n\n\t/**\n\t * Get information about the current storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'keychain' | 'file'; secure: boolean }> {\n\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\treturn { type: 'keychain', secure: true }\n\t\t}\n\t\treturn { type: 'file', secure: true }\n\t}\n}\n\n/**\n * Create the default token storage\n * - Node.js: Uses OS keychain when available, falls back to secure file storage\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use keychain/file storage\n\tif (isNode()) {\n\t\treturn new CompositeTokenStorage()\n\t}\n\n\t// Browser - use localStorage\n\tif (typeof localStorage !== 'undefined') {\n\t\treturn new LocalStorageTokenStorage()\n\t}\n\n\t// Workers/other - use memory storage\n\treturn new MemoryTokenStorage()\n}\n","{\n\t\"name\": \"oauth.do\",\n\t\"version\": \"0.1.2\",\n\t\"description\": \"OAuth authentication SDK and CLI for .do Platform\",\n\t\"type\": \"module\",\n\t\"main\": \"./dist/index.js\",\n\t\"types\": \"./dist/index.d.ts\",\n\t\"bin\": {\n\t\t\"oauth.do\": \"./dist/cli.js\"\n\t},\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./dist/index.d.ts\",\n\t\t\t\"import\": \"./dist/index.js\"\n\t\t},\n\t\t\"./mdx/*\": \"./src/mdx/*\"\n\t},\n\t\"files\": [\n\t\t\"dist\",\n\t\t\"src/mdx\",\n\t\t\"README.md\",\n\t\t\"LICENSE\"\n\t],\n\t\"scripts\": {\n\t\t\"build\": \"tsup\",\n\t\t\"dev\": \"tsup --watch\",\n\t\t\"test\": \"vitest run\",\n\t\t\"test:watch\": \"vitest\",\n\t\t\"prepublishOnly\": \"pnpm build && pnpm test\"\n\t},\n\t\"keywords\": [\n\t\t\"oauth\",\n\t\t\"authentication\",\n\t\t\"auth\",\n\t\t\"login\",\n\t\t\"api-key\",\n\t\t\"cli\",\n\t\t\"sdk\",\n\t\t\"platform\",\n\t\t\"workos\"\n\t],\n\t\"author\": {\n\t\t\"name\": \"Platform.do\",\n\t\t\"email\": \"npm@platform.do\",\n\t\t\"url\": \"https://platform.do\"\n\t},\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/dot-do/oauth.do.git\"\n\t},\n\t\"bugs\": {\n\t\t\"url\": \"https://github.com/dot-do/oauth.do/issues\"\n\t},\n\t\"homepage\": \"https://oauth.do\",\n\t\"engines\": {\n\t\t\"node\": \">=18.0.0\"\n\t},\n\t\"dependencies\": {\n\t\t\"keytar\": \"^7.9.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/node\": \"^24.10.1\",\n\t\t\"tsup\": \"^8.0.0\",\n\t\t\"typescript\": \"^5.5.2\",\n\t\t\"vitest\": \"^2.1.8\"\n\t}\n}\n","import type { OAuthConfig } from './types.js'\n\n/**\n * Safe environment variable access (works in Node, browser, and Workers)\n */\nfunction getEnv(key: string): string | undefined {\n\t// Check globalThis first (Workers)\n\tif ((globalThis as any)[key]) return (globalThis as any)[key]\n\t// Check process.env (Node.js)\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Global OAuth configuration\n */\nlet globalConfig: Required<OAuthConfig> = {\n\tapiUrl: getEnv('OAUTH_API_URL') || getEnv('API_URL') || 'https://apis.do',\n\tclientId: getEnv('OAUTH_CLIENT_ID') || 'client_01JQYTRXK9ZPD8JPJTKDCRB656',\n\tauthKitDomain: getEnv('OAUTH_AUTHKIT_DOMAIN') || 'login.oauth.do',\n\tfetch: globalThis.fetch,\n}\n\n/**\n * Configure OAuth settings\n */\nexport function configure(config: OAuthConfig): void {\n\tglobalConfig = {\n\t\t...globalConfig,\n\t\t...config,\n\t}\n}\n\n/**\n * Get current configuration\n */\nexport function getConfig(): Required<OAuthConfig> {\n\treturn globalConfig\n}\n","import { getConfig } from './config.js'\nimport type { DeviceAuthorizationResponse, TokenResponse, TokenError } from './types.js'\n\n/**\n * Initiate device authorization flow\n * Following OAuth 2.0 Device Authorization Grant (RFC 8628)\n *\n * @returns Device authorization response with codes and URIs\n */\nexport async function authorizeDevice(): Promise<DeviceAuthorizationResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for device authorization. Set OAUTH_CLIENT_ID or configure({ clientId: \"...\" })')\n\t}\n\n\ttry {\n\t\tconst url = 'https://auth.apis.do/user_management/authorize/device'\n\t\tconst body = new URLSearchParams({ client_id: config.clientId })\n\n\t\tconst response = await config.fetch(url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t},\n\t\t\tbody,\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text()\n\t\t\tthrow new Error(`Device authorization failed: ${response.statusText} - ${errorText}`)\n\t\t}\n\n\t\tconst data = (await response.json()) as DeviceAuthorizationResponse\n\t\treturn data\n\t} catch (error) {\n\t\tconsole.error('Device authorization error:', error)\n\t\tthrow error\n\t}\n}\n\n/**\n * Poll for tokens after device authorization\n *\n * @param deviceCode - Device code from authorization response\n * @param interval - Polling interval in seconds (default: 5)\n * @param expiresIn - Expiration time in seconds (default: 600)\n * @returns Token response with access token and user info\n */\nexport async function pollForTokens(\n\tdeviceCode: string,\n\tinterval: number = 5,\n\texpiresIn: number = 600\n): Promise<TokenResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for token polling')\n\t}\n\n\tconst startTime = Date.now()\n\tconst timeout = expiresIn * 1000\n\tlet currentInterval = interval * 1000\n\n\twhile (true) {\n\t\t// Check if expired\n\t\tif (Date.now() - startTime > timeout) {\n\t\t\tthrow new Error('Device authorization expired. Please try again.')\n\t\t}\n\n\t\t// Wait for interval\n\t\tawait new Promise((resolve) => setTimeout(resolve, currentInterval))\n\n\t\ttry {\n\t\t\tconst response = await config.fetch('https://auth.apis.do/user_management/authenticate', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t\t},\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tgrant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n\t\t\t\t\tdevice_code: deviceCode,\n\t\t\t\t\tclient_id: config.clientId,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst data = (await response.json()) as TokenResponse\n\t\t\t\treturn data\n\t\t\t}\n\n\t\t\t// Handle error responses\n\t\t\tconst errorData = (await response.json().catch(() => ({ error: 'unknown' }))) as { error?: string }\n\t\t\tconst error = (errorData.error || 'unknown') as TokenError\n\n\t\t\tswitch (error) {\n\t\t\t\tcase 'authorization_pending':\n\t\t\t\t\t// Continue polling\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase 'slow_down':\n\t\t\t\t\t// Increase interval by 5 seconds\n\t\t\t\t\tcurrentInterval += 5000\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase 'access_denied':\n\t\t\t\t\tthrow new Error('Access denied by user')\n\n\t\t\t\tcase 'expired_token':\n\t\t\t\t\tthrow new Error('Device code expired')\n\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Token polling failed: ${error}`)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// If it's our thrown error, re-throw it\n\t\t\tif (error instanceof Error) {\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\t// Otherwise continue polling\n\t\t\tcontinue\n\t\t}\n\t}\n}\n","import { getConfig } from './config.js'\nimport type { User, AuthResult } from './types.js'\n\n/**\n * Safe environment variable access (works in Node, browser, and Workers)\n */\nfunction getEnv(key: string): string | undefined {\n\t// Check globalThis first (Workers)\n\tif ((globalThis as any)[key]) return (globalThis as any)[key]\n\t// Check process.env (Node.js)\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Get current authenticated user\n * Calls GET /me endpoint\n *\n * @param token - Optional authentication token (will use DO_TOKEN env var if not provided)\n * @returns Authentication result with user info or null if not authenticated\n */\nexport async function auth(token?: string): Promise<AuthResult> {\n\tconst config = getConfig()\n\tconst authToken = token || getEnv('DO_TOKEN') || ''\n\n\tif (!authToken) {\n\t\treturn { user: null }\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/me`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\t'Authorization': `Bearer ${authToken}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 401) {\n\t\t\t\treturn { user: null }\n\t\t\t}\n\t\t\tthrow new Error(`Authentication failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst user = (await response.json()) as User\n\t\treturn { user, token: authToken }\n\t} catch (error) {\n\t\tconsole.error('Auth error:', error)\n\t\treturn { user: null }\n\t}\n}\n\n/**\n * Initiate login flow\n * Calls POST /login endpoint\n *\n * @param credentials - Login credentials (email, password, etc.)\n * @returns Authentication result with user info and token\n */\nexport async function login(credentials: {\n\temail?: string\n\tpassword?: string\n\t[key: string]: any\n}): Promise<AuthResult> {\n\tconst config = getConfig()\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/login`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t\tbody: JSON.stringify(credentials),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Login failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst data = (await response.json()) as { user: User; token: string }\n\t\treturn { user: data.user, token: data.token }\n\t} catch (error) {\n\t\tconsole.error('Login error:', error)\n\t\tthrow error\n\t}\n}\n\n/**\n * Logout current user\n * Calls POST /logout endpoint\n *\n * @param token - Optional authentication token (will use DO_TOKEN env var if not provided)\n */\nexport async function logout(token?: string): Promise<void> {\n\tconst config = getConfig()\n\tconst authToken = token || getEnv('DO_TOKEN') || ''\n\n\tif (!authToken) {\n\t\treturn\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/logout`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Authorization': `Bearer ${authToken}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconsole.warn(`Logout warning: ${response.statusText}`)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('Logout error:', error)\n\t}\n}\n\n/**\n * Get token from environment or stored credentials\n *\n * Checks in order:\n * 1. process.env.DO_ADMIN_TOKEN\n * 2. process.env.DO_TOKEN\n * 3. Stored token (keychain/secure file)\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers, process.env for Node)\n\tconst adminToken = getEnv('DO_ADMIN_TOKEN')\n\tif (adminToken) return adminToken\n\tconst doToken = getEnv('DO_TOKEN')\n\tif (doToken) return doToken\n\n\t// Try stored token (Node.js only - uses keychain/file storage)\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\treturn await storage.getToken()\n\t} catch {\n\t\t// Storage not available (browser/worker) - return null\n\t\treturn null\n\t}\n}\n\n/**\n * Check if user is authenticated (has valid token)\n */\nexport async function isAuthenticated(token?: string): Promise<boolean> {\n\tconst result = await auth(token)\n\treturn result.user !== null\n}\n\n/**\n * Build OAuth authorization URL\n *\n * @example\n * const url = buildAuthUrl({\n * redirectUri: 'https://myapp.com/callback',\n * scope: 'openid profile email',\n * })\n */\nexport function buildAuthUrl(options: {\n\tredirectUri: string\n\tscope?: string\n\tstate?: string\n\tresponseType?: string\n\tclientId?: string\n\tauthDomain?: string\n}): string {\n\tconst config = getConfig()\n\tconst clientId = options.clientId || config.clientId\n\tconst authDomain = options.authDomain || config.authKitDomain\n\n\tconst params = new URLSearchParams({\n\t\tclient_id: clientId,\n\t\tredirect_uri: options.redirectUri,\n\t\tresponse_type: options.responseType || 'code',\n\t\tscope: options.scope || 'openid profile email',\n\t})\n\n\tif (options.state) {\n\t\tparams.set('state', options.state)\n\t}\n\n\treturn `https://${authDomain}/authorize?${params.toString()}`\n}\n","#!/usr/bin/env node\n/**\n * OAuth.do CLI\n * Authenticate with .do Platform using OAuth device flow\n *\n * Usage:\n * oauth.do login - Login using device authorization flow\n * oauth.do logout - Logout and remove stored credentials\n * oauth.do whoami - Show current authenticated user\n * oauth.do token - Display current authentication token\n */\n\nimport { authorizeDevice, pollForTokens } from './device.js'\nimport { auth, logout as logoutFn } from './auth.js'\nimport { createSecureStorage, CompositeTokenStorage } from './storage.js'\nimport { configure } from './config.js'\n\n// Color codes for terminal output\nconst colors = {\n\treset: '\\x1b[0m',\n\tbright: '\\x1b[1m',\n\tdim: '\\x1b[2m',\n\tgreen: '\\x1b[32m',\n\tyellow: '\\x1b[33m',\n\tred: '\\x1b[31m',\n\tcyan: '\\x1b[36m',\n\tgray: '\\x1b[90m',\n\tblue: '\\x1b[34m',\n}\n\n// Token storage - uses OS keychain when available, falls back to secure file storage\nconst storage = createSecureStorage()\n\n/**\n * Configure OAuth from environment variables\n */\nfunction configureFromEnv() {\n\tconfigure({\n\t\tapiUrl: process.env.OAUTH_API_URL || process.env.API_URL || 'https://apis.do',\n\t\tclientId: process.env.OAUTH_CLIENT_ID || 'client_01JQYTRXK9ZPD8JPJTKDCRB656',\n\t\tauthKitDomain: process.env.OAUTH_AUTHKIT_DOMAIN || 'login.oauth.do',\n\t})\n}\n\n/**\n * Print error message\n */\nfunction printError(message: string, error?: Error) {\n\tconsole.error(`${colors.red}Error:${colors.reset} ${message}`)\n\tif (error && error.message) {\n\t\tconsole.error(error.message)\n\t}\n\tif (error && error.stack && process.env.DEBUG) {\n\t\tconsole.error(`\\n${colors.dim}Stack trace:${colors.reset}`)\n\t\tconsole.error(`${colors.dim}${error.stack}${colors.reset}`)\n\t}\n}\n\n/**\n * Print success message\n */\nfunction printSuccess(message: string) {\n\tconsole.log(`${colors.green}✓${colors.reset} ${message}`)\n}\n\n/**\n * Print info message\n */\nfunction printInfo(message: string) {\n\tconsole.log(`${colors.cyan}ℹ${colors.reset} ${message}`)\n}\n\n/**\n * Print help message\n */\nfunction printHelp() {\n\tconsole.log(`\n${colors.bright}OAuth.do CLI${colors.reset}\n\n${colors.cyan}Usage:${colors.reset}\n oauth.do <command> [options]\n\n${colors.cyan}Commands:${colors.reset}\n login Login using device authorization flow\n logout Logout and remove stored credentials\n whoami Show current authenticated user\n token Display current authentication token\n status Show authentication and storage status\n\n${colors.cyan}Options:${colors.reset}\n --help, -h Show this help message\n --version, -v Show version\n --debug Show debug information\n\n${colors.cyan}Examples:${colors.reset}\n ${colors.gray}# Login to your account${colors.reset}\n oauth.do login\n\n ${colors.gray}# Check who is logged in${colors.reset}\n oauth.do whoami\n\n ${colors.gray}# Get your authentication token${colors.reset}\n oauth.do token\n\n ${colors.gray}# Logout${colors.reset}\n oauth.do logout\n\n${colors.cyan}Environment Variables:${colors.reset}\n OAUTH_CLIENT_ID Client ID for OAuth\n OAUTH_AUTHKIT_DOMAIN AuthKit domain (default: login.oauth.do)\n OAUTH_API_URL API base URL (default: https://apis.do)\n DEBUG Enable debug output\n`)\n}\n\n/**\n * Print version\n */\nfunction printVersion() {\n\ttry {\n\t\t// Dynamic import of package.json\n\t\timport('../package.json', { assert: { type: 'json' } }).then((pkg) => {\n\t\t\tconsole.log(`oauth.do v${pkg.default.version}`)\n\t\t})\n\t} catch {\n\t\tconsole.log('oauth.do')\n\t}\n}\n\n/**\n * Login command - device authorization flow\n */\nasync function loginCommand() {\n\ttry {\n\t\tconsole.log(`${colors.bright}Starting OAuth login...${colors.reset}\\n`)\n\n\t\t// Step 1: Authorize device\n\t\tprintInfo('Requesting device authorization...')\n\t\tconst authResponse = await authorizeDevice()\n\n\t\t// Step 2: Display instructions to user\n\t\tconsole.log(`\\n${colors.bright}To complete login:${colors.reset}`)\n\t\tconsole.log(`\\n 1. Visit: ${colors.cyan}${authResponse.verification_uri}${colors.reset}`)\n\t\tconsole.log(` 2. Enter code: ${colors.bright}${colors.yellow}${authResponse.user_code}${colors.reset}`)\n\t\tconsole.log(`\\n ${colors.dim}Or open this URL directly:${colors.reset}`)\n\t\tconsole.log(` ${colors.blue}${authResponse.verification_uri_complete}${colors.reset}\\n`)\n\n\t\t// Try to open browser automatically\n\t\tconst open = await import('open').catch(() => null)\n\t\tif (open) {\n\t\t\ttry {\n\t\t\t\tawait open.default(authResponse.verification_uri_complete)\n\t\t\t\tprintInfo('Opened browser for authentication')\n\t\t\t} catch {\n\t\t\t\t// Silently fail if can't open browser\n\t\t\t}\n\t\t}\n\n\t\t// Step 3: Poll for tokens\n\t\tconsole.log(`${colors.dim}Waiting for authorization...${colors.reset}\\n`)\n\t\tconst tokenResponse = await pollForTokens(\n\t\t\tauthResponse.device_code,\n\t\t\tauthResponse.interval,\n\t\t\tauthResponse.expires_in\n\t\t)\n\n\t\t// Step 4: Save token\n\t\tawait storage.setToken(tokenResponse.access_token)\n\n\t\t// Step 5: Get user info\n\t\tconst authResult = await auth(tokenResponse.access_token)\n\n\t\tprintSuccess('Login successful!')\n\t\tif (authResult.user) {\n\t\t\tconsole.log(`\\n${colors.dim}Logged in as:${colors.reset}`)\n\t\t\tif (authResult.user.name) {\n\t\t\t\tconsole.log(` ${colors.bright}${authResult.user.name}${colors.reset}`)\n\t\t\t}\n\t\t\tif (authResult.user.email) {\n\t\t\t\tconsole.log(` ${colors.gray}${authResult.user.email}${colors.reset}`)\n\t\t\t}\n\t\t}\n\n\t\t// Show storage info\n\t\tconst compositeStorage = storage as CompositeTokenStorage\n\t\tif (typeof compositeStorage.getStorageInfo === 'function') {\n\t\t\tconst storageInfo = await compositeStorage.getStorageInfo()\n\t\t\tconst storageLabel =\n\t\t\t\tstorageInfo.type === 'keychain' ? `${colors.green}OS Keychain${colors.reset}` : `${colors.yellow}Secure File${colors.reset}`\n\t\t\tconsole.log(`\\n${colors.dim}Token stored in: ${storageLabel}${colors.reset}`)\n\t\t}\n\t} catch (error) {\n\t\tprintError('Login failed', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Logout command\n */\nasync function logoutCommand() {\n\ttry {\n\t\t// Get current token\n\t\tconst token = await storage.getToken()\n\n\t\tif (!token) {\n\t\t\tprintInfo('Not logged in')\n\t\t\treturn\n\t\t}\n\n\t\t// Call logout endpoint\n\t\tawait logoutFn(token)\n\n\t\t// Remove stored token\n\t\tawait storage.removeToken()\n\n\t\tprintSuccess('Logged out successfully')\n\t} catch (error) {\n\t\tprintError('Logout failed', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Whoami command - show current user\n */\nasync function whoamiCommand() {\n\ttry {\n\t\tconst token = await storage.getToken()\n\n\t\tif (!token) {\n\t\t\tconsole.log(`${colors.dim}Not logged in${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to authenticate`)\n\t\t\treturn\n\t\t}\n\n\t\tconst authResult = await auth(token)\n\n\t\tif (!authResult.user) {\n\t\t\tconsole.log(`${colors.dim}Not authenticated${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to authenticate`)\n\t\t\treturn\n\t\t}\n\n\t\tconsole.log(`${colors.bright}Authenticated as:${colors.reset}`)\n\t\tif (authResult.user.name) {\n\t\t\tconsole.log(` ${colors.green}Name:${colors.reset} ${authResult.user.name}`)\n\t\t}\n\t\tif (authResult.user.email) {\n\t\t\tconsole.log(` ${colors.green}Email:${colors.reset} ${authResult.user.email}`)\n\t\t}\n\t\tif (authResult.user.id) {\n\t\t\tconsole.log(` ${colors.green}ID:${colors.reset} ${authResult.user.id}`)\n\t\t}\n\t} catch (error) {\n\t\tprintError('Failed to get user info', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Token command - display current token\n */\nasync function tokenCommand() {\n\ttry {\n\t\tconst token = await storage.getToken()\n\n\t\tif (!token) {\n\t\t\tconsole.log(`${colors.dim}No token found${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to authenticate`)\n\t\t\treturn\n\t\t}\n\n\t\tconsole.log(token)\n\t} catch (error) {\n\t\tprintError('Failed to get token', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Status command - show authentication and storage status\n */\nasync function statusCommand() {\n\ttry {\n\t\tconsole.log(`${colors.bright}OAuth.do Status${colors.reset}\\n`)\n\n\t\t// Get storage info\n\t\tconst compositeStorage = storage as CompositeTokenStorage\n\t\tif (typeof compositeStorage.getStorageInfo === 'function') {\n\t\t\tconst storageInfo = await compositeStorage.getStorageInfo()\n\t\t\tconst storageLabel =\n\t\t\t\tstorageInfo.type === 'keychain' ? `${colors.green}OS Keychain${colors.reset}` : `${colors.yellow}Secure File${colors.reset}`\n\n\t\t\tconsole.log(`${colors.cyan}Storage:${colors.reset} ${storageLabel}`)\n\n\t\t\tif (storageInfo.type === 'keychain') {\n\t\t\t\tconsole.log(` ${colors.dim}Using system credential manager (most secure)${colors.reset}`)\n\t\t\t} else {\n\t\t\t\tconsole.log(` ${colors.dim}Using ~/.oauth.do/token with 0600 permissions${colors.reset}`)\n\t\t\t}\n\t\t}\n\n\t\t// Get auth status\n\t\tconst token = await storage.getToken()\n\t\tif (!token) {\n\t\t\tconsole.log(`\\n${colors.cyan}Auth:${colors.reset} ${colors.dim}Not authenticated${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to authenticate`)\n\t\t\treturn\n\t\t}\n\n\t\tconst authResult = await auth(token)\n\t\tif (authResult.user) {\n\t\t\tconsole.log(`\\n${colors.cyan}Auth:${colors.reset} ${colors.green}Authenticated${colors.reset}`)\n\t\t\tif (authResult.user.email) {\n\t\t\t\tconsole.log(` ${colors.dim}${authResult.user.email}${colors.reset}`)\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(`\\n${colors.cyan}Auth:${colors.reset} ${colors.yellow}Token expired or invalid${colors.reset}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do login${colors.reset} to re-authenticate`)\n\t\t}\n\t} catch (error) {\n\t\tprintError('Failed to get status', error instanceof Error ? error : undefined)\n\t\tprocess.exit(1)\n\t}\n}\n\n/**\n * Main CLI function\n */\nasync function main() {\n\tconfigureFromEnv()\n\n\tconst args = process.argv.slice(2)\n\n\t// Handle flags\n\tif (args.includes('--help') || args.includes('-h')) {\n\t\tprintHelp()\n\t\tprocess.exit(0)\n\t}\n\n\tif (args.includes('--version') || args.includes('-v')) {\n\t\tprintVersion()\n\t\tprocess.exit(0)\n\t}\n\n\tif (args.includes('--debug')) {\n\t\tprocess.env.DEBUG = 'true'\n\t}\n\n\t// Get command\n\tconst command = args.find((arg) => !arg.startsWith('--'))\n\n\tswitch (command) {\n\t\tcase 'login':\n\t\tcase undefined: // Default to login when no command specified\n\t\t\tawait loginCommand()\n\t\t\tbreak\n\n\t\tcase 'logout':\n\t\t\tawait logoutCommand()\n\t\t\tbreak\n\n\t\tcase 'whoami':\n\t\t\tawait whoamiCommand()\n\t\t\tbreak\n\n\t\tcase 'token':\n\t\t\tawait tokenCommand()\n\t\t\tbreak\n\n\t\tcase 'status':\n\t\t\tawait statusCommand()\n\t\t\tbreak\n\n\t\tdefault:\n\t\t\tprintError(`Unknown command: ${command}`)\n\t\t\tconsole.log(`\\nRun ${colors.cyan}oauth.do --help${colors.reset} for usage information`)\n\t\t\tprocess.exit(1)\n\t}\n}\n\n// Run CLI\nmain().catch((error) => {\n\tprintError('Unexpected error', error)\n\tprocess.exit(1)\n})\n\nexport { main }\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -156,45 +156,38 @@ declare function authorizeDevice(): Promise<DeviceAuthorizationResponse>;
|
|
|
156
156
|
declare function pollForTokens(deviceCode: string, interval?: number, expiresIn?: number): Promise<TokenResponse>;
|
|
157
157
|
|
|
158
158
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* Create, rotate, and delete API keys
|
|
159
|
+
* CLI-centric login utilities
|
|
160
|
+
* Handles device flow with browser auto-launch for CLI apps
|
|
162
161
|
*/
|
|
163
|
-
interface
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
162
|
+
interface LoginOptions {
|
|
163
|
+
/** Open browser automatically (default: true) */
|
|
164
|
+
openBrowser?: boolean;
|
|
165
|
+
/** Custom print function for output */
|
|
166
|
+
print?: (message: string) => void;
|
|
167
|
+
/** Storage to use (default: createSecureStorage()) */
|
|
168
|
+
storage?: {
|
|
169
|
+
getToken: () => Promise<string | null>;
|
|
170
|
+
setToken: (token: string) => Promise<void>;
|
|
171
|
+
removeToken: () => Promise<void>;
|
|
172
|
+
};
|
|
169
173
|
}
|
|
170
|
-
interface
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
scopes?: string[];
|
|
174
|
+
interface LoginResult {
|
|
175
|
+
token: string;
|
|
176
|
+
isNewLogin: boolean;
|
|
174
177
|
}
|
|
175
|
-
interface RotateApiKeyOptions {
|
|
176
|
-
expiresIn?: string;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Create a new API key
|
|
180
|
-
*/
|
|
181
|
-
declare function createApiKey(options: CreateApiKeyOptions, token?: string): Promise<ApiKey>;
|
|
182
|
-
/**
|
|
183
|
-
* List all API keys for the current user
|
|
184
|
-
*/
|
|
185
|
-
declare function listApiKeys(token?: string): Promise<ApiKey[]>;
|
|
186
178
|
/**
|
|
187
|
-
* Get
|
|
179
|
+
* Get existing token or perform device flow login
|
|
180
|
+
* Handles browser launch and token storage automatically
|
|
188
181
|
*/
|
|
189
|
-
declare function
|
|
182
|
+
declare function ensureLoggedIn(options?: LoginOptions): Promise<LoginResult>;
|
|
190
183
|
/**
|
|
191
|
-
*
|
|
184
|
+
* Force a new login (ignores existing token)
|
|
192
185
|
*/
|
|
193
|
-
declare function
|
|
186
|
+
declare function forceLogin(options?: LoginOptions): Promise<LoginResult>;
|
|
194
187
|
/**
|
|
195
|
-
*
|
|
188
|
+
* Logout and remove stored token
|
|
196
189
|
*/
|
|
197
|
-
declare function
|
|
190
|
+
declare function ensureLoggedOut(options?: LoginOptions): Promise<void>;
|
|
198
191
|
|
|
199
192
|
/**
|
|
200
193
|
* Keychain-based token storage using OS credential manager
|
|
@@ -302,4 +295,4 @@ declare class CompositeTokenStorage implements TokenStorage {
|
|
|
302
295
|
*/
|
|
303
296
|
declare function createSecureStorage(): TokenStorage;
|
|
304
297
|
|
|
305
|
-
export { type
|
|
298
|
+
export { type AuthResult, CompositeTokenStorage, type DeviceAuthorizationResponse, FileTokenStorage, KeychainTokenStorage, LocalStorageTokenStorage, type LoginOptions, type LoginResult, MemoryTokenStorage, type OAuthConfig, SecureFileTokenStorage, type TokenError, type TokenResponse, type TokenStorage, type User, auth, authorizeDevice, buildAuthUrl, configure, createSecureStorage, ensureLoggedIn, ensureLoggedOut, forceLogin, getConfig, getToken, isAuthenticated, login, logout, pollForTokens };
|
package/dist/index.js
CHANGED
|
@@ -326,7 +326,7 @@ function getEnv(key) {
|
|
|
326
326
|
}
|
|
327
327
|
var globalConfig = {
|
|
328
328
|
apiUrl: getEnv("OAUTH_API_URL") || getEnv("API_URL") || "https://apis.do",
|
|
329
|
-
clientId: getEnv("OAUTH_CLIENT_ID") || "
|
|
329
|
+
clientId: getEnv("OAUTH_CLIENT_ID") || "client_01JQYTRXK9ZPD8JPJTKDCRB656",
|
|
330
330
|
authKitDomain: getEnv("OAUTH_AUTHKIT_DOMAIN") || "login.oauth.do",
|
|
331
331
|
fetch: globalThis.fetch
|
|
332
332
|
};
|
|
@@ -454,17 +454,18 @@ async function authorizeDevice() {
|
|
|
454
454
|
throw new Error('Client ID is required for device authorization. Set OAUTH_CLIENT_ID or configure({ clientId: "..." })');
|
|
455
455
|
}
|
|
456
456
|
try {
|
|
457
|
-
const
|
|
457
|
+
const url = "https://auth.apis.do/user_management/authorize/device";
|
|
458
|
+
const body = new URLSearchParams({ client_id: config.clientId });
|
|
459
|
+
const response = await config.fetch(url, {
|
|
458
460
|
method: "POST",
|
|
459
461
|
headers: {
|
|
460
462
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
461
463
|
},
|
|
462
|
-
body
|
|
463
|
-
client_id: config.clientId
|
|
464
|
-
})
|
|
464
|
+
body
|
|
465
465
|
});
|
|
466
466
|
if (!response.ok) {
|
|
467
|
-
|
|
467
|
+
const errorText = await response.text();
|
|
468
|
+
throw new Error(`Device authorization failed: ${response.statusText} - ${errorText}`);
|
|
468
469
|
}
|
|
469
470
|
const data = await response.json();
|
|
470
471
|
return data;
|
|
@@ -487,7 +488,7 @@ async function pollForTokens(deviceCode, interval = 5, expiresIn = 600) {
|
|
|
487
488
|
}
|
|
488
489
|
await new Promise((resolve) => setTimeout(resolve, currentInterval));
|
|
489
490
|
try {
|
|
490
|
-
const response = await config.fetch(
|
|
491
|
+
const response = await config.fetch("https://auth.apis.do/user_management/authenticate", {
|
|
491
492
|
method: "POST",
|
|
492
493
|
headers: {
|
|
493
494
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
@@ -526,112 +527,54 @@ async function pollForTokens(deviceCode, interval = 5, expiresIn = 600) {
|
|
|
526
527
|
}
|
|
527
528
|
}
|
|
528
529
|
|
|
529
|
-
// src/
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
const config = getConfig();
|
|
537
|
-
const authToken = token || getEnv4("DO_TOKEN");
|
|
538
|
-
if (!authToken) {
|
|
539
|
-
throw new Error("Authentication required to create API key");
|
|
540
|
-
}
|
|
541
|
-
const response = await config.fetch(`${config.apiUrl}/api-keys`, {
|
|
542
|
-
method: "POST",
|
|
543
|
-
headers: {
|
|
544
|
-
"Authorization": `Bearer ${authToken}`,
|
|
545
|
-
"Content-Type": "application/json"
|
|
546
|
-
},
|
|
547
|
-
body: JSON.stringify(options)
|
|
548
|
-
});
|
|
549
|
-
if (!response.ok) {
|
|
550
|
-
const error = await response.text();
|
|
551
|
-
throw new Error(`Failed to create API key: ${error}`);
|
|
552
|
-
}
|
|
553
|
-
return response.json();
|
|
554
|
-
}
|
|
555
|
-
async function listApiKeys(token) {
|
|
556
|
-
const config = getConfig();
|
|
557
|
-
const authToken = token || getEnv4("DO_TOKEN");
|
|
558
|
-
if (!authToken) {
|
|
559
|
-
throw new Error("Authentication required to list API keys");
|
|
560
|
-
}
|
|
561
|
-
const response = await config.fetch(`${config.apiUrl}/api-keys`, {
|
|
562
|
-
method: "GET",
|
|
563
|
-
headers: {
|
|
564
|
-
"Authorization": `Bearer ${authToken}`,
|
|
565
|
-
"Content-Type": "application/json"
|
|
566
|
-
}
|
|
567
|
-
});
|
|
568
|
-
if (!response.ok) {
|
|
569
|
-
const error = await response.text();
|
|
570
|
-
throw new Error(`Failed to list API keys: ${error}`);
|
|
571
|
-
}
|
|
572
|
-
return response.json();
|
|
573
|
-
}
|
|
574
|
-
async function getApiKey(id, token) {
|
|
575
|
-
const config = getConfig();
|
|
576
|
-
const authToken = token || getEnv4("DO_TOKEN");
|
|
577
|
-
if (!authToken) {
|
|
578
|
-
throw new Error("Authentication required to get API key");
|
|
530
|
+
// src/login.ts
|
|
531
|
+
init_storage();
|
|
532
|
+
async function ensureLoggedIn(options = {}) {
|
|
533
|
+
const { openBrowser = true, print = console.log, storage = createSecureStorage() } = options;
|
|
534
|
+
const existingToken = await storage.getToken();
|
|
535
|
+
if (existingToken) {
|
|
536
|
+
return { token: existingToken, isNewLogin: false };
|
|
579
537
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
538
|
+
print("\nLogging in...\n");
|
|
539
|
+
const authResponse = await authorizeDevice();
|
|
540
|
+
print(`To complete login:`);
|
|
541
|
+
print(` 1. Visit: ${authResponse.verification_uri}`);
|
|
542
|
+
print(` 2. Enter code: ${authResponse.user_code}`);
|
|
543
|
+
print(`
|
|
544
|
+
Or open: ${authResponse.verification_uri_complete}
|
|
545
|
+
`);
|
|
546
|
+
if (openBrowser) {
|
|
547
|
+
try {
|
|
548
|
+
const open = await import('open');
|
|
549
|
+
await open.default(authResponse.verification_uri_complete);
|
|
550
|
+
print("Browser opened automatically\n");
|
|
551
|
+
} catch {
|
|
585
552
|
}
|
|
586
|
-
});
|
|
587
|
-
if (!response.ok) {
|
|
588
|
-
const error = await response.text();
|
|
589
|
-
throw new Error(`Failed to get API key: ${error}`);
|
|
590
553
|
}
|
|
591
|
-
|
|
554
|
+
print("Waiting for authorization...\n");
|
|
555
|
+
const tokenResponse = await pollForTokens(
|
|
556
|
+
authResponse.device_code,
|
|
557
|
+
authResponse.interval,
|
|
558
|
+
authResponse.expires_in
|
|
559
|
+
);
|
|
560
|
+
await storage.setToken(tokenResponse.access_token);
|
|
561
|
+
print("Login successful!\n");
|
|
562
|
+
return { token: tokenResponse.access_token, isNewLogin: true };
|
|
592
563
|
}
|
|
593
|
-
async function
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
throw new Error("Authentication required to rotate API key");
|
|
598
|
-
}
|
|
599
|
-
const response = await config.fetch(`${config.apiUrl}/api-keys/${id}/rotate`, {
|
|
600
|
-
method: "POST",
|
|
601
|
-
headers: {
|
|
602
|
-
"Authorization": `Bearer ${authToken}`,
|
|
603
|
-
"Content-Type": "application/json"
|
|
604
|
-
},
|
|
605
|
-
body: JSON.stringify(options || {})
|
|
606
|
-
});
|
|
607
|
-
if (!response.ok) {
|
|
608
|
-
const error = await response.text();
|
|
609
|
-
throw new Error(`Failed to rotate API key: ${error}`);
|
|
610
|
-
}
|
|
611
|
-
return response.json();
|
|
564
|
+
async function forceLogin(options = {}) {
|
|
565
|
+
const { storage = createSecureStorage() } = options;
|
|
566
|
+
await storage.removeToken();
|
|
567
|
+
return ensureLoggedIn(options);
|
|
612
568
|
}
|
|
613
|
-
async function
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
throw new Error("Authentication required to delete API key");
|
|
618
|
-
}
|
|
619
|
-
const response = await config.fetch(`${config.apiUrl}/api-keys/${id}`, {
|
|
620
|
-
method: "DELETE",
|
|
621
|
-
headers: {
|
|
622
|
-
"Authorization": `Bearer ${authToken}`,
|
|
623
|
-
"Content-Type": "application/json"
|
|
624
|
-
}
|
|
625
|
-
});
|
|
626
|
-
if (!response.ok) {
|
|
627
|
-
const error = await response.text();
|
|
628
|
-
throw new Error(`Failed to delete API key: ${error}`);
|
|
629
|
-
}
|
|
569
|
+
async function ensureLoggedOut(options = {}) {
|
|
570
|
+
const { print = console.log, storage = createSecureStorage() } = options;
|
|
571
|
+
await storage.removeToken();
|
|
572
|
+
print("Logged out successfully\n");
|
|
630
573
|
}
|
|
631
574
|
|
|
632
575
|
// src/index.ts
|
|
633
576
|
init_storage();
|
|
634
577
|
|
|
635
|
-
export { CompositeTokenStorage, FileTokenStorage, KeychainTokenStorage, LocalStorageTokenStorage, MemoryTokenStorage, SecureFileTokenStorage, auth, authorizeDevice, buildAuthUrl, configure,
|
|
578
|
+
export { CompositeTokenStorage, FileTokenStorage, KeychainTokenStorage, LocalStorageTokenStorage, MemoryTokenStorage, SecureFileTokenStorage, auth, authorizeDevice, buildAuthUrl, configure, createSecureStorage, ensureLoggedIn, ensureLoggedOut, forceLogin, getConfig, getToken, isAuthenticated, login, logout, pollForTokens };
|
|
636
579
|
//# sourceMappingURL=index.js.map
|
|
637
580
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/storage.ts","../src/config.ts","../src/auth.ts","../src/device.ts","../src/apikey.ts","../src/index.ts"],"names":["getEnv","createSecureStorage"],"mappings":";;;;;;;;;;;AAAA,IAAA,eAAA,GAAA,EAAA;AAAA,QAAA,CAAA,eAAA,EAAA;AAAA,EAAA,qBAAA,EAAA,MAAA,qBAAA;AAAA,EAAA,gBAAA,EAAA,MAAA,gBAAA;AAAA,EAAA,oBAAA,EAAA,MAAA,oBAAA;AAAA,EAAA,wBAAA,EAAA,MAAA,wBAAA;AAAA,EAAA,kBAAA,EAAA,MAAA,kBAAA;AAAA,EAAA,sBAAA,EAAA,MAAA,sBAAA;AAAA,EAAA,mBAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AASA,SAAS,MAAA,GAAkB;AAC1B,EAAA,OAAO,OAAO,YAAY,WAAA,IACzB,OAAA,CAAQ,YAAY,IAAA,IACpB,OAAA,CAAQ,SAAS,IAAA,IAAQ,IAAA;AAC3B;AAKA,SAASA,QAAO,GAAA,EAAiC;AAChD,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,GAAA,GAAM,GAAG,CAAA,EAAG,OAAO,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAChF,EAAA,OAAO,MAAA;AACR;AAsYO,SAAS,mBAAA,GAAoC;AAEnD,EAAA,IAAI,QAAO,EAAG;AACb,IAAA,OAAO,IAAI,qBAAA,EAAsB;AAAA,EAClC;AAGA,EAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACxC,IAAA,OAAO,IAAI,wBAAA,EAAyB;AAAA,EACrC;AAGA,EAAA,OAAO,IAAI,kBAAA,EAAmB;AAC/B;AAxaA,IAGM,kBACA,gBAAA,CAAA,CA2BO,oBAAA,CAAA,CAkGA,sBAAA,CAAA,CAsFA,gBAAA,CAAA,CAgEA,oBAmBA,wBAAA,CAAA,CA6BA;AAvUb,IAAA,YAAA,GAAA,KAAA,CAAA;AAAA,EAAA,gBAAA,GAAA;AAGA,IAAM,gBAAA,GAAmB,UAAA;AACzB,IAAM,gBAAA,GAAmB,cAAA;AA2BlB,IAAM,uBAAN,MAAmD;AAAA,MACjD,MAAA,GAAyC,IAAA;AAAA,MACzC,WAAA,GAAc,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMtB,MAAc,SAAA,GAAqD;AAClE,QAAA,IAAI,KAAK,WAAA,EAAa;AACrB,UAAA,OAAO,IAAA,CAAK,MAAA;AAAA,QACb;AAEA,QAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAEnB,QAAA,IAAI;AAEH,UAAA,IAAA,CAAK,MAAA,GAAS,MAAM,OAAO,QAAQ,CAAA;AACnC,UAAA,OAAO,IAAA,CAAK,MAAA;AAAA,QACb,SAAS,KAAA,EAAO;AAGf,UAAA,IAAIA,OAAAA,CAAO,OAAO,CAAA,EAAG;AACpB,YAAA,OAAA,CAAQ,IAAA,CAAK,mCAAmC,KAAK,CAAA;AAAA,UACtD;AACA,UAAA,OAAO,IAAA;AAAA,QACR;AAAA,MACD;AAAA,MAEA,MAAM,QAAA,GAAmC;AACxC,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,SAAA,EAAU;AACpC,QAAA,IAAI,CAAC,MAAA,EAAQ;AACZ,UAAA,OAAO,IAAA;AAAA,QACR;AAEA,QAAA,IAAI;AACH,UAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,WAAA,CAAY,kBAAkB,gBAAgB,CAAA;AACzE,UAAA,OAAO,KAAA;AAAA,QACR,SAAS,KAAA,EAAO;AACf,UAAA,IAAIA,OAAAA,CAAO,OAAO,CAAA,EAAG;AACpB,YAAA,OAAA,CAAQ,IAAA,CAAK,sCAAsC,KAAK,CAAA;AAAA,UACzD;AACA,UAAA,OAAO,IAAA;AAAA,QACR;AAAA,MACD;AAAA,MAEA,MAAM,SAAS,KAAA,EAA8B;AAC5C,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,SAAA,EAAU;AACpC,QAAA,IAAI,CAAC,MAAA,EAAQ;AACZ,UAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,QACjD;AAEA,QAAA,IAAI;AACH,UAAA,MAAM,MAAA,CAAO,WAAA,CAAY,gBAAA,EAAkB,gBAAA,EAAkB,KAAK,CAAA;AAAA,QACnE,SAAS,KAAA,EAAO;AACf,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kCAAA,EAAqC,KAAK,CAAA,CAAE,CAAA;AAAA,QAC7D;AAAA,MACD;AAAA,MAEA,MAAM,WAAA,GAA6B;AAClC,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,SAAA,EAAU;AACpC,QAAA,IAAI,CAAC,MAAA,EAAQ;AACZ,UAAA;AAAA,QACD;AAEA,QAAA,IAAI;AACH,UAAA,MAAM,MAAA,CAAO,cAAA,CAAe,gBAAA,EAAkB,gBAAgB,CAAA;AAAA,QAC/D,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACD;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,WAAA,GAAgC;AACrC,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,SAAA,EAAU;AACpC,QAAA,IAAI,CAAC,MAAA,EAAQ;AACZ,UAAA,OAAO,KAAA;AAAA,QACR;AAEA,QAAA,IAAI;AAEH,UAAA,MAAM,MAAA,CAAO,WAAA,CAAY,gBAAA,EAAkB,UAAU,CAAA;AACrD,UAAA,OAAO,IAAA;AAAA,QACR,CAAA,CAAA,MAAQ;AACP,UAAA,OAAO,KAAA;AAAA,QACR;AAAA,MACD;AAAA,KACD;AASO,IAAM,yBAAN,MAAqD;AAAA,MACnD,SAAA,GAA2B,IAAA;AAAA,MAC3B,SAAA,GAA2B,IAAA;AAAA,MAC3B,WAAA,GAAc,KAAA;AAAA,MAEtB,MAAc,IAAA,GAAyB;AACtC,QAAA,IAAI,IAAA,CAAK,WAAA,EAAa,OAAO,IAAA,CAAK,SAAA,KAAc,IAAA;AAChD,QAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAEnB,QAAA,IAAI,CAAC,MAAA,EAAO,EAAG,OAAO,KAAA;AAEtB,QAAA,IAAI;AACH,UAAA,MAAM,EAAA,GAAK,MAAM,OAAO,IAAI,CAAA;AAC5B,UAAA,MAAM,IAAA,GAAO,MAAM,OAAO,MAAM,CAAA;AAChC,UAAA,IAAA,CAAK,YAAY,IAAA,CAAK,IAAA,CAAK,EAAA,CAAG,OAAA,IAAW,WAAW,CAAA;AACpD,UAAA,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,WAAW,OAAO,CAAA;AAClD,UAAA,OAAO,IAAA;AAAA,QACR,CAAA,CAAA,MAAQ;AACP,UAAA,OAAO,KAAA;AAAA,QACR;AAAA,MACD;AAAA,MAEA,MAAM,QAAA,GAAmC;AACxC,QAAA,IAAI,CAAE,MAAM,IAAA,CAAK,IAAA,MAAW,CAAC,IAAA,CAAK,WAAW,OAAO,IAAA;AAEpD,QAAA,IAAI;AACH,UAAA,MAAM,EAAA,GAAK,MAAM,OAAO,aAAa,CAAA;AAErC,UAAA,MAAM,KAAA,GAAQ,MAAM,EAAA,CAAG,IAAA,CAAK,KAAK,SAAS,CAAA;AAC1C,UAAA,MAAM,IAAA,GAAO,MAAM,IAAA,GAAO,GAAA;AAG1B,UAAA,IAAI,IAAA,KAAS,GAAA,IAASA,OAAAA,CAAO,OAAO,CAAA,EAAG;AACtC,YAAA,OAAA,CAAQ,IAAA;AAAA,cACP,iDAAiD,IAAA,CAAK,QAAA,CAAS,CAAC,CAAC,CAAA,gCAAA,EAChC,KAAK,SAAS,CAAA;AAAA,aAChD;AAAA,UACD;AAEA,UAAA,MAAM,QAAQ,MAAM,EAAA,CAAG,QAAA,CAAS,IAAA,CAAK,WAAW,OAAO,CAAA;AACvD,UAAA,OAAO,MAAM,IAAA,EAAK;AAAA,QACnB,CAAA,CAAA,MAAQ;AACP,UAAA,OAAO,IAAA;AAAA,QACR;AAAA,MACD;AAAA,MAEA,MAAM,SAAS,KAAA,EAA8B;AAC5C,QAAA,IAAI,CAAE,MAAM,IAAA,CAAK,IAAA,EAAK,IAAM,CAAC,IAAA,CAAK,SAAA,IAAa,CAAC,IAAA,CAAK,SAAA,EAAW;AAC/D,UAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,QAC7C;AAEA,QAAA,IAAI;AACH,UAAA,MAAM,EAAA,GAAK,MAAM,OAAO,aAAa,CAAA;AAErC,UAAA,MAAM,EAAA,CAAG,MAAM,IAAA,CAAK,SAAA,EAAW,EAAE,SAAA,EAAW,IAAA,EAAM,IAAA,EAAM,GAAA,EAAO,CAAA;AAG/D,UAAA,MAAM,EAAA,CAAG,SAAA,CAAU,IAAA,CAAK,SAAA,EAAW,KAAA,EAAO,EAAE,QAAA,EAAU,OAAA,EAAS,IAAA,EAAM,GAAA,EAAO,CAAA;AAG5E,UAAA,MAAM,EAAA,CAAG,KAAA,CAAM,IAAA,CAAK,SAAA,EAAW,GAAK,CAAA;AAAA,QACrC,SAAS,KAAA,EAAO;AACf,UAAA,OAAA,CAAQ,KAAA,CAAM,yBAAyB,KAAK,CAAA;AAC5C,UAAA,MAAM,KAAA;AAAA,QACP;AAAA,MACD;AAAA,MAEA,MAAM,WAAA,GAA6B;AAClC,QAAA,IAAI,CAAE,MAAM,IAAA,CAAK,MAAK,IAAM,CAAC,KAAK,SAAA,EAAW;AAE7C,QAAA,IAAI;AACH,UAAA,MAAM,EAAA,GAAK,MAAM,OAAO,aAAa,CAAA;AACrC,UAAA,MAAM,EAAA,CAAG,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA;AAAA,QAC/B,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACD;AAAA,KACD;AASO,IAAM,mBAAN,MAA+C;AAAA,MAC7C,SAAA,GAA2B,IAAA;AAAA,MAC3B,SAAA,GAA2B,IAAA;AAAA,MAC3B,WAAA,GAAc,KAAA;AAAA,MAEtB,MAAc,IAAA,GAAyB;AACtC,QAAA,IAAI,IAAA,CAAK,WAAA,EAAa,OAAO,IAAA,CAAK,SAAA,KAAc,IAAA;AAChD,QAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAEnB,QAAA,IAAI,CAAC,MAAA,EAAO,EAAG,OAAO,KAAA;AAEtB,QAAA,IAAI;AACH,UAAA,MAAM,EAAA,GAAK,MAAM,OAAO,IAAI,CAAA;AAC5B,UAAA,MAAM,IAAA,GAAO,MAAM,OAAO,MAAM,CAAA;AAChC,UAAA,IAAA,CAAK,YAAY,IAAA,CAAK,IAAA,CAAK,EAAA,CAAG,OAAA,IAAW,WAAW,CAAA;AACpD,UAAA,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,WAAW,OAAO,CAAA;AAClD,UAAA,OAAO,IAAA;AAAA,QACR,CAAA,CAAA,MAAQ;AACP,UAAA,OAAO,KAAA;AAAA,QACR;AAAA,MACD;AAAA,MAEA,MAAM,QAAA,GAAmC;AACxC,QAAA,IAAI,CAAE,MAAM,IAAA,CAAK,IAAA,MAAW,CAAC,IAAA,CAAK,WAAW,OAAO,IAAA;AAEpD,QAAA,IAAI;AACH,UAAA,MAAM,EAAA,GAAK,MAAM,OAAO,aAAa,CAAA;AACrC,UAAA,MAAM,QAAQ,MAAM,EAAA,CAAG,QAAA,CAAS,IAAA,CAAK,WAAW,OAAO,CAAA;AACvD,UAAA,OAAO,MAAM,IAAA,EAAK;AAAA,QACnB,CAAA,CAAA,MAAQ;AACP,UAAA,OAAO,IAAA;AAAA,QACR;AAAA,MACD;AAAA,MAEA,MAAM,SAAS,KAAA,EAA8B;AAC5C,QAAA,IAAI,CAAE,MAAM,IAAA,CAAK,IAAA,EAAK,IAAM,CAAC,IAAA,CAAK,SAAA,IAAa,CAAC,IAAA,CAAK,SAAA,EAAW;AAC/D,UAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,QAC7C;AAEA,QAAA,IAAI;AACH,UAAA,MAAM,EAAA,GAAK,MAAM,OAAO,aAAa,CAAA;AACrC,UAAA,MAAM,GAAG,KAAA,CAAM,IAAA,CAAK,WAAW,EAAE,SAAA,EAAW,MAAM,CAAA;AAClD,UAAA,MAAM,EAAA,CAAG,SAAA,CAAU,IAAA,CAAK,SAAA,EAAW,OAAO,OAAO,CAAA;AAAA,QAClD,SAAS,KAAA,EAAO;AACf,UAAA,OAAA,CAAQ,KAAA,CAAM,yBAAyB,KAAK,CAAA;AAC5C,UAAA,MAAM,KAAA;AAAA,QACP;AAAA,MACD;AAAA,MAEA,MAAM,WAAA,GAA6B;AAClC,QAAA,IAAI,CAAE,MAAM,IAAA,CAAK,MAAK,IAAM,CAAC,KAAK,SAAA,EAAW;AAE7C,QAAA,IAAI;AACH,UAAA,MAAM,EAAA,GAAK,MAAM,OAAO,aAAa,CAAA;AACrC,UAAA,MAAM,EAAA,CAAG,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA;AAAA,QAC/B,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACD;AAAA,KACD;AAKO,IAAM,qBAAN,MAAiD;AAAA,MAC/C,KAAA,GAAuB,IAAA;AAAA,MAE/B,MAAM,QAAA,GAAmC;AACxC,QAAA,OAAO,IAAA,CAAK,KAAA;AAAA,MACb;AAAA,MAEA,MAAM,SAAS,KAAA,EAA8B;AAC5C,QAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,MACd;AAAA,MAEA,MAAM,WAAA,GAA6B;AAClC,QAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,MACd;AAAA,KACD;AAKO,IAAM,2BAAN,MAAuD;AAAA,MACrD,GAAA,GAAM,gBAAA;AAAA,MAEd,MAAM,QAAA,GAAmC;AACxC,QAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACxC,UAAA,OAAO,IAAA;AAAA,QACR;AACA,QAAA,OAAO,YAAA,CAAa,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA;AAAA,MACrC;AAAA,MAEA,MAAM,SAAS,KAAA,EAA8B;AAC5C,QAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACxC,UAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,QAChD;AACA,QAAA,YAAA,CAAa,OAAA,CAAQ,IAAA,CAAK,GAAA,EAAK,KAAK,CAAA;AAAA,MACrC;AAAA,MAEA,MAAM,WAAA,GAA6B;AAClC,QAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACxC,UAAA;AAAA,QACD;AACA,QAAA,YAAA,CAAa,UAAA,CAAW,KAAK,GAAG,CAAA;AAAA,MACjC;AAAA,KACD;AAMO,IAAM,wBAAN,MAAoD;AAAA,MAClD,eAAA;AAAA,MACA,WAAA;AAAA,MACA,gBAAA,GAAwC,IAAA;AAAA,MAEhD,WAAA,GAAc;AACb,QAAA,IAAA,CAAK,eAAA,GAAkB,IAAI,oBAAA,EAAqB;AAChD,QAAA,IAAA,CAAK,WAAA,GAAc,IAAI,sBAAA,EAAuB;AAAA,MAC/C;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,mBAAA,GAA6C;AAC1D,QAAA,IAAI,KAAK,gBAAA,EAAkB;AAC1B,UAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,QACb;AAGA,QAAA,IAAI,MAAM,IAAA,CAAK,eAAA,CAAgB,WAAA,EAAY,EAAG;AAC7C,UAAA,IAAA,CAAK,mBAAmB,IAAA,CAAK,eAAA;AAC7B,UAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,QACb;AAGA,QAAA,IAAA,CAAK,mBAAmB,IAAA,CAAK,WAAA;AAC7B,QAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,MACb;AAAA,MAEA,MAAM,QAAA,GAAmC;AAExC,QAAA,MAAM,aAAA,GAAgB,MAAM,IAAA,CAAK,eAAA,CAAgB,QAAA,EAAS;AAC1D,QAAA,IAAI,aAAA,EAAe;AAClB,UAAA,OAAO,aAAA;AAAA,QACR;AAGA,QAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,WAAA,CAAY,QAAA,EAAS;AAClD,QAAA,IAAI,SAAA,EAAW;AAEd,UAAA,IAAI,MAAM,IAAA,CAAK,eAAA,CAAgB,WAAA,EAAY,EAAG;AAC7C,YAAA,IAAI;AACH,cAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,QAAA,CAAS,SAAS,CAAA;AAC7C,cAAA,MAAM,IAAA,CAAK,YAAY,WAAA,EAAY;AACnC,cAAA,IAAIA,OAAAA,CAAO,OAAO,CAAA,EAAG;AACpB,gBAAA,OAAA,CAAQ,IAAI,sCAAsC,CAAA;AAAA,cACnD;AAAA,YACD,CAAA,CAAA,MAAQ;AAAA,YAER;AAAA,UACD;AACA,UAAA,OAAO,SAAA;AAAA,QACR;AAEA,QAAA,OAAO,IAAA;AAAA,MACR;AAAA,MAEA,MAAM,SAAS,KAAA,EAA8B;AAC5C,QAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,mBAAA,EAAoB;AAC/C,QAAA,MAAM,OAAA,CAAQ,SAAS,KAAK,CAAA;AAAA,MAC7B;AAAA,MAEA,MAAM,WAAA,GAA6B;AAElC,QAAA,MAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,IAAA,CAAK,eAAA,CAAgB,WAAA,EAAY,EAAG,IAAA,CAAK,WAAA,CAAY,WAAA,EAAa,CAAC,CAAA;AAAA,MACvF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,cAAA,GAA0E;AAC/E,QAAA,IAAI,MAAM,IAAA,CAAK,eAAA,CAAgB,WAAA,EAAY,EAAG;AAC7C,UAAA,OAAO,EAAE,IAAA,EAAM,UAAA,EAAY,MAAA,EAAQ,IAAA,EAAK;AAAA,QACzC;AACA,QAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAK;AAAA,MACrC;AAAA,KACD;AAAA,EAAA;AAAA,CAAA,CAAA;;;AC9YA,SAAS,OAAO,GAAA,EAAiC;AAEhD,EAAA,IAAK,UAAA,CAAmB,GAAG,CAAA,EAAG,OAAQ,WAAmB,GAAG,CAAA;AAE5D,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,GAAA,GAAM,GAAG,CAAA,EAAG,OAAO,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAChF,EAAA,OAAO,MAAA;AACR;AAKA,IAAI,YAAA,GAAsC;AAAA,EACzC,QAAQ,MAAA,CAAO,eAAe,CAAA,IAAK,MAAA,CAAO,SAAS,CAAA,IAAK,iBAAA;AAAA,EACxD,QAAA,EAAU,MAAA,CAAO,iBAAiB,CAAA,IAAK,UAAA;AAAA,EACvC,aAAA,EAAe,MAAA,CAAO,sBAAsB,CAAA,IAAK,gBAAA;AAAA,EACjD,OAAO,UAAA,CAAW;AACnB,CAAA;AAKO,SAAS,UAAU,MAAA,EAA2B;AACpD,EAAA,YAAA,GAAe;AAAA,IACd,GAAG,YAAA;AAAA,IACH,GAAG;AAAA,GACJ;AACD;AAKO,SAAS,SAAA,GAAmC;AAClD,EAAA,OAAO,YAAA;AACR;;;AChCA,SAASA,QAAO,GAAA,EAAiC;AAEhD,EAAA,IAAK,UAAA,CAAmB,GAAG,CAAA,EAAG,OAAQ,WAAmB,GAAG,CAAA;AAE5D,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,GAAA,GAAM,GAAG,CAAA,EAAG,OAAO,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAChF,EAAA,OAAO,MAAA;AACR;AASA,eAAsB,KAAK,KAAA,EAAqC;AAC/D,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,SAAA,GAAY,KAAA,IAASA,OAAAA,CAAO,UAAU,CAAA,IAAK,EAAA;AAEjD,EAAA,IAAI,CAAC,SAAA,EAAW;AACf,IAAA,OAAO,EAAE,MAAM,IAAA,EAAK;AAAA,EACrB;AAEA,EAAA,IAAI;AACH,IAAA,MAAM,WAAW,MAAM,MAAA,CAAO,MAAM,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA,GAAA,CAAA,EAAO;AAAA,MAC1D,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACR,eAAA,EAAiB,UAAU,SAAS,CAAA,CAAA;AAAA,QACpC,cAAA,EAAgB;AAAA;AACjB,KACA,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACjB,MAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC5B,QAAA,OAAO,EAAE,MAAM,IAAA,EAAK;AAAA,MACrB;AACA,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IAChE;AAEA,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,SAAA,EAAU;AAAA,EACjC,SAAS,KAAA,EAAO;AACf,IAAA,OAAA,CAAQ,KAAA,CAAM,eAAe,KAAK,CAAA;AAClC,IAAA,OAAO,EAAE,MAAM,IAAA,EAAK;AAAA,EACrB;AACD;AASA,eAAsB,MAAM,WAAA,EAIJ;AACvB,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,IAAI;AACH,IAAA,MAAM,WAAW,MAAM,MAAA,CAAO,MAAM,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA,MAAA,CAAA,EAAU;AAAA,MAC7D,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACR,cAAA,EAAgB;AAAA,OACjB;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,WAAW;AAAA,KAChC,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACjB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IACvD;AAEA,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,KAAA,EAAO,KAAK,KAAA,EAAM;AAAA,EAC7C,SAAS,KAAA,EAAO;AACf,IAAA,OAAA,CAAQ,KAAA,CAAM,gBAAgB,KAAK,CAAA;AACnC,IAAA,MAAM,KAAA;AAAA,EACP;AACD;AAQA,eAAsB,OAAO,KAAA,EAA+B;AAC3D,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,SAAA,GAAY,KAAA,IAASA,OAAAA,CAAO,UAAU,CAAA,IAAK,EAAA;AAEjD,EAAA,IAAI,CAAC,SAAA,EAAW;AACf,IAAA;AAAA,EACD;AAEA,EAAA,IAAI;AACH,IAAA,MAAM,WAAW,MAAM,MAAA,CAAO,MAAM,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA,OAAA,CAAA,EAAW;AAAA,MAC9D,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACR,eAAA,EAAiB,UAAU,SAAS,CAAA,CAAA;AAAA,QACpC,cAAA,EAAgB;AAAA;AACjB,KACA,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACjB,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,gBAAA,EAAmB,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IACtD;AAAA,EACD,SAAS,KAAA,EAAO;AACf,IAAA,OAAA,CAAQ,KAAA,CAAM,iBAAiB,KAAK,CAAA;AAAA,EACrC;AACD;AAUA,eAAsB,QAAA,GAAmC;AAExD,EAAA,MAAM,UAAA,GAAaA,QAAO,gBAAgB,CAAA;AAC1C,EAAA,IAAI,YAAY,OAAO,UAAA;AACvB,EAAA,MAAM,OAAA,GAAUA,QAAO,UAAU,CAAA;AACjC,EAAA,IAAI,SAAS,OAAO,OAAA;AAGpB,EAAA,IAAI;AACH,IAAA,MAAM,EAAE,mBAAA,EAAAC,oBAAAA,EAAoB,GAAI,MAAM,OAAA,CAAA,OAAA,EAAA,CAAA,IAAA,CAAA,OAAA,YAAA,EAAA,EAAA,eAAA,CAAA,CAAA;AACtC,IAAA,MAAM,UAAUA,oBAAAA,EAAoB;AACpC,IAAA,OAAO,MAAM,QAAQ,QAAA,EAAS;AAAA,EAC/B,CAAA,CAAA,MAAQ;AAEP,IAAA,OAAO,IAAA;AAAA,EACR;AACD;AAKA,eAAsB,gBAAgB,KAAA,EAAkC;AACvE,EAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,KAAK,CAAA;AAC/B,EAAA,OAAO,OAAO,IAAA,KAAS,IAAA;AACxB;AAWO,SAAS,aAAa,OAAA,EAOlB;AACV,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,MAAA,CAAO,QAAA;AAC5C,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,IAAc,MAAA,CAAO,aAAA;AAEhD,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB;AAAA,IAClC,SAAA,EAAW,QAAA;AAAA,IACX,cAAc,OAAA,CAAQ,WAAA;AAAA,IACtB,aAAA,EAAe,QAAQ,YAAA,IAAgB,MAAA;AAAA,IACvC,KAAA,EAAO,QAAQ,KAAA,IAAS;AAAA,GACxB,CAAA;AAED,EAAA,IAAI,QAAQ,KAAA,EAAO;AAClB,IAAA,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,OAAA,CAAQ,KAAK,CAAA;AAAA,EAClC;AAEA,EAAA,OAAO,CAAA,QAAA,EAAW,UAAU,CAAA,WAAA,EAAc,MAAA,CAAO,UAAU,CAAA,CAAA;AAC5D;;;ACjLA,eAAsB,eAAA,GAAwD;AAC7E,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,IAAI,CAAC,OAAO,QAAA,EAAU;AACrB,IAAA,MAAM,IAAI,MAAM,uGAAuG,CAAA;AAAA,EACxH;AAEA,EAAA,IAAI;AACH,IAAA,MAAM,WAAW,MAAM,MAAA,CAAO,MAAM,CAAA,QAAA,EAAW,MAAA,CAAO,aAAa,CAAA,iBAAA,CAAA,EAAqB;AAAA,MACvF,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACR,cAAA,EAAgB;AAAA,OACjB;AAAA,MACA,IAAA,EAAM,IAAI,eAAA,CAAgB;AAAA,QACzB,WAAW,MAAA,CAAO;AAAA,OAClB;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACjB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6BAAA,EAAgC,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IACtE;AAEA,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,OAAO,IAAA;AAAA,EACR,SAAS,KAAA,EAAO;AACf,IAAA,OAAA,CAAQ,KAAA,CAAM,+BAA+B,KAAK,CAAA;AAClD,IAAA,MAAM,KAAA;AAAA,EACP;AACD;AAUA,eAAsB,aAAA,CACrB,UAAA,EACA,QAAA,GAAmB,CAAA,EACnB,YAAoB,GAAA,EACK;AACzB,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,IAAI,CAAC,OAAO,QAAA,EAAU;AACrB,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAC1D;AAEA,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,EAAA,MAAM,UAAU,SAAA,GAAY,GAAA;AAC5B,EAAA,IAAI,kBAAkB,QAAA,GAAW,GAAA;AAEjC,EAAA,OAAO,IAAA,EAAM;AAEZ,IAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA,GAAY,OAAA,EAAS;AACrC,MAAA,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAAA,IAClE;AAGA,IAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,eAAe,CAAC,CAAA;AAEnE,IAAA,IAAI;AACH,MAAA,MAAM,WAAW,MAAM,MAAA,CAAO,MAAM,CAAA,QAAA,EAAW,MAAA,CAAO,aAAa,CAAA,aAAA,CAAA,EAAiB;AAAA,QACnF,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACR,cAAA,EAAgB;AAAA,SACjB;AAAA,QACA,IAAA,EAAM,IAAI,eAAA,CAAgB;AAAA,UACzB,UAAA,EAAY,8CAAA;AAAA,UACZ,WAAA,EAAa,UAAA;AAAA,UACb,WAAW,MAAA,CAAO;AAAA,SAClB;AAAA,OACD,CAAA;AAED,MAAA,IAAI,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,QAAA,OAAO,IAAA;AAAA,MACR;AAGA,MAAA,MAAM,SAAA,GAAa,MAAM,QAAA,CAAS,IAAA,EAAK,CAAE,MAAM,OAAO,EAAE,KAAA,EAAO,SAAA,EAAU,CAAE,CAAA;AAC3E,MAAA,MAAM,KAAA,GAAS,UAAU,KAAA,IAAS,SAAA;AAElC,MAAA,QAAQ,KAAA;AAAO,QACd,KAAK,uBAAA;AAEJ,UAAA;AAAA,QAED,KAAK,WAAA;AAEJ,UAAA,eAAA,IAAmB,GAAA;AACnB,UAAA;AAAA,QAED,KAAK,eAAA;AACJ,UAAA,MAAM,IAAI,MAAM,uBAAuB,CAAA;AAAA,QAExC,KAAK,eAAA;AACJ,UAAA,MAAM,IAAI,MAAM,qBAAqB,CAAA;AAAA,QAEtC;AACC,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,KAAK,CAAA,CAAE,CAAA;AAAA;AAClD,IACD,SAAS,KAAA,EAAO;AAEf,MAAA,IAAI,iBAAiB,KAAA,EAAO;AAC3B,QAAA,MAAM,KAAA;AAAA,MACP;AAEA,MAAA;AAAA,IACD;AAAA,EACD;AACD;;;AC9GA,SAASD,QAAO,GAAA,EAAiC;AAE/C,EAAA,IAAK,UAAA,CAAmB,GAAG,CAAA,EAAG,OAAQ,WAAmB,GAAG,CAAA;AAE5D,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,GAAA,GAAM,GAAG,CAAA,EAAG,OAAO,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAChF,EAAA,OAAO,MAAA;AACT;AAuBA,eAAsB,YAAA,CACpB,SACA,KAAA,EACiB;AACjB,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,SAAA,GAAY,KAAA,IAASA,OAAAA,CAAO,UAAU,CAAA;AAE5C,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,EAC7D;AAEA,EAAA,MAAM,WAAW,MAAM,MAAA,CAAO,MAAM,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA,SAAA,CAAA,EAAa;AAAA,IAC/D,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,eAAA,EAAiB,UAAU,SAAS,CAAA,CAAA;AAAA,MACpC,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,GAC7B,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,KAAK,CAAA,CAAE,CAAA;AAAA,EACtD;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB;AAKA,eAAsB,YAAY,KAAA,EAAmC;AACnE,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,SAAA,GAAY,KAAA,IAASA,OAAAA,CAAO,UAAU,CAAA;AAE5C,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AAEA,EAAA,MAAM,WAAW,MAAM,MAAA,CAAO,MAAM,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA,SAAA,CAAA,EAAa;AAAA,IAC/D,MAAA,EAAQ,KAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,eAAA,EAAiB,UAAU,SAAS,CAAA,CAAA;AAAA,MACpC,cAAA,EAAgB;AAAA;AAClB,GACD,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,KAAK,CAAA,CAAE,CAAA;AAAA,EACrD;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB;AAKA,eAAsB,SAAA,CAAU,IAAY,KAAA,EAAiC;AAC3E,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,SAAA,GAAY,KAAA,IAASA,OAAAA,CAAO,UAAU,CAAA;AAE5C,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAAA,EAC1D;AAEA,EAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,KAAA,CAAM,GAAG,MAAA,CAAO,MAAM,CAAA,UAAA,EAAa,EAAE,CAAA,CAAA,EAAI;AAAA,IACrE,MAAA,EAAQ,KAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,eAAA,EAAiB,UAAU,SAAS,CAAA,CAAA;AAAA,MACpC,cAAA,EAAgB;AAAA;AAClB,GACD,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,KAAK,CAAA,CAAE,CAAA;AAAA,EACnD;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB;AAKA,eAAsB,YAAA,CACpB,EAAA,EACA,OAAA,EACA,KAAA,EACiB;AACjB,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,SAAA,GAAY,KAAA,IAASA,OAAAA,CAAO,UAAU,CAAA;AAE5C,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,EAC7D;AAEA,EAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,KAAA,CAAM,GAAG,MAAA,CAAO,MAAM,CAAA,UAAA,EAAa,EAAE,CAAA,OAAA,CAAA,EAAW;AAAA,IAC5E,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,eAAA,EAAiB,UAAU,SAAS,CAAA,CAAA;AAAA,MACpC,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAA,IAAW,EAAE;AAAA,GACnC,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,KAAK,CAAA,CAAE,CAAA;AAAA,EACtD;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB;AAKA,eAAsB,YAAA,CAAa,IAAY,KAAA,EAA+B;AAC5E,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,SAAA,GAAY,KAAA,IAASA,OAAAA,CAAO,UAAU,CAAA;AAE5C,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,EAC7D;AAEA,EAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,KAAA,CAAM,GAAG,MAAA,CAAO,MAAM,CAAA,UAAA,EAAa,EAAE,CAAA,CAAA,EAAI;AAAA,IACrE,MAAA,EAAQ,QAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,eAAA,EAAiB,UAAU,SAAS,CAAA,CAAA;AAAA,MACpC,cAAA,EAAgB;AAAA;AAClB,GACD,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,KAAK,CAAA,CAAE,CAAA;AAAA,EACtD;AACF;;;ACtKA,YAAA,EAAA","file":"index.js","sourcesContent":["import type { TokenStorage } from './types.js'\n\n// Keychain service and account identifiers\nconst KEYCHAIN_SERVICE = 'oauth.do'\nconst KEYCHAIN_ACCOUNT = 'access_token'\n\n/**\n * Check if we're running in a Node.js environment\n */\nfunction isNode(): boolean {\n\treturn typeof process !== 'undefined' &&\n\t\tprocess.versions != null &&\n\t\tprocess.versions.node != null\n}\n\n/**\n * Safe environment variable access\n */\nfunction getEnv(key: string): string | undefined {\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Keychain-based token storage using OS credential manager\n * - macOS: Keychain\n * - Windows: Credential Manager\n * - Linux: Secret Service (libsecret)\n *\n * This is the most secure option for CLI token storage.\n */\nexport class KeychainTokenStorage implements TokenStorage {\n\tprivate keytar: typeof import('keytar') | null = null\n\tprivate initialized = false\n\n\t/**\n\t * Lazily load keytar module\n\t * Returns null if keytar is not available (e.g., missing native dependencies)\n\t */\n\tprivate async getKeytar(): Promise<typeof import('keytar') | null> {\n\t\tif (this.initialized) {\n\t\t\treturn this.keytar\n\t\t}\n\n\t\tthis.initialized = true\n\n\t\ttry {\n\t\t\t// Dynamic import to handle cases where keytar native module isn't available\n\t\t\tthis.keytar = await import('keytar')\n\t\t\treturn this.keytar\n\t\t} catch (error) {\n\t\t\t// keytar requires native dependencies that may not be available\n\t\t\t// Fall back gracefully\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain storage not available:', error)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn null\n\t\t}\n\n\t\ttry {\n\t\t\tconst token = await keytar.getPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)\n\t\t\treturn token\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Failed to get token from keychain:', error)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\tthrow new Error('Keychain storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to save token to keychain: ${error}`)\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn\n\t\t}\n\n\t\ttry {\n\t\t\tawait keytar.deletePassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)\n\t\t} catch {\n\t\t\t// Ignore errors if credential doesn't exist\n\t\t}\n\t}\n\n\t/**\n\t * Check if keychain storage is available on this system\n\t */\n\tasync isAvailable(): Promise<boolean> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn false\n\t\t}\n\n\t\ttry {\n\t\t\t// Try a read operation to verify keychain access\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n}\n\n/**\n * Secure file-based token storage for CLI\n * Stores token in ~/.oauth.do/token with restricted permissions (0600)\n *\n * This is used as a fallback when keychain storage is not available.\n * Only works in Node.js environment.\n */\nexport class SecureFileTokenStorage implements TokenStorage {\n\tprivate tokenPath: string | null = null\n\tprivate configDir: string | null = null\n\tprivate initialized = false\n\n\tprivate async init(): Promise<boolean> {\n\t\tif (this.initialized) return this.tokenPath !== null\n\t\tthis.initialized = true\n\n\t\tif (!isNode()) return false\n\n\t\ttry {\n\t\t\tconst os = await import('os')\n\t\t\tconst path = await import('path')\n\t\t\tthis.configDir = path.join(os.homedir(), '.oauth.do')\n\t\t\tthis.tokenPath = path.join(this.configDir, 'token')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (!(await this.init()) || !this.tokenPath) return null\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\t// Verify file permissions before reading\n\t\t\tconst stats = await fs.stat(this.tokenPath)\n\t\t\tconst mode = stats.mode & 0o777\n\n\t\t\t// Warn if file has insecure permissions\n\t\t\tif (mode !== 0o600 && getEnv('DEBUG')) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Warning: Token file has insecure permissions (${mode.toString(8)}). ` +\n\t\t\t\t\t\t`Expected 600. Run: chmod 600 ${this.tokenPath}`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst token = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\treturn token.trim()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath || !this.configDir) {\n\t\t\tthrow new Error('File storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\t// Create config directory with restricted permissions\n\t\t\tawait fs.mkdir(this.configDir, { recursive: true, mode: 0o700 })\n\n\t\t\t// Write token file\n\t\t\tawait fs.writeFile(this.tokenPath, token, { encoding: 'utf-8', mode: 0o600 })\n\n\t\t\t// Ensure permissions are correct (writeFile mode may be affected by umask)\n\t\t\tawait fs.chmod(this.tokenPath, 0o600)\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token:', error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath) return\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.unlink(this.tokenPath)\n\t\t} catch {\n\t\t\t// Ignore errors if file doesn't exist\n\t\t}\n\t}\n}\n\n/**\n * File-based token storage for CLI (legacy, less secure)\n * Stores token in ~/.oauth.do/token\n * Only works in Node.js environment.\n *\n * @deprecated Use SecureFileTokenStorage or KeychainTokenStorage instead\n */\nexport class FileTokenStorage implements TokenStorage {\n\tprivate tokenPath: string | null = null\n\tprivate configDir: string | null = null\n\tprivate initialized = false\n\n\tprivate async init(): Promise<boolean> {\n\t\tif (this.initialized) return this.tokenPath !== null\n\t\tthis.initialized = true\n\n\t\tif (!isNode()) return false\n\n\t\ttry {\n\t\t\tconst os = await import('os')\n\t\t\tconst path = await import('path')\n\t\t\tthis.configDir = path.join(os.homedir(), '.oauth.do')\n\t\t\tthis.tokenPath = path.join(this.configDir, 'token')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (!(await this.init()) || !this.tokenPath) return null\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tconst token = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\treturn token.trim()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath || !this.configDir) {\n\t\t\tthrow new Error('File storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.mkdir(this.configDir, { recursive: true })\n\t\t\tawait fs.writeFile(this.tokenPath, token, 'utf-8')\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token:', error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath) return\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.unlink(this.tokenPath)\n\t\t} catch {\n\t\t\t// Ignore errors if file doesn't exist\n\t\t}\n\t}\n}\n\n/**\n * In-memory token storage (for browser or testing)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n\tprivate token: string | null = null\n\n\tasync getToken(): Promise<string | null> {\n\t\treturn this.token\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tthis.token = token\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tthis.token = null\n\t}\n}\n\n/**\n * LocalStorage-based token storage (for browser)\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n\tprivate key = 'oauth.do:token'\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\treturn null\n\t\t}\n\t\treturn localStorage.getItem(this.key)\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\tthrow new Error('localStorage is not available')\n\t\t}\n\t\tlocalStorage.setItem(this.key, token)\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\treturn\n\t\t}\n\t\tlocalStorage.removeItem(this.key)\n\t}\n}\n\n/**\n * Composite token storage that tries multiple storage backends\n * Attempts keychain first, then falls back to secure file storage\n */\nexport class CompositeTokenStorage implements TokenStorage {\n\tprivate keychainStorage: KeychainTokenStorage\n\tprivate fileStorage: SecureFileTokenStorage\n\tprivate preferredStorage: TokenStorage | null = null\n\n\tconstructor() {\n\t\tthis.keychainStorage = new KeychainTokenStorage()\n\t\tthis.fileStorage = new SecureFileTokenStorage()\n\t}\n\n\t/**\n\t * Determine the best available storage backend\n\t */\n\tprivate async getPreferredStorage(): Promise<TokenStorage> {\n\t\tif (this.preferredStorage) {\n\t\t\treturn this.preferredStorage\n\t\t}\n\n\t\t// Try keychain first\n\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\tthis.preferredStorage = this.keychainStorage\n\t\t\treturn this.preferredStorage\n\t\t}\n\n\t\t// Fall back to secure file storage\n\t\tthis.preferredStorage = this.fileStorage\n\t\treturn this.preferredStorage\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\t// First, check keychain\n\t\tconst keychainToken = await this.keychainStorage.getToken()\n\t\tif (keychainToken) {\n\t\t\treturn keychainToken\n\t\t}\n\n\t\t// Fall back to file storage (for migration from old installations)\n\t\tconst fileToken = await this.fileStorage.getToken()\n\t\tif (fileToken) {\n\t\t\t// Migrate token to keychain if available\n\t\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.keychainStorage.setToken(fileToken)\n\t\t\t\t\tawait this.fileStorage.removeToken()\n\t\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\t\tconsole.log('Migrated token from file to keychain')\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Continue with file token if migration fails\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fileToken\n\t\t}\n\n\t\treturn null\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tconst storage = await this.getPreferredStorage()\n\t\tawait storage.setToken(token)\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\t// Remove from both storages to ensure complete logout\n\t\tawait Promise.all([this.keychainStorage.removeToken(), this.fileStorage.removeToken()])\n\t}\n\n\t/**\n\t * Get information about the current storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'keychain' | 'file'; secure: boolean }> {\n\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\treturn { type: 'keychain', secure: true }\n\t\t}\n\t\treturn { type: 'file', secure: true }\n\t}\n}\n\n/**\n * Create the default token storage\n * - Node.js: Uses OS keychain when available, falls back to secure file storage\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use keychain/file storage\n\tif (isNode()) {\n\t\treturn new CompositeTokenStorage()\n\t}\n\n\t// Browser - use localStorage\n\tif (typeof localStorage !== 'undefined') {\n\t\treturn new LocalStorageTokenStorage()\n\t}\n\n\t// Workers/other - use memory storage\n\treturn new MemoryTokenStorage()\n}\n","import type { OAuthConfig } from './types.js'\n\n/**\n * Safe environment variable access (works in Node, browser, and Workers)\n */\nfunction getEnv(key: string): string | undefined {\n\t// Check globalThis first (Workers)\n\tif ((globalThis as any)[key]) return (globalThis as any)[key]\n\t// Check process.env (Node.js)\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Global OAuth configuration\n */\nlet globalConfig: Required<OAuthConfig> = {\n\tapiUrl: getEnv('OAUTH_API_URL') || getEnv('API_URL') || 'https://apis.do',\n\tclientId: getEnv('OAUTH_CLIENT_ID') || 'oauth.do',\n\tauthKitDomain: getEnv('OAUTH_AUTHKIT_DOMAIN') || 'login.oauth.do',\n\tfetch: globalThis.fetch,\n}\n\n/**\n * Configure OAuth settings\n */\nexport function configure(config: OAuthConfig): void {\n\tglobalConfig = {\n\t\t...globalConfig,\n\t\t...config,\n\t}\n}\n\n/**\n * Get current configuration\n */\nexport function getConfig(): Required<OAuthConfig> {\n\treturn globalConfig\n}\n","import { getConfig } from './config.js'\nimport type { User, AuthResult } from './types.js'\n\n/**\n * Safe environment variable access (works in Node, browser, and Workers)\n */\nfunction getEnv(key: string): string | undefined {\n\t// Check globalThis first (Workers)\n\tif ((globalThis as any)[key]) return (globalThis as any)[key]\n\t// Check process.env (Node.js)\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Get current authenticated user\n * Calls GET /me endpoint\n *\n * @param token - Optional authentication token (will use DO_TOKEN env var if not provided)\n * @returns Authentication result with user info or null if not authenticated\n */\nexport async function auth(token?: string): Promise<AuthResult> {\n\tconst config = getConfig()\n\tconst authToken = token || getEnv('DO_TOKEN') || ''\n\n\tif (!authToken) {\n\t\treturn { user: null }\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/me`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\t'Authorization': `Bearer ${authToken}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 401) {\n\t\t\t\treturn { user: null }\n\t\t\t}\n\t\t\tthrow new Error(`Authentication failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst user = (await response.json()) as User\n\t\treturn { user, token: authToken }\n\t} catch (error) {\n\t\tconsole.error('Auth error:', error)\n\t\treturn { user: null }\n\t}\n}\n\n/**\n * Initiate login flow\n * Calls POST /login endpoint\n *\n * @param credentials - Login credentials (email, password, etc.)\n * @returns Authentication result with user info and token\n */\nexport async function login(credentials: {\n\temail?: string\n\tpassword?: string\n\t[key: string]: any\n}): Promise<AuthResult> {\n\tconst config = getConfig()\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/login`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t\tbody: JSON.stringify(credentials),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Login failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst data = (await response.json()) as { user: User; token: string }\n\t\treturn { user: data.user, token: data.token }\n\t} catch (error) {\n\t\tconsole.error('Login error:', error)\n\t\tthrow error\n\t}\n}\n\n/**\n * Logout current user\n * Calls POST /logout endpoint\n *\n * @param token - Optional authentication token (will use DO_TOKEN env var if not provided)\n */\nexport async function logout(token?: string): Promise<void> {\n\tconst config = getConfig()\n\tconst authToken = token || getEnv('DO_TOKEN') || ''\n\n\tif (!authToken) {\n\t\treturn\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/logout`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Authorization': `Bearer ${authToken}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconsole.warn(`Logout warning: ${response.statusText}`)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('Logout error:', error)\n\t}\n}\n\n/**\n * Get token from environment or stored credentials\n *\n * Checks in order:\n * 1. process.env.DO_ADMIN_TOKEN\n * 2. process.env.DO_TOKEN\n * 3. Stored token (keychain/secure file)\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers, process.env for Node)\n\tconst adminToken = getEnv('DO_ADMIN_TOKEN')\n\tif (adminToken) return adminToken\n\tconst doToken = getEnv('DO_TOKEN')\n\tif (doToken) return doToken\n\n\t// Try stored token (Node.js only - uses keychain/file storage)\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\treturn await storage.getToken()\n\t} catch {\n\t\t// Storage not available (browser/worker) - return null\n\t\treturn null\n\t}\n}\n\n/**\n * Check if user is authenticated (has valid token)\n */\nexport async function isAuthenticated(token?: string): Promise<boolean> {\n\tconst result = await auth(token)\n\treturn result.user !== null\n}\n\n/**\n * Build OAuth authorization URL\n *\n * @example\n * const url = buildAuthUrl({\n * redirectUri: 'https://myapp.com/callback',\n * scope: 'openid profile email',\n * })\n */\nexport function buildAuthUrl(options: {\n\tredirectUri: string\n\tscope?: string\n\tstate?: string\n\tresponseType?: string\n\tclientId?: string\n\tauthDomain?: string\n}): string {\n\tconst config = getConfig()\n\tconst clientId = options.clientId || config.clientId\n\tconst authDomain = options.authDomain || config.authKitDomain\n\n\tconst params = new URLSearchParams({\n\t\tclient_id: clientId,\n\t\tredirect_uri: options.redirectUri,\n\t\tresponse_type: options.responseType || 'code',\n\t\tscope: options.scope || 'openid profile email',\n\t})\n\n\tif (options.state) {\n\t\tparams.set('state', options.state)\n\t}\n\n\treturn `https://${authDomain}/authorize?${params.toString()}`\n}\n","import { getConfig } from './config.js'\nimport type { DeviceAuthorizationResponse, TokenResponse, TokenError } from './types.js'\n\n/**\n * Initiate device authorization flow\n * Following OAuth 2.0 Device Authorization Grant (RFC 8628)\n *\n * @returns Device authorization response with codes and URIs\n */\nexport async function authorizeDevice(): Promise<DeviceAuthorizationResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for device authorization. Set OAUTH_CLIENT_ID or configure({ clientId: \"...\" })')\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`https://${config.authKitDomain}/device/authorize`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t},\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tclient_id: config.clientId,\n\t\t\t}),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Device authorization failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst data = (await response.json()) as DeviceAuthorizationResponse\n\t\treturn data\n\t} catch (error) {\n\t\tconsole.error('Device authorization error:', error)\n\t\tthrow error\n\t}\n}\n\n/**\n * Poll for tokens after device authorization\n *\n * @param deviceCode - Device code from authorization response\n * @param interval - Polling interval in seconds (default: 5)\n * @param expiresIn - Expiration time in seconds (default: 600)\n * @returns Token response with access token and user info\n */\nexport async function pollForTokens(\n\tdeviceCode: string,\n\tinterval: number = 5,\n\texpiresIn: number = 600\n): Promise<TokenResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for token polling')\n\t}\n\n\tconst startTime = Date.now()\n\tconst timeout = expiresIn * 1000\n\tlet currentInterval = interval * 1000\n\n\twhile (true) {\n\t\t// Check if expired\n\t\tif (Date.now() - startTime > timeout) {\n\t\t\tthrow new Error('Device authorization expired. Please try again.')\n\t\t}\n\n\t\t// Wait for interval\n\t\tawait new Promise((resolve) => setTimeout(resolve, currentInterval))\n\n\t\ttry {\n\t\t\tconst response = await config.fetch(`https://${config.authKitDomain}/device/token`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t\t},\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tgrant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n\t\t\t\t\tdevice_code: deviceCode,\n\t\t\t\t\tclient_id: config.clientId,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst data = (await response.json()) as TokenResponse\n\t\t\t\treturn data\n\t\t\t}\n\n\t\t\t// Handle error responses\n\t\t\tconst errorData = (await response.json().catch(() => ({ error: 'unknown' }))) as { error?: string }\n\t\t\tconst error = (errorData.error || 'unknown') as TokenError\n\n\t\t\tswitch (error) {\n\t\t\t\tcase 'authorization_pending':\n\t\t\t\t\t// Continue polling\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase 'slow_down':\n\t\t\t\t\t// Increase interval by 5 seconds\n\t\t\t\t\tcurrentInterval += 5000\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase 'access_denied':\n\t\t\t\t\tthrow new Error('Access denied by user')\n\n\t\t\t\tcase 'expired_token':\n\t\t\t\t\tthrow new Error('Device code expired')\n\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Token polling failed: ${error}`)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// If it's our thrown error, re-throw it\n\t\t\tif (error instanceof Error) {\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\t// Otherwise continue polling\n\t\t\tcontinue\n\t\t}\n\t}\n}\n","/**\n * API Key management via WorkOS\n *\n * Create, rotate, and delete API keys\n */\n\nimport { getConfig } from './config.js'\n\n/**\n * Safe environment variable access (works in Node, browser, and Workers)\n */\nfunction getEnv(key: string): string | undefined {\n // Check globalThis first (Workers)\n if ((globalThis as any)[key]) return (globalThis as any)[key]\n // Check process.env (Node.js)\n if (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n return undefined\n}\n\nexport interface ApiKey {\n id: string\n key: string\n name: string\n createdAt: string\n expiresAt?: string\n}\n\nexport interface CreateApiKeyOptions {\n name: string\n expiresIn?: string // e.g., '30d', '1y', 'never'\n scopes?: string[]\n}\n\nexport interface RotateApiKeyOptions {\n expiresIn?: string\n}\n\n/**\n * Create a new API key\n */\nexport async function createApiKey(\n options: CreateApiKeyOptions,\n token?: string\n): Promise<ApiKey> {\n const config = getConfig()\n const authToken = token || getEnv('DO_TOKEN')\n\n if (!authToken) {\n throw new Error('Authentication required to create API key')\n }\n\n const response = await config.fetch(`${config.apiUrl}/api-keys`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(options),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to create API key: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * List all API keys for the current user\n */\nexport async function listApiKeys(token?: string): Promise<ApiKey[]> {\n const config = getConfig()\n const authToken = token || getEnv('DO_TOKEN')\n\n if (!authToken) {\n throw new Error('Authentication required to list API keys')\n }\n\n const response = await config.fetch(`${config.apiUrl}/api-keys`, {\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to list API keys: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * Get a specific API key by ID\n */\nexport async function getApiKey(id: string, token?: string): Promise<ApiKey> {\n const config = getConfig()\n const authToken = token || getEnv('DO_TOKEN')\n\n if (!authToken) {\n throw new Error('Authentication required to get API key')\n }\n\n const response = await config.fetch(`${config.apiUrl}/api-keys/${id}`, {\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to get API key: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * Rotate an API key (creates new key, invalidates old)\n */\nexport async function rotateApiKey(\n id: string,\n options?: RotateApiKeyOptions,\n token?: string\n): Promise<ApiKey> {\n const config = getConfig()\n const authToken = token || getEnv('DO_TOKEN')\n\n if (!authToken) {\n throw new Error('Authentication required to rotate API key')\n }\n\n const response = await config.fetch(`${config.apiUrl}/api-keys/${id}/rotate`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(options || {}),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to rotate API key: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * Delete an API key\n */\nexport async function deleteApiKey(id: string, token?: string): Promise<void> {\n const config = getConfig()\n const authToken = token || getEnv('DO_TOKEN')\n\n if (!authToken) {\n throw new Error('Authentication required to delete API key')\n }\n\n const response = await config.fetch(`${config.apiUrl}/api-keys/${id}`, {\n method: 'DELETE',\n headers: {\n 'Authorization': `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to delete API key: ${error}`)\n }\n}\n","/**\n * oauth.do - OAuth authentication SDK and CLI for .do Platform\n *\n * @packageDocumentation\n */\n\nexport { auth, login, logout, getToken, isAuthenticated, buildAuthUrl } from './auth.js'\nexport { configure, getConfig } from './config.js'\nexport { authorizeDevice, pollForTokens } from './device.js'\nexport { createApiKey, listApiKeys, getApiKey, rotateApiKey, deleteApiKey } from './apikey.js'\nexport type { ApiKey, CreateApiKeyOptions, RotateApiKeyOptions } from './apikey.js'\nexport {\n\tFileTokenStorage,\n\tMemoryTokenStorage,\n\tLocalStorageTokenStorage,\n\tSecureFileTokenStorage,\n\tKeychainTokenStorage,\n\tCompositeTokenStorage,\n\tcreateSecureStorage,\n} from './storage.js'\nexport type {\n\tOAuthConfig,\n\tUser,\n\tAuthResult,\n\tDeviceAuthorizationResponse,\n\tTokenResponse,\n\tTokenError,\n\tTokenStorage,\n} from './types.js'\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/storage.ts","../src/config.ts","../src/auth.ts","../src/device.ts","../src/login.ts","../src/index.ts"],"names":["getEnv","createSecureStorage"],"mappings":"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","file":"index.js","sourcesContent":["import type { TokenStorage } from './types.js'\n\n// Keychain service and account identifiers\nconst KEYCHAIN_SERVICE = 'oauth.do'\nconst KEYCHAIN_ACCOUNT = 'access_token'\n\n/**\n * Check if we're running in a Node.js environment\n */\nfunction isNode(): boolean {\n\treturn typeof process !== 'undefined' &&\n\t\tprocess.versions != null &&\n\t\tprocess.versions.node != null\n}\n\n/**\n * Safe environment variable access\n */\nfunction getEnv(key: string): string | undefined {\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Keychain-based token storage using OS credential manager\n * - macOS: Keychain\n * - Windows: Credential Manager\n * - Linux: Secret Service (libsecret)\n *\n * This is the most secure option for CLI token storage.\n */\nexport class KeychainTokenStorage implements TokenStorage {\n\tprivate keytar: typeof import('keytar') | null = null\n\tprivate initialized = false\n\n\t/**\n\t * Lazily load keytar module\n\t * Returns null if keytar is not available (e.g., missing native dependencies)\n\t */\n\tprivate async getKeytar(): Promise<typeof import('keytar') | null> {\n\t\tif (this.initialized) {\n\t\t\treturn this.keytar\n\t\t}\n\n\t\tthis.initialized = true\n\n\t\ttry {\n\t\t\t// Dynamic import to handle cases where keytar native module isn't available\n\t\t\tthis.keytar = await import('keytar')\n\t\t\treturn this.keytar\n\t\t} catch (error) {\n\t\t\t// keytar requires native dependencies that may not be available\n\t\t\t// Fall back gracefully\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain storage not available:', error)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn null\n\t\t}\n\n\t\ttry {\n\t\t\tconst token = await keytar.getPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)\n\t\t\treturn token\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Failed to get token from keychain:', error)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\tthrow new Error('Keychain storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to save token to keychain: ${error}`)\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn\n\t\t}\n\n\t\ttry {\n\t\t\tawait keytar.deletePassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)\n\t\t} catch {\n\t\t\t// Ignore errors if credential doesn't exist\n\t\t}\n\t}\n\n\t/**\n\t * Check if keychain storage is available on this system\n\t */\n\tasync isAvailable(): Promise<boolean> {\n\t\tconst keytar = await this.getKeytar()\n\t\tif (!keytar) {\n\t\t\treturn false\n\t\t}\n\n\t\ttry {\n\t\t\t// Try a read operation to verify keychain access\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n}\n\n/**\n * Secure file-based token storage for CLI\n * Stores token in ~/.oauth.do/token with restricted permissions (0600)\n *\n * This is used as a fallback when keychain storage is not available.\n * Only works in Node.js environment.\n */\nexport class SecureFileTokenStorage implements TokenStorage {\n\tprivate tokenPath: string | null = null\n\tprivate configDir: string | null = null\n\tprivate initialized = false\n\n\tprivate async init(): Promise<boolean> {\n\t\tif (this.initialized) return this.tokenPath !== null\n\t\tthis.initialized = true\n\n\t\tif (!isNode()) return false\n\n\t\ttry {\n\t\t\tconst os = await import('os')\n\t\t\tconst path = await import('path')\n\t\t\tthis.configDir = path.join(os.homedir(), '.oauth.do')\n\t\t\tthis.tokenPath = path.join(this.configDir, 'token')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (!(await this.init()) || !this.tokenPath) return null\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\t// Verify file permissions before reading\n\t\t\tconst stats = await fs.stat(this.tokenPath)\n\t\t\tconst mode = stats.mode & 0o777\n\n\t\t\t// Warn if file has insecure permissions\n\t\t\tif (mode !== 0o600 && getEnv('DEBUG')) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Warning: Token file has insecure permissions (${mode.toString(8)}). ` +\n\t\t\t\t\t\t`Expected 600. Run: chmod 600 ${this.tokenPath}`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst token = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\treturn token.trim()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath || !this.configDir) {\n\t\t\tthrow new Error('File storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\t// Create config directory with restricted permissions\n\t\t\tawait fs.mkdir(this.configDir, { recursive: true, mode: 0o700 })\n\n\t\t\t// Write token file\n\t\t\tawait fs.writeFile(this.tokenPath, token, { encoding: 'utf-8', mode: 0o600 })\n\n\t\t\t// Ensure permissions are correct (writeFile mode may be affected by umask)\n\t\t\tawait fs.chmod(this.tokenPath, 0o600)\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token:', error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath) return\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.unlink(this.tokenPath)\n\t\t} catch {\n\t\t\t// Ignore errors if file doesn't exist\n\t\t}\n\t}\n}\n\n/**\n * File-based token storage for CLI (legacy, less secure)\n * Stores token in ~/.oauth.do/token\n * Only works in Node.js environment.\n *\n * @deprecated Use SecureFileTokenStorage or KeychainTokenStorage instead\n */\nexport class FileTokenStorage implements TokenStorage {\n\tprivate tokenPath: string | null = null\n\tprivate configDir: string | null = null\n\tprivate initialized = false\n\n\tprivate async init(): Promise<boolean> {\n\t\tif (this.initialized) return this.tokenPath !== null\n\t\tthis.initialized = true\n\n\t\tif (!isNode()) return false\n\n\t\ttry {\n\t\t\tconst os = await import('os')\n\t\t\tconst path = await import('path')\n\t\t\tthis.configDir = path.join(os.homedir(), '.oauth.do')\n\t\t\tthis.tokenPath = path.join(this.configDir, 'token')\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (!(await this.init()) || !this.tokenPath) return null\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tconst token = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\treturn token.trim()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath || !this.configDir) {\n\t\t\tthrow new Error('File storage not available')\n\t\t}\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.mkdir(this.configDir, { recursive: true })\n\t\t\tawait fs.writeFile(this.tokenPath, token, 'utf-8')\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token:', error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (!(await this.init()) || !this.tokenPath) return\n\n\t\ttry {\n\t\t\tconst fs = await import('fs/promises')\n\t\t\tawait fs.unlink(this.tokenPath)\n\t\t} catch {\n\t\t\t// Ignore errors if file doesn't exist\n\t\t}\n\t}\n}\n\n/**\n * In-memory token storage (for browser or testing)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n\tprivate token: string | null = null\n\n\tasync getToken(): Promise<string | null> {\n\t\treturn this.token\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tthis.token = token\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tthis.token = null\n\t}\n}\n\n/**\n * LocalStorage-based token storage (for browser)\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n\tprivate key = 'oauth.do:token'\n\n\tasync getToken(): Promise<string | null> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\treturn null\n\t\t}\n\t\treturn localStorage.getItem(this.key)\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\tthrow new Error('localStorage is not available')\n\t\t}\n\t\tlocalStorage.setItem(this.key, token)\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\treturn\n\t\t}\n\t\tlocalStorage.removeItem(this.key)\n\t}\n}\n\n/**\n * Composite token storage that tries multiple storage backends\n * Attempts keychain first, then falls back to secure file storage\n */\nexport class CompositeTokenStorage implements TokenStorage {\n\tprivate keychainStorage: KeychainTokenStorage\n\tprivate fileStorage: SecureFileTokenStorage\n\tprivate preferredStorage: TokenStorage | null = null\n\n\tconstructor() {\n\t\tthis.keychainStorage = new KeychainTokenStorage()\n\t\tthis.fileStorage = new SecureFileTokenStorage()\n\t}\n\n\t/**\n\t * Determine the best available storage backend\n\t */\n\tprivate async getPreferredStorage(): Promise<TokenStorage> {\n\t\tif (this.preferredStorage) {\n\t\t\treturn this.preferredStorage\n\t\t}\n\n\t\t// Try keychain first\n\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\tthis.preferredStorage = this.keychainStorage\n\t\t\treturn this.preferredStorage\n\t\t}\n\n\t\t// Fall back to secure file storage\n\t\tthis.preferredStorage = this.fileStorage\n\t\treturn this.preferredStorage\n\t}\n\n\tasync getToken(): Promise<string | null> {\n\t\t// First, check keychain\n\t\tconst keychainToken = await this.keychainStorage.getToken()\n\t\tif (keychainToken) {\n\t\t\treturn keychainToken\n\t\t}\n\n\t\t// Fall back to file storage (for migration from old installations)\n\t\tconst fileToken = await this.fileStorage.getToken()\n\t\tif (fileToken) {\n\t\t\t// Migrate token to keychain if available\n\t\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.keychainStorage.setToken(fileToken)\n\t\t\t\t\tawait this.fileStorage.removeToken()\n\t\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\t\tconsole.log('Migrated token from file to keychain')\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Continue with file token if migration fails\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fileToken\n\t\t}\n\n\t\treturn null\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\tconst storage = await this.getPreferredStorage()\n\t\tawait storage.setToken(token)\n\t}\n\n\tasync removeToken(): Promise<void> {\n\t\t// Remove from both storages to ensure complete logout\n\t\tawait Promise.all([this.keychainStorage.removeToken(), this.fileStorage.removeToken()])\n\t}\n\n\t/**\n\t * Get information about the current storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'keychain' | 'file'; secure: boolean }> {\n\t\tif (await this.keychainStorage.isAvailable()) {\n\t\t\treturn { type: 'keychain', secure: true }\n\t\t}\n\t\treturn { type: 'file', secure: true }\n\t}\n}\n\n/**\n * Create the default token storage\n * - Node.js: Uses OS keychain when available, falls back to secure file storage\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use keychain/file storage\n\tif (isNode()) {\n\t\treturn new CompositeTokenStorage()\n\t}\n\n\t// Browser - use localStorage\n\tif (typeof localStorage !== 'undefined') {\n\t\treturn new LocalStorageTokenStorage()\n\t}\n\n\t// Workers/other - use memory storage\n\treturn new MemoryTokenStorage()\n}\n","import type { OAuthConfig } from './types.js'\n\n/**\n * Safe environment variable access (works in Node, browser, and Workers)\n */\nfunction getEnv(key: string): string | undefined {\n\t// Check globalThis first (Workers)\n\tif ((globalThis as any)[key]) return (globalThis as any)[key]\n\t// Check process.env (Node.js)\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Global OAuth configuration\n */\nlet globalConfig: Required<OAuthConfig> = {\n\tapiUrl: getEnv('OAUTH_API_URL') || getEnv('API_URL') || 'https://apis.do',\n\tclientId: getEnv('OAUTH_CLIENT_ID') || 'client_01JQYTRXK9ZPD8JPJTKDCRB656',\n\tauthKitDomain: getEnv('OAUTH_AUTHKIT_DOMAIN') || 'login.oauth.do',\n\tfetch: globalThis.fetch,\n}\n\n/**\n * Configure OAuth settings\n */\nexport function configure(config: OAuthConfig): void {\n\tglobalConfig = {\n\t\t...globalConfig,\n\t\t...config,\n\t}\n}\n\n/**\n * Get current configuration\n */\nexport function getConfig(): Required<OAuthConfig> {\n\treturn globalConfig\n}\n","import { getConfig } from './config.js'\nimport type { User, AuthResult } from './types.js'\n\n/**\n * Safe environment variable access (works in Node, browser, and Workers)\n */\nfunction getEnv(key: string): string | undefined {\n\t// Check globalThis first (Workers)\n\tif ((globalThis as any)[key]) return (globalThis as any)[key]\n\t// Check process.env (Node.js)\n\tif (typeof process !== 'undefined' && process.env?.[key]) return process.env[key]\n\treturn undefined\n}\n\n/**\n * Get current authenticated user\n * Calls GET /me endpoint\n *\n * @param token - Optional authentication token (will use DO_TOKEN env var if not provided)\n * @returns Authentication result with user info or null if not authenticated\n */\nexport async function auth(token?: string): Promise<AuthResult> {\n\tconst config = getConfig()\n\tconst authToken = token || getEnv('DO_TOKEN') || ''\n\n\tif (!authToken) {\n\t\treturn { user: null }\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/me`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\t'Authorization': `Bearer ${authToken}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 401) {\n\t\t\t\treturn { user: null }\n\t\t\t}\n\t\t\tthrow new Error(`Authentication failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst user = (await response.json()) as User\n\t\treturn { user, token: authToken }\n\t} catch (error) {\n\t\tconsole.error('Auth error:', error)\n\t\treturn { user: null }\n\t}\n}\n\n/**\n * Initiate login flow\n * Calls POST /login endpoint\n *\n * @param credentials - Login credentials (email, password, etc.)\n * @returns Authentication result with user info and token\n */\nexport async function login(credentials: {\n\temail?: string\n\tpassword?: string\n\t[key: string]: any\n}): Promise<AuthResult> {\n\tconst config = getConfig()\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/login`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t\tbody: JSON.stringify(credentials),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Login failed: ${response.statusText}`)\n\t\t}\n\n\t\tconst data = (await response.json()) as { user: User; token: string }\n\t\treturn { user: data.user, token: data.token }\n\t} catch (error) {\n\t\tconsole.error('Login error:', error)\n\t\tthrow error\n\t}\n}\n\n/**\n * Logout current user\n * Calls POST /logout endpoint\n *\n * @param token - Optional authentication token (will use DO_TOKEN env var if not provided)\n */\nexport async function logout(token?: string): Promise<void> {\n\tconst config = getConfig()\n\tconst authToken = token || getEnv('DO_TOKEN') || ''\n\n\tif (!authToken) {\n\t\treturn\n\t}\n\n\ttry {\n\t\tconst response = await config.fetch(`${config.apiUrl}/logout`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Authorization': `Bearer ${authToken}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconsole.warn(`Logout warning: ${response.statusText}`)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('Logout error:', error)\n\t}\n}\n\n/**\n * Get token from environment or stored credentials\n *\n * Checks in order:\n * 1. process.env.DO_ADMIN_TOKEN\n * 2. process.env.DO_TOKEN\n * 3. Stored token (keychain/secure file)\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers, process.env for Node)\n\tconst adminToken = getEnv('DO_ADMIN_TOKEN')\n\tif (adminToken) return adminToken\n\tconst doToken = getEnv('DO_TOKEN')\n\tif (doToken) return doToken\n\n\t// Try stored token (Node.js only - uses keychain/file storage)\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\treturn await storage.getToken()\n\t} catch {\n\t\t// Storage not available (browser/worker) - return null\n\t\treturn null\n\t}\n}\n\n/**\n * Check if user is authenticated (has valid token)\n */\nexport async function isAuthenticated(token?: string): Promise<boolean> {\n\tconst result = await auth(token)\n\treturn result.user !== null\n}\n\n/**\n * Build OAuth authorization URL\n *\n * @example\n * const url = buildAuthUrl({\n * redirectUri: 'https://myapp.com/callback',\n * scope: 'openid profile email',\n * })\n */\nexport function buildAuthUrl(options: {\n\tredirectUri: string\n\tscope?: string\n\tstate?: string\n\tresponseType?: string\n\tclientId?: string\n\tauthDomain?: string\n}): string {\n\tconst config = getConfig()\n\tconst clientId = options.clientId || config.clientId\n\tconst authDomain = options.authDomain || config.authKitDomain\n\n\tconst params = new URLSearchParams({\n\t\tclient_id: clientId,\n\t\tredirect_uri: options.redirectUri,\n\t\tresponse_type: options.responseType || 'code',\n\t\tscope: options.scope || 'openid profile email',\n\t})\n\n\tif (options.state) {\n\t\tparams.set('state', options.state)\n\t}\n\n\treturn `https://${authDomain}/authorize?${params.toString()}`\n}\n","import { getConfig } from './config.js'\nimport type { DeviceAuthorizationResponse, TokenResponse, TokenError } from './types.js'\n\n/**\n * Initiate device authorization flow\n * Following OAuth 2.0 Device Authorization Grant (RFC 8628)\n *\n * @returns Device authorization response with codes and URIs\n */\nexport async function authorizeDevice(): Promise<DeviceAuthorizationResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for device authorization. Set OAUTH_CLIENT_ID or configure({ clientId: \"...\" })')\n\t}\n\n\ttry {\n\t\tconst url = 'https://auth.apis.do/user_management/authorize/device'\n\t\tconst body = new URLSearchParams({ client_id: config.clientId })\n\n\t\tconst response = await config.fetch(url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t},\n\t\t\tbody,\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text()\n\t\t\tthrow new Error(`Device authorization failed: ${response.statusText} - ${errorText}`)\n\t\t}\n\n\t\tconst data = (await response.json()) as DeviceAuthorizationResponse\n\t\treturn data\n\t} catch (error) {\n\t\tconsole.error('Device authorization error:', error)\n\t\tthrow error\n\t}\n}\n\n/**\n * Poll for tokens after device authorization\n *\n * @param deviceCode - Device code from authorization response\n * @param interval - Polling interval in seconds (default: 5)\n * @param expiresIn - Expiration time in seconds (default: 600)\n * @returns Token response with access token and user info\n */\nexport async function pollForTokens(\n\tdeviceCode: string,\n\tinterval: number = 5,\n\texpiresIn: number = 600\n): Promise<TokenResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for token polling')\n\t}\n\n\tconst startTime = Date.now()\n\tconst timeout = expiresIn * 1000\n\tlet currentInterval = interval * 1000\n\n\twhile (true) {\n\t\t// Check if expired\n\t\tif (Date.now() - startTime > timeout) {\n\t\t\tthrow new Error('Device authorization expired. Please try again.')\n\t\t}\n\n\t\t// Wait for interval\n\t\tawait new Promise((resolve) => setTimeout(resolve, currentInterval))\n\n\t\ttry {\n\t\t\tconst response = await config.fetch('https://auth.apis.do/user_management/authenticate', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t\t},\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tgrant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n\t\t\t\t\tdevice_code: deviceCode,\n\t\t\t\t\tclient_id: config.clientId,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst data = (await response.json()) as TokenResponse\n\t\t\t\treturn data\n\t\t\t}\n\n\t\t\t// Handle error responses\n\t\t\tconst errorData = (await response.json().catch(() => ({ error: 'unknown' }))) as { error?: string }\n\t\t\tconst error = (errorData.error || 'unknown') as TokenError\n\n\t\t\tswitch (error) {\n\t\t\t\tcase 'authorization_pending':\n\t\t\t\t\t// Continue polling\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase 'slow_down':\n\t\t\t\t\t// Increase interval by 5 seconds\n\t\t\t\t\tcurrentInterval += 5000\n\t\t\t\t\tcontinue\n\n\t\t\t\tcase 'access_denied':\n\t\t\t\t\tthrow new Error('Access denied by user')\n\n\t\t\t\tcase 'expired_token':\n\t\t\t\t\tthrow new Error('Device code expired')\n\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Token polling failed: ${error}`)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// If it's our thrown error, re-throw it\n\t\t\tif (error instanceof Error) {\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\t// Otherwise continue polling\n\t\t\tcontinue\n\t\t}\n\t}\n}\n","/**\n * CLI-centric login utilities\n * Handles device flow with browser auto-launch for CLI apps\n */\n\nimport { authorizeDevice, pollForTokens } from './device.js'\nimport { createSecureStorage } from './storage.js'\n\nexport interface LoginOptions {\n\t/** Open browser automatically (default: true) */\n\topenBrowser?: boolean\n\t/** Custom print function for output */\n\tprint?: (message: string) => void\n\t/** Storage to use (default: createSecureStorage()) */\n\tstorage?: {\n\t\tgetToken: () => Promise<string | null>\n\t\tsetToken: (token: string) => Promise<void>\n\t\tremoveToken: () => Promise<void>\n\t}\n}\n\nexport interface LoginResult {\n\ttoken: string\n\tisNewLogin: boolean\n}\n\n/**\n * Get existing token or perform device flow login\n * Handles browser launch and token storage automatically\n */\nexport async function ensureLoggedIn(options: LoginOptions = {}): Promise<LoginResult> {\n\tconst { openBrowser = true, print = console.log, storage = createSecureStorage() } = options\n\n\t// Check for existing token\n\tconst existingToken = await storage.getToken()\n\tif (existingToken) {\n\t\treturn { token: existingToken, isNewLogin: false }\n\t}\n\n\t// No token, start device flow\n\tprint('\\nLogging in...\\n')\n\n\tconst authResponse = await authorizeDevice()\n\n\tprint(`To complete login:`)\n\tprint(` 1. Visit: ${authResponse.verification_uri}`)\n\tprint(` 2. Enter code: ${authResponse.user_code}`)\n\tprint(`\\n Or open: ${authResponse.verification_uri_complete}\\n`)\n\n\t// Auto-launch browser\n\tif (openBrowser) {\n\t\ttry {\n\t\t\t// @ts-expect-error - dynamic import of optional 'open' module\n\t\t\tconst open = await import('open')\n\t\t\tawait open.default(authResponse.verification_uri_complete)\n\t\t\tprint('Browser opened automatically\\n')\n\t\t} catch {\n\t\t\t// Silently fail if can't open browser\n\t\t}\n\t}\n\n\tprint('Waiting for authorization...\\n')\n\n\tconst tokenResponse = await pollForTokens(\n\t\tauthResponse.device_code,\n\t\tauthResponse.interval,\n\t\tauthResponse.expires_in\n\t)\n\n\tawait storage.setToken(tokenResponse.access_token)\n\tprint('Login successful!\\n')\n\n\treturn { token: tokenResponse.access_token, isNewLogin: true }\n}\n\n/**\n * Force a new login (ignores existing token)\n */\nexport async function forceLogin(options: LoginOptions = {}): Promise<LoginResult> {\n\tconst { storage = createSecureStorage() } = options\n\tawait storage.removeToken()\n\treturn ensureLoggedIn(options)\n}\n\n/**\n * Logout and remove stored token\n */\nexport async function ensureLoggedOut(options: LoginOptions = {}): Promise<void> {\n\tconst { print = console.log, storage = createSecureStorage() } = options\n\tawait storage.removeToken()\n\tprint('Logged out successfully\\n')\n}\n","/**\n * oauth.do - OAuth authentication SDK and CLI for .do Platform\n *\n * @packageDocumentation\n */\n\nexport { auth, login, logout, getToken, isAuthenticated, buildAuthUrl } from './auth.js'\nexport { configure, getConfig } from './config.js'\nexport { authorizeDevice, pollForTokens } from './device.js'\nexport { ensureLoggedIn, forceLogin, ensureLoggedOut } from './login.js'\nexport type { LoginOptions, LoginResult } from './login.js'\nexport {\n\tFileTokenStorage,\n\tMemoryTokenStorage,\n\tLocalStorageTokenStorage,\n\tSecureFileTokenStorage,\n\tKeychainTokenStorage,\n\tCompositeTokenStorage,\n\tcreateSecureStorage,\n} from './storage.js'\nexport type {\n\tOAuthConfig,\n\tUser,\n\tAuthResult,\n\tDeviceAuthorizationResponse,\n\tTokenResponse,\n\tTokenError,\n\tTokenStorage,\n} from './types.js'\n"]}
|