oauth.do 0.1.10 → 0.1.12
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/dist/cli.js +33 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -0
- package/dist/index.js +30 -4
- package/dist/index.js.map +1 -1
- package/dist/node.js +114 -7
- package/dist/node.js.map +1 -1
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -172,6 +172,10 @@ var init_storage = __esm({
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
async getToken() {
|
|
175
|
+
const data = await this.getTokenData();
|
|
176
|
+
if (data) {
|
|
177
|
+
return data.accessToken;
|
|
178
|
+
}
|
|
175
179
|
if (!await this.init() || !this.tokenPath) return null;
|
|
176
180
|
try {
|
|
177
181
|
const fs = await import('fs/promises');
|
|
@@ -182,23 +186,45 @@ var init_storage = __esm({
|
|
|
182
186
|
`Warning: Token file has insecure permissions (${mode.toString(8)}). Expected 600. Run: chmod 600 ${this.tokenPath}`
|
|
183
187
|
);
|
|
184
188
|
}
|
|
185
|
-
const
|
|
186
|
-
|
|
189
|
+
const content = await fs.readFile(this.tokenPath, "utf-8");
|
|
190
|
+
const trimmed = content.trim();
|
|
191
|
+
if (trimmed.startsWith("{")) {
|
|
192
|
+
const data2 = JSON.parse(trimmed);
|
|
193
|
+
return data2.accessToken;
|
|
194
|
+
}
|
|
195
|
+
return trimmed;
|
|
187
196
|
} catch {
|
|
188
197
|
return null;
|
|
189
198
|
}
|
|
190
199
|
}
|
|
191
200
|
async setToken(token) {
|
|
201
|
+
await this.setTokenData({ accessToken: token.trim() });
|
|
202
|
+
}
|
|
203
|
+
async getTokenData() {
|
|
204
|
+
if (!await this.init() || !this.tokenPath) return null;
|
|
205
|
+
try {
|
|
206
|
+
const fs = await import('fs/promises');
|
|
207
|
+
const content = await fs.readFile(this.tokenPath, "utf-8");
|
|
208
|
+
const trimmed = content.trim();
|
|
209
|
+
if (trimmed.startsWith("{")) {
|
|
210
|
+
return JSON.parse(trimmed);
|
|
211
|
+
}
|
|
212
|
+
return { accessToken: trimmed };
|
|
213
|
+
} catch {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async setTokenData(data) {
|
|
192
218
|
if (!await this.init() || !this.tokenPath || !this.configDir) {
|
|
193
219
|
throw new Error("File storage not available");
|
|
194
220
|
}
|
|
195
221
|
try {
|
|
196
222
|
const fs = await import('fs/promises');
|
|
197
223
|
await fs.mkdir(this.configDir, { recursive: true, mode: 448 });
|
|
198
|
-
await fs.writeFile(this.tokenPath,
|
|
224
|
+
await fs.writeFile(this.tokenPath, JSON.stringify(data), { encoding: "utf-8", mode: 384 });
|
|
199
225
|
await fs.chmod(this.tokenPath, 384);
|
|
200
226
|
} catch (error) {
|
|
201
|
-
console.error("Failed to save token:", error);
|
|
227
|
+
console.error("Failed to save token data:", error);
|
|
202
228
|
throw error;
|
|
203
229
|
}
|
|
204
230
|
}
|
|
@@ -369,7 +395,7 @@ var require_package = __commonJS({
|
|
|
369
395
|
"package.json"(exports$1, module) {
|
|
370
396
|
module.exports = {
|
|
371
397
|
name: "oauth.do",
|
|
372
|
-
version: "0.1.
|
|
398
|
+
version: "0.1.12",
|
|
373
399
|
description: "OAuth authentication SDK and CLI for .do Platform",
|
|
374
400
|
type: "module",
|
|
375
401
|
main: "./dist/index.js",
|
|
@@ -399,7 +425,8 @@ var require_package = __commonJS({
|
|
|
399
425
|
dev: "tsup --watch",
|
|
400
426
|
test: "vitest run",
|
|
401
427
|
"test:watch": "vitest",
|
|
402
|
-
|
|
428
|
+
"check:publish": `node -e "const pkg = require('./package.json'); const deps = JSON.stringify(pkg.dependencies || {}); if (deps.includes('workspace:')) { console.error('ERROR: workspace: protocol found in dependencies. Replace with actual versions before publishing.'); process.exit(1); }"`,
|
|
429
|
+
prepublishOnly: "pnpm check:publish && pnpm build && pnpm test"
|
|
403
430
|
},
|
|
404
431
|
keywords: [
|
|
405
432
|
"oauth",
|
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","createSecureStorage"],"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\tconst imported = await import('keytar')\n\t\t\t// Handle ESM/CJS interop - keytar is CommonJS, so functions may be on .default\n\t\t\tconst keytarModule = (imported as any).default || imported\n\t\t\tthis.keytar = keytarModule as typeof import('keytar')\n\n\t\t\t// Verify the module loaded correctly by checking for expected function\n\t\t\tif (typeof this.keytar.getPassword !== 'function') {\n\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\tconsole.warn('Keytar module loaded but getPassword is not a function:', Object.keys(this.keytar))\n\t\t\t\t}\n\t\t\t\tthis.keytar = null\n\t\t\t\treturn null\n\t\t\t}\n\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\tthrow new Error('Keychain storage not available')\n\t\t\t}\n\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error: any) {\n\t\t\t// Check if this is a native module error vs an actual keychain error\n\t\t\tif (error?.code === 'MODULE_NOT_FOUND' || error?.message?.includes('Cannot find module')) {\n\t\t\t\tthrow new Error('Keychain storage not available: native module not built')\n\t\t\t}\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Try a read operation to verify keychain access\n\t\t\t// This will throw if native module is not built\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain not available:', error)\n\t\t\t}\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 the default storage for Node.js CLI because it doesn't require\n * GUI authorization popups like the keychain does on macOS.\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\t/**\n\t * Get information about the storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'file'; secure: boolean; path: string | null }> {\n\t\tawait this.init()\n\t\treturn { type: 'file', secure: true, path: this.tokenPath }\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 secure file storage (~/.oauth.do/token with 0600 permissions)\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n *\n * Note: We use file storage by default because keychain storage on macOS\n * requires GUI authorization popups, which breaks automation and agent workflows.\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use secure file storage (no keychain popups)\n\tif (isNode()) {\n\t\treturn new SecureFileTokenStorage()\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.10\",\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\"./node\": {\n\t\t\t\"types\": \"./dist/node.d.ts\",\n\t\t\t\"import\": \"./dist/node.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\"open\": \"^10.1.0\"\n\t},\n\t\"optionalDependencies\": {\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({\n\t\t\tclient_id: config.clientId,\n\t\t\tscope: 'openid profile email',\n\t\t})\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 * Resolve a secret that could be a plain string or a secrets store binding\n * Secrets store bindings have a .get() method that returns a Promise<string>\n * @see https://developers.cloudflare.com/workers/configuration/secrets/#secrets-store\n */\nasync function resolveSecret(value: unknown): Promise<string | null> {\n\tif (!value) return null\n\tif (typeof value === 'string') return value\n\tif (typeof value === 'object' && typeof (value as any).get === 'function') {\n\t\treturn await (value as any).get()\n\t}\n\treturn null\n}\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 getUser(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. globalThis.DO_ADMIN_TOKEN / DO_TOKEN (Workers legacy)\n * 2. process.env.DO_ADMIN_TOKEN / DO_TOKEN (Node.js)\n * 3. cloudflare:workers env import (Workers 2025+) - supports secrets store bindings\n * 4. Stored token (keychain/secure file)\n *\n * @see https://developers.cloudflare.com/changelog/2025-03-17-importable-env/\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers legacy, 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 cloudflare:workers env import (Workers 2025+)\n\t// Supports both plain strings and secrets store bindings\n\ttry {\n\t\t// @ts-ignore - cloudflare:workers only available in Workers runtime\n\t\tconst { env } = await import('cloudflare:workers')\n\n\t\tconst cfAdminToken = await resolveSecret((env as any).DO_ADMIN_TOKEN)\n\t\tif (cfAdminToken) return cfAdminToken\n\n\t\tconst cfToken = await resolveSecret((env as any).DO_TOKEN)\n\t\tif (cfToken) return cfToken\n\t} catch {\n\t\t// Not in Workers environment or env not available\n\t}\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 getUser(token)\n\treturn result.user !== null\n}\n\n/**\n * Auth provider function type for HTTP clients\n */\nexport type AuthProvider = () => string | null | undefined | Promise<string | null | undefined>\n\n/**\n * Create an auth provider function for HTTP clients (apis.do, rpc.do)\n * Returns a function that resolves to a token string\n *\n * @example\n * import { auth } from 'oauth.do'\n * const getAuth = auth()\n * const token = await getAuth()\n */\nexport function auth(): AuthProvider {\n\treturn getToken\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, SecureFileTokenStorage } 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// Auto-open browser (no prompt - better for automation/agents)\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\tprintSuccess('Opened browser for authentication')\n\t\t\t} catch {\n\t\t\t\tprintInfo(`Could not open browser. Please visit the URL above manually.`)\n\t\t\t}\n\t\t} else {\n\t\t\tprintInfo(`Could not open browser. Please visit the URL above manually.`)\n\t\t}\n\n\t\t// Step 3: Poll for tokens\n\t\tconsole.log(`\\n${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 fileStorage = storage as SecureFileTokenStorage\n\t\tif (typeof fileStorage.getStorageInfo === 'function') {\n\t\t\tconst storageInfo = await fileStorage.getStorageInfo()\n\t\t\tconsole.log(`\\n${colors.dim}Token stored in: ${colors.green}~/.oauth.do/token${colors.reset}${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 fileStorage = storage as SecureFileTokenStorage\n\t\tif (typeof fileStorage.getStorageInfo === 'function') {\n\t\t\tconst storageInfo = await fileStorage.getStorageInfo()\n\t\t\tconsole.log(`${colors.cyan}Storage:${colors.reset} ${colors.green}Secure File${colors.reset}`)\n\t\t\tconsole.log(` ${colors.dim}Using ~/.oauth.do/token with 0600 permissions${colors.reset}`)\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 * Auto login or show current user\n * If already logged in with valid token, show user info\n * If not logged in or token expired, start login flow\n */\nasync function autoLoginOrShowUser() {\n\ttry {\n\t\t// Check if we have a stored token\n\t\tconst token = await storage.getToken()\n\n\t\tif (token) {\n\t\t\t// Verify the token is still valid\n\t\t\tconst authResult = await auth(token)\n\n\t\t\tif (authResult.user) {\n\t\t\t\t// Already logged in - show user info\n\t\t\t\tconsole.log(`${colors.green}✓${colors.reset} Already authenticated\\n`)\n\t\t\t\tif (authResult.user.name) {\n\t\t\t\t\tconsole.log(` ${colors.bright}${authResult.user.name}${colors.reset}`)\n\t\t\t\t}\n\t\t\t\tif (authResult.user.email) {\n\t\t\t\t\tconsole.log(` ${colors.gray}${authResult.user.email}${colors.reset}`)\n\t\t\t\t}\n\t\t\t\tif (authResult.user.id) {\n\t\t\t\t\tconsole.log(` ${colors.dim}ID: ${authResult.user.id}${colors.reset}`)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Token exists but is invalid/expired - continue to login\n\t\t\tprintInfo('Session expired, logging in again...\\n')\n\t\t}\n\n\t\t// Not logged in - start login flow\n\t\tawait loginCommand()\n\t} catch (error) {\n\t\t// If auth check fails, try to login\n\t\tawait loginCommand()\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\t\tawait loginCommand()\n\t\t\tbreak\n\n\t\tcase undefined:\n\t\t\t// Default: check if logged in, login if not\n\t\t\tawait autoLoginOrShowUser()\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","data","storage","exports","createSecureStorage"],"mappings":"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","file":"cli.js","sourcesContent":["import type { TokenStorage, StoredTokenData } 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\tconst imported = await import('keytar')\n\t\t\t// Handle ESM/CJS interop - keytar is CommonJS, so functions may be on .default\n\t\t\tconst keytarModule = (imported as any).default || imported\n\t\t\tthis.keytar = keytarModule as typeof import('keytar')\n\n\t\t\t// Verify the module loaded correctly by checking for expected function\n\t\t\tif (typeof this.keytar.getPassword !== 'function') {\n\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\tconsole.warn('Keytar module loaded but getPassword is not a function:', Object.keys(this.keytar))\n\t\t\t\t}\n\t\t\t\tthis.keytar = null\n\t\t\t\treturn null\n\t\t\t}\n\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\tthrow new Error('Keychain storage not available')\n\t\t\t}\n\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error: any) {\n\t\t\t// Check if this is a native module error vs an actual keychain error\n\t\t\tif (error?.code === 'MODULE_NOT_FOUND' || error?.message?.includes('Cannot find module')) {\n\t\t\t\tthrow new Error('Keychain storage not available: native module not built')\n\t\t\t}\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Try a read operation to verify keychain access\n\t\t\t// This will throw if native module is not built\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain not available:', error)\n\t\t\t}\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 the default storage for Node.js CLI because it doesn't require\n * GUI authorization popups like the keychain does on macOS.\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\t// Try to get from token data first (new format)\n\t\tconst data = await this.getTokenData()\n\t\tif (data) {\n\t\t\treturn data.accessToken\n\t\t}\n\n\t\t// Fall back to legacy plain text format\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 stats = await fs.stat(this.tokenPath)\n\t\t\tconst mode = stats.mode & 0o777\n\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 content = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\tconst trimmed = content.trim()\n\n\t\t\t// Check if it's JSON (new format) or plain token (legacy)\n\t\t\tif (trimmed.startsWith('{')) {\n\t\t\t\tconst data = JSON.parse(trimmed) as StoredTokenData\n\t\t\t\treturn data.accessToken\n\t\t\t}\n\n\t\t\treturn trimmed\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\t// Store as token data for consistency, trimming whitespace\n\t\tawait this.setTokenData({ accessToken: token.trim() })\n\t}\n\n\tasync getTokenData(): Promise<StoredTokenData | 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 content = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\tconst trimmed = content.trim()\n\n\t\t\t// Check if it's JSON format\n\t\t\tif (trimmed.startsWith('{')) {\n\t\t\t\treturn JSON.parse(trimmed) as StoredTokenData\n\t\t\t}\n\n\t\t\t// Legacy plain text format - convert to token data\n\t\t\treturn { accessToken: trimmed }\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setTokenData(data: StoredTokenData): 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, mode: 0o700 })\n\t\t\tawait fs.writeFile(this.tokenPath, JSON.stringify(data), { encoding: 'utf-8', mode: 0o600 })\n\t\t\tawait fs.chmod(this.tokenPath, 0o600)\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token data:', 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\t/**\n\t * Get information about the storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'file'; secure: boolean; path: string | null }> {\n\t\tawait this.init()\n\t\treturn { type: 'file', secure: true, path: this.tokenPath }\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 secure file storage (~/.oauth.do/token with 0600 permissions)\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n *\n * Note: We use file storage by default because keychain storage on macOS\n * requires GUI authorization popups, which breaks automation and agent workflows.\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use secure file storage (no keychain popups)\n\tif (isNode()) {\n\t\treturn new SecureFileTokenStorage()\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.12\",\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\"./node\": {\n\t\t\t\"types\": \"./dist/node.d.ts\",\n\t\t\t\"import\": \"./dist/node.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\"check:publish\": \"node -e \\\"const pkg = require('./package.json'); const deps = JSON.stringify(pkg.dependencies || {}); if (deps.includes('workspace:')) { console.error('ERROR: workspace: protocol found in dependencies. Replace with actual versions before publishing.'); process.exit(1); }\\\"\",\n\t\t\"prepublishOnly\": \"pnpm check:publish && 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\"open\": \"^10.1.0\"\n\t},\n\t\"optionalDependencies\": {\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({\n\t\t\tclient_id: config.clientId,\n\t\t\tscope: 'openid profile email',\n\t\t})\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, TokenResponse, StoredTokenData } from './types.js'\n\n/**\n * Resolve a secret that could be a plain string or a secrets store binding\n * Secrets store bindings have a .get() method that returns a Promise<string>\n * @see https://developers.cloudflare.com/workers/configuration/secrets/#secrets-store\n */\nasync function resolveSecret(value: unknown): Promise<string | null> {\n\tif (!value) return null\n\tif (typeof value === 'string') return value\n\tif (typeof value === 'object' && typeof (value as any).get === 'function') {\n\t\treturn await (value as any).get()\n\t}\n\treturn null\n}\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 getUser(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. globalThis.DO_ADMIN_TOKEN / DO_TOKEN (Workers legacy)\n * 2. process.env.DO_ADMIN_TOKEN / DO_TOKEN (Node.js)\n * 3. cloudflare:workers env import (Workers 2025+) - supports secrets store bindings\n * 4. Stored token (keychain/secure file)\n *\n * @see https://developers.cloudflare.com/changelog/2025-03-17-importable-env/\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers legacy, 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 cloudflare:workers env import (Workers 2025+)\n\t// Supports both plain strings and secrets store bindings\n\ttry {\n\t\t// @ts-ignore - cloudflare:workers only available in Workers runtime\n\t\tconst { env } = await import('cloudflare:workers')\n\n\t\tconst cfAdminToken = await resolveSecret((env as any).DO_ADMIN_TOKEN)\n\t\tif (cfAdminToken) return cfAdminToken\n\n\t\tconst cfToken = await resolveSecret((env as any).DO_TOKEN)\n\t\tif (cfToken) return cfToken\n\t} catch {\n\t\t// Not in Workers environment or env not available\n\t}\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 getUser(token)\n\treturn result.user !== null\n}\n\n/**\n * Auth provider function type for HTTP clients\n */\nexport type AuthProvider = () => string | null | undefined | Promise<string | null | undefined>\n\n/**\n * Create an auth provider function for HTTP clients (apis.do, rpc.do)\n * Returns a function that resolves to a token string\n *\n * @example\n * import { auth } from 'oauth.do'\n * const getAuth = auth()\n * const token = await getAuth()\n */\nexport function auth(): AuthProvider {\n\treturn getToken\n}\n\n/**\n * Refresh an access token using a refresh token\n *\n * @param refreshToken - The refresh token from the original auth response\n * @returns New token response with fresh access_token (and possibly new refresh_token)\n */\nexport async function refreshAccessToken(refreshToken: string): Promise<TokenResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for token refresh')\n\t}\n\n\tconst response = await config.fetch('https://auth.apis.do/user_management/authenticate', {\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t},\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: 'refresh_token',\n\t\t\trefresh_token: refreshToken,\n\t\t\tclient_id: config.clientId,\n\t\t}),\n\t})\n\n\tif (!response.ok) {\n\t\tconst errorText = await response.text()\n\t\tthrow new Error(`Token refresh failed: ${response.status} - ${errorText}`)\n\t}\n\n\treturn (await response.json()) as TokenResponse\n}\n\n/**\n * Get stored token data from storage\n */\nexport async function getStoredTokenData(): Promise<StoredTokenData | null> {\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\tif (storage.getTokenData) {\n\t\t\treturn await storage.getTokenData()\n\t\t}\n\t\t// Fall back to just access token\n\t\tconst token = await storage.getToken()\n\t\treturn token ? { accessToken: token } : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Store token data including refresh token\n */\nexport async function storeTokenData(data: StoredTokenData): Promise<void> {\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\tif (storage.setTokenData) {\n\t\t\tawait storage.setTokenData(data)\n\t\t} else {\n\t\t\tawait storage.setToken(data.accessToken)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('Failed to store token data:', error)\n\t\tthrow error\n\t}\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, SecureFileTokenStorage } 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// Auto-open browser (no prompt - better for automation/agents)\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\tprintSuccess('Opened browser for authentication')\n\t\t\t} catch {\n\t\t\t\tprintInfo(`Could not open browser. Please visit the URL above manually.`)\n\t\t\t}\n\t\t} else {\n\t\t\tprintInfo(`Could not open browser. Please visit the URL above manually.`)\n\t\t}\n\n\t\t// Step 3: Poll for tokens\n\t\tconsole.log(`\\n${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 fileStorage = storage as SecureFileTokenStorage\n\t\tif (typeof fileStorage.getStorageInfo === 'function') {\n\t\t\tconst storageInfo = await fileStorage.getStorageInfo()\n\t\t\tconsole.log(`\\n${colors.dim}Token stored in: ${colors.green}~/.oauth.do/token${colors.reset}${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 fileStorage = storage as SecureFileTokenStorage\n\t\tif (typeof fileStorage.getStorageInfo === 'function') {\n\t\t\tconst storageInfo = await fileStorage.getStorageInfo()\n\t\t\tconsole.log(`${colors.cyan}Storage:${colors.reset} ${colors.green}Secure File${colors.reset}`)\n\t\t\tconsole.log(` ${colors.dim}Using ~/.oauth.do/token with 0600 permissions${colors.reset}`)\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 * Auto login or show current user\n * If already logged in with valid token, show user info\n * If not logged in or token expired, start login flow\n */\nasync function autoLoginOrShowUser() {\n\ttry {\n\t\t// Check if we have a stored token\n\t\tconst token = await storage.getToken()\n\n\t\tif (token) {\n\t\t\t// Verify the token is still valid\n\t\t\tconst authResult = await auth(token)\n\n\t\t\tif (authResult.user) {\n\t\t\t\t// Already logged in - show user info\n\t\t\t\tconsole.log(`${colors.green}✓${colors.reset} Already authenticated\\n`)\n\t\t\t\tif (authResult.user.name) {\n\t\t\t\t\tconsole.log(` ${colors.bright}${authResult.user.name}${colors.reset}`)\n\t\t\t\t}\n\t\t\t\tif (authResult.user.email) {\n\t\t\t\t\tconsole.log(` ${colors.gray}${authResult.user.email}${colors.reset}`)\n\t\t\t\t}\n\t\t\t\tif (authResult.user.id) {\n\t\t\t\t\tconsole.log(` ${colors.dim}ID: ${authResult.user.id}${colors.reset}`)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Token exists but is invalid/expired - continue to login\n\t\t\tprintInfo('Session expired, logging in again...\\n')\n\t\t}\n\n\t\t// Not logged in - start login flow\n\t\tawait loginCommand()\n\t} catch (error) {\n\t\t// If auth check fails, try to login\n\t\tawait loginCommand()\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\t\tawait loginCommand()\n\t\t\tbreak\n\n\t\tcase undefined:\n\t\t\t// Default: check if logged in, login if not\n\t\t\tawait autoLoginOrShowUser()\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
|
@@ -62,6 +62,14 @@ interface TokenResponse {
|
|
|
62
62
|
* Token polling error types
|
|
63
63
|
*/
|
|
64
64
|
type TokenError = 'authorization_pending' | 'slow_down' | 'access_denied' | 'expired_token' | 'unknown';
|
|
65
|
+
/**
|
|
66
|
+
* Stored token data including refresh token and expiration
|
|
67
|
+
*/
|
|
68
|
+
interface StoredTokenData {
|
|
69
|
+
accessToken: string;
|
|
70
|
+
refreshToken?: string;
|
|
71
|
+
expiresAt?: number;
|
|
72
|
+
}
|
|
65
73
|
/**
|
|
66
74
|
* Token storage interface
|
|
67
75
|
*/
|
|
@@ -69,6 +77,8 @@ interface TokenStorage {
|
|
|
69
77
|
getToken(): Promise<string | null>;
|
|
70
78
|
setToken(token: string): Promise<void>;
|
|
71
79
|
removeToken(): Promise<void>;
|
|
80
|
+
getTokenData?(): Promise<StoredTokenData | null>;
|
|
81
|
+
setTokenData?(data: StoredTokenData): Promise<void>;
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
/**
|
|
@@ -211,6 +221,8 @@ declare class SecureFileTokenStorage implements TokenStorage {
|
|
|
211
221
|
private init;
|
|
212
222
|
getToken(): Promise<string | null>;
|
|
213
223
|
setToken(token: string): Promise<void>;
|
|
224
|
+
getTokenData(): Promise<StoredTokenData | null>;
|
|
225
|
+
setTokenData(data: StoredTokenData): Promise<void>;
|
|
214
226
|
removeToken(): Promise<void>;
|
|
215
227
|
/**
|
|
216
228
|
* Get information about the storage backend
|
|
@@ -294,6 +306,7 @@ declare function createSecureStorage(): TokenStorage;
|
|
|
294
306
|
* CLI-centric login utilities
|
|
295
307
|
* Handles device flow with browser auto-launch for CLI apps
|
|
296
308
|
*/
|
|
309
|
+
|
|
297
310
|
interface LoginOptions {
|
|
298
311
|
/** Open browser automatically (default: true) */
|
|
299
312
|
openBrowser?: boolean;
|
|
@@ -304,6 +317,8 @@ interface LoginOptions {
|
|
|
304
317
|
getToken: () => Promise<string | null>;
|
|
305
318
|
setToken: (token: string) => Promise<void>;
|
|
306
319
|
removeToken: () => Promise<void>;
|
|
320
|
+
getTokenData?: () => Promise<StoredTokenData | null>;
|
|
321
|
+
setTokenData?: (data: StoredTokenData) => Promise<void>;
|
|
307
322
|
};
|
|
308
323
|
}
|
|
309
324
|
interface LoginResult {
|
|
@@ -313,6 +328,7 @@ interface LoginResult {
|
|
|
313
328
|
/**
|
|
314
329
|
* Get existing token or perform device flow login
|
|
315
330
|
* Handles browser launch and token storage automatically
|
|
331
|
+
* Automatically refreshes expired tokens if refresh_token is available
|
|
316
332
|
*/
|
|
317
333
|
declare function ensureLoggedIn(options?: LoginOptions): Promise<LoginResult>;
|
|
318
334
|
/**
|
package/dist/index.js
CHANGED
|
@@ -148,6 +148,10 @@ var init_storage = __esm({
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
async getToken() {
|
|
151
|
+
const data = await this.getTokenData();
|
|
152
|
+
if (data) {
|
|
153
|
+
return data.accessToken;
|
|
154
|
+
}
|
|
151
155
|
if (!await this.init() || !this.tokenPath) return null;
|
|
152
156
|
try {
|
|
153
157
|
const fs = await import('fs/promises');
|
|
@@ -158,23 +162,45 @@ var init_storage = __esm({
|
|
|
158
162
|
`Warning: Token file has insecure permissions (${mode.toString(8)}). Expected 600. Run: chmod 600 ${this.tokenPath}`
|
|
159
163
|
);
|
|
160
164
|
}
|
|
161
|
-
const
|
|
162
|
-
|
|
165
|
+
const content = await fs.readFile(this.tokenPath, "utf-8");
|
|
166
|
+
const trimmed = content.trim();
|
|
167
|
+
if (trimmed.startsWith("{")) {
|
|
168
|
+
const data2 = JSON.parse(trimmed);
|
|
169
|
+
return data2.accessToken;
|
|
170
|
+
}
|
|
171
|
+
return trimmed;
|
|
163
172
|
} catch {
|
|
164
173
|
return null;
|
|
165
174
|
}
|
|
166
175
|
}
|
|
167
176
|
async setToken(token) {
|
|
177
|
+
await this.setTokenData({ accessToken: token.trim() });
|
|
178
|
+
}
|
|
179
|
+
async getTokenData() {
|
|
180
|
+
if (!await this.init() || !this.tokenPath) return null;
|
|
181
|
+
try {
|
|
182
|
+
const fs = await import('fs/promises');
|
|
183
|
+
const content = await fs.readFile(this.tokenPath, "utf-8");
|
|
184
|
+
const trimmed = content.trim();
|
|
185
|
+
if (trimmed.startsWith("{")) {
|
|
186
|
+
return JSON.parse(trimmed);
|
|
187
|
+
}
|
|
188
|
+
return { accessToken: trimmed };
|
|
189
|
+
} catch {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async setTokenData(data) {
|
|
168
194
|
if (!await this.init() || !this.tokenPath || !this.configDir) {
|
|
169
195
|
throw new Error("File storage not available");
|
|
170
196
|
}
|
|
171
197
|
try {
|
|
172
198
|
const fs = await import('fs/promises');
|
|
173
199
|
await fs.mkdir(this.configDir, { recursive: true, mode: 448 });
|
|
174
|
-
await fs.writeFile(this.tokenPath,
|
|
200
|
+
await fs.writeFile(this.tokenPath, JSON.stringify(data), { encoding: "utf-8", mode: 384 });
|
|
175
201
|
await fs.chmod(this.tokenPath, 384);
|
|
176
202
|
} catch (error) {
|
|
177
|
-
console.error("Failed to save token:", error);
|
|
203
|
+
console.error("Failed to save token data:", error);
|
|
178
204
|
throw error;
|
|
179
205
|
}
|
|
180
206
|
}
|
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/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\tconst imported = await import('keytar')\n\t\t\t// Handle ESM/CJS interop - keytar is CommonJS, so functions may be on .default\n\t\t\tconst keytarModule = (imported as any).default || imported\n\t\t\tthis.keytar = keytarModule as typeof import('keytar')\n\n\t\t\t// Verify the module loaded correctly by checking for expected function\n\t\t\tif (typeof this.keytar.getPassword !== 'function') {\n\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\tconsole.warn('Keytar module loaded but getPassword is not a function:', Object.keys(this.keytar))\n\t\t\t\t}\n\t\t\t\tthis.keytar = null\n\t\t\t\treturn null\n\t\t\t}\n\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\tthrow new Error('Keychain storage not available')\n\t\t\t}\n\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error: any) {\n\t\t\t// Check if this is a native module error vs an actual keychain error\n\t\t\tif (error?.code === 'MODULE_NOT_FOUND' || error?.message?.includes('Cannot find module')) {\n\t\t\t\tthrow new Error('Keychain storage not available: native module not built')\n\t\t\t}\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Try a read operation to verify keychain access\n\t\t\t// This will throw if native module is not built\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain not available:', error)\n\t\t\t}\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 the default storage for Node.js CLI because it doesn't require\n * GUI authorization popups like the keychain does on macOS.\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\t/**\n\t * Get information about the storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'file'; secure: boolean; path: string | null }> {\n\t\tawait this.init()\n\t\treturn { type: 'file', secure: true, path: this.tokenPath }\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 secure file storage (~/.oauth.do/token with 0600 permissions)\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n *\n * Note: We use file storage by default because keychain storage on macOS\n * requires GUI authorization popups, which breaks automation and agent workflows.\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use secure file storage (no keychain popups)\n\tif (isNode()) {\n\t\treturn new SecureFileTokenStorage()\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 * Resolve a secret that could be a plain string or a secrets store binding\n * Secrets store bindings have a .get() method that returns a Promise<string>\n * @see https://developers.cloudflare.com/workers/configuration/secrets/#secrets-store\n */\nasync function resolveSecret(value: unknown): Promise<string | null> {\n\tif (!value) return null\n\tif (typeof value === 'string') return value\n\tif (typeof value === 'object' && typeof (value as any).get === 'function') {\n\t\treturn await (value as any).get()\n\t}\n\treturn null\n}\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 getUser(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. globalThis.DO_ADMIN_TOKEN / DO_TOKEN (Workers legacy)\n * 2. process.env.DO_ADMIN_TOKEN / DO_TOKEN (Node.js)\n * 3. cloudflare:workers env import (Workers 2025+) - supports secrets store bindings\n * 4. Stored token (keychain/secure file)\n *\n * @see https://developers.cloudflare.com/changelog/2025-03-17-importable-env/\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers legacy, 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 cloudflare:workers env import (Workers 2025+)\n\t// Supports both plain strings and secrets store bindings\n\ttry {\n\t\t// @ts-ignore - cloudflare:workers only available in Workers runtime\n\t\tconst { env } = await import('cloudflare:workers')\n\n\t\tconst cfAdminToken = await resolveSecret((env as any).DO_ADMIN_TOKEN)\n\t\tif (cfAdminToken) return cfAdminToken\n\n\t\tconst cfToken = await resolveSecret((env as any).DO_TOKEN)\n\t\tif (cfToken) return cfToken\n\t} catch {\n\t\t// Not in Workers environment or env not available\n\t}\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 getUser(token)\n\treturn result.user !== null\n}\n\n/**\n * Auth provider function type for HTTP clients\n */\nexport type AuthProvider = () => string | null | undefined | Promise<string | null | undefined>\n\n/**\n * Create an auth provider function for HTTP clients (apis.do, rpc.do)\n * Returns a function that resolves to a token string\n *\n * @example\n * import { auth } from 'oauth.do'\n * const getAuth = auth()\n * const token = await getAuth()\n */\nexport function auth(): AuthProvider {\n\treturn getToken\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({\n\t\t\tclient_id: config.clientId,\n\t\t\tscope: 'openid profile email',\n\t\t})\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 * oauth.do - OAuth authentication SDK and CLI for .do Platform\n *\n * This is the browser-safe entry point.\n * For CLI utilities that open the browser, import from 'oauth.do/cli'\n *\n * @packageDocumentation\n */\n\n// Browser-safe auth utilities\nexport { auth, getUser, login, logout, getToken, isAuthenticated, buildAuthUrl } from './auth.js'\nexport type { AuthProvider } from './auth.js'\nexport { configure, getConfig } from './config.js'\nexport { authorizeDevice, pollForTokens } from './device.js'\n\n// Storage utilities (browser-safe - uses dynamic imports for Node.js features)\nexport {\n\tFileTokenStorage,\n\tMemoryTokenStorage,\n\tLocalStorageTokenStorage,\n\tSecureFileTokenStorage,\n\tKeychainTokenStorage,\n\tCompositeTokenStorage,\n\tcreateSecureStorage,\n} from './storage.js'\n\n// Types\nexport type {\n\tOAuthConfig,\n\tUser,\n\tAuthResult,\n\tDeviceAuthorizationResponse,\n\tTokenResponse,\n\tTokenError,\n\tTokenStorage,\n} from './types.js'\n\n// Re-export login types only (not functions - they use 'open' package)\nexport type { LoginOptions, LoginResult } from './login.js'\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/storage.ts","../src/config.ts","../src/auth.ts","../src/device.ts","../src/index.ts"],"names":["getEnv","data","createSecureStorage"],"mappings":"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","file":"index.js","sourcesContent":["import type { TokenStorage, StoredTokenData } 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\tconst imported = await import('keytar')\n\t\t\t// Handle ESM/CJS interop - keytar is CommonJS, so functions may be on .default\n\t\t\tconst keytarModule = (imported as any).default || imported\n\t\t\tthis.keytar = keytarModule as typeof import('keytar')\n\n\t\t\t// Verify the module loaded correctly by checking for expected function\n\t\t\tif (typeof this.keytar.getPassword !== 'function') {\n\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\tconsole.warn('Keytar module loaded but getPassword is not a function:', Object.keys(this.keytar))\n\t\t\t\t}\n\t\t\t\tthis.keytar = null\n\t\t\t\treturn null\n\t\t\t}\n\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\tthrow new Error('Keychain storage not available')\n\t\t\t}\n\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error: any) {\n\t\t\t// Check if this is a native module error vs an actual keychain error\n\t\t\tif (error?.code === 'MODULE_NOT_FOUND' || error?.message?.includes('Cannot find module')) {\n\t\t\t\tthrow new Error('Keychain storage not available: native module not built')\n\t\t\t}\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Try a read operation to verify keychain access\n\t\t\t// This will throw if native module is not built\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain not available:', error)\n\t\t\t}\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 the default storage for Node.js CLI because it doesn't require\n * GUI authorization popups like the keychain does on macOS.\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\t// Try to get from token data first (new format)\n\t\tconst data = await this.getTokenData()\n\t\tif (data) {\n\t\t\treturn data.accessToken\n\t\t}\n\n\t\t// Fall back to legacy plain text format\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 stats = await fs.stat(this.tokenPath)\n\t\t\tconst mode = stats.mode & 0o777\n\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 content = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\tconst trimmed = content.trim()\n\n\t\t\t// Check if it's JSON (new format) or plain token (legacy)\n\t\t\tif (trimmed.startsWith('{')) {\n\t\t\t\tconst data = JSON.parse(trimmed) as StoredTokenData\n\t\t\t\treturn data.accessToken\n\t\t\t}\n\n\t\t\treturn trimmed\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\t// Store as token data for consistency, trimming whitespace\n\t\tawait this.setTokenData({ accessToken: token.trim() })\n\t}\n\n\tasync getTokenData(): Promise<StoredTokenData | 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 content = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\tconst trimmed = content.trim()\n\n\t\t\t// Check if it's JSON format\n\t\t\tif (trimmed.startsWith('{')) {\n\t\t\t\treturn JSON.parse(trimmed) as StoredTokenData\n\t\t\t}\n\n\t\t\t// Legacy plain text format - convert to token data\n\t\t\treturn { accessToken: trimmed }\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setTokenData(data: StoredTokenData): 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, mode: 0o700 })\n\t\t\tawait fs.writeFile(this.tokenPath, JSON.stringify(data), { encoding: 'utf-8', mode: 0o600 })\n\t\t\tawait fs.chmod(this.tokenPath, 0o600)\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token data:', 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\t/**\n\t * Get information about the storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'file'; secure: boolean; path: string | null }> {\n\t\tawait this.init()\n\t\treturn { type: 'file', secure: true, path: this.tokenPath }\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 secure file storage (~/.oauth.do/token with 0600 permissions)\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n *\n * Note: We use file storage by default because keychain storage on macOS\n * requires GUI authorization popups, which breaks automation and agent workflows.\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use secure file storage (no keychain popups)\n\tif (isNode()) {\n\t\treturn new SecureFileTokenStorage()\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, TokenResponse, StoredTokenData } from './types.js'\n\n/**\n * Resolve a secret that could be a plain string or a secrets store binding\n * Secrets store bindings have a .get() method that returns a Promise<string>\n * @see https://developers.cloudflare.com/workers/configuration/secrets/#secrets-store\n */\nasync function resolveSecret(value: unknown): Promise<string | null> {\n\tif (!value) return null\n\tif (typeof value === 'string') return value\n\tif (typeof value === 'object' && typeof (value as any).get === 'function') {\n\t\treturn await (value as any).get()\n\t}\n\treturn null\n}\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 getUser(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. globalThis.DO_ADMIN_TOKEN / DO_TOKEN (Workers legacy)\n * 2. process.env.DO_ADMIN_TOKEN / DO_TOKEN (Node.js)\n * 3. cloudflare:workers env import (Workers 2025+) - supports secrets store bindings\n * 4. Stored token (keychain/secure file)\n *\n * @see https://developers.cloudflare.com/changelog/2025-03-17-importable-env/\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers legacy, 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 cloudflare:workers env import (Workers 2025+)\n\t// Supports both plain strings and secrets store bindings\n\ttry {\n\t\t// @ts-ignore - cloudflare:workers only available in Workers runtime\n\t\tconst { env } = await import('cloudflare:workers')\n\n\t\tconst cfAdminToken = await resolveSecret((env as any).DO_ADMIN_TOKEN)\n\t\tif (cfAdminToken) return cfAdminToken\n\n\t\tconst cfToken = await resolveSecret((env as any).DO_TOKEN)\n\t\tif (cfToken) return cfToken\n\t} catch {\n\t\t// Not in Workers environment or env not available\n\t}\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 getUser(token)\n\treturn result.user !== null\n}\n\n/**\n * Auth provider function type for HTTP clients\n */\nexport type AuthProvider = () => string | null | undefined | Promise<string | null | undefined>\n\n/**\n * Create an auth provider function for HTTP clients (apis.do, rpc.do)\n * Returns a function that resolves to a token string\n *\n * @example\n * import { auth } from 'oauth.do'\n * const getAuth = auth()\n * const token = await getAuth()\n */\nexport function auth(): AuthProvider {\n\treturn getToken\n}\n\n/**\n * Refresh an access token using a refresh token\n *\n * @param refreshToken - The refresh token from the original auth response\n * @returns New token response with fresh access_token (and possibly new refresh_token)\n */\nexport async function refreshAccessToken(refreshToken: string): Promise<TokenResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for token refresh')\n\t}\n\n\tconst response = await config.fetch('https://auth.apis.do/user_management/authenticate', {\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t},\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: 'refresh_token',\n\t\t\trefresh_token: refreshToken,\n\t\t\tclient_id: config.clientId,\n\t\t}),\n\t})\n\n\tif (!response.ok) {\n\t\tconst errorText = await response.text()\n\t\tthrow new Error(`Token refresh failed: ${response.status} - ${errorText}`)\n\t}\n\n\treturn (await response.json()) as TokenResponse\n}\n\n/**\n * Get stored token data from storage\n */\nexport async function getStoredTokenData(): Promise<StoredTokenData | null> {\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\tif (storage.getTokenData) {\n\t\t\treturn await storage.getTokenData()\n\t\t}\n\t\t// Fall back to just access token\n\t\tconst token = await storage.getToken()\n\t\treturn token ? { accessToken: token } : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Store token data including refresh token\n */\nexport async function storeTokenData(data: StoredTokenData): Promise<void> {\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\tif (storage.setTokenData) {\n\t\t\tawait storage.setTokenData(data)\n\t\t} else {\n\t\t\tawait storage.setToken(data.accessToken)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('Failed to store token data:', error)\n\t\tthrow error\n\t}\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({\n\t\t\tclient_id: config.clientId,\n\t\t\tscope: 'openid profile email',\n\t\t})\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 * oauth.do - OAuth authentication SDK and CLI for .do Platform\n *\n * This is the browser-safe entry point.\n * For CLI utilities that open the browser, import from 'oauth.do/cli'\n *\n * @packageDocumentation\n */\n\n// Browser-safe auth utilities\nexport { auth, getUser, login, logout, getToken, isAuthenticated, buildAuthUrl } from './auth.js'\nexport type { AuthProvider } from './auth.js'\nexport { configure, getConfig } from './config.js'\nexport { authorizeDevice, pollForTokens } from './device.js'\n\n// Storage utilities (browser-safe - uses dynamic imports for Node.js features)\nexport {\n\tFileTokenStorage,\n\tMemoryTokenStorage,\n\tLocalStorageTokenStorage,\n\tSecureFileTokenStorage,\n\tKeychainTokenStorage,\n\tCompositeTokenStorage,\n\tcreateSecureStorage,\n} from './storage.js'\n\n// Types\nexport type {\n\tOAuthConfig,\n\tUser,\n\tAuthResult,\n\tDeviceAuthorizationResponse,\n\tTokenResponse,\n\tTokenError,\n\tTokenStorage,\n} from './types.js'\n\n// Re-export login types only (not functions - they use 'open' package)\nexport type { LoginOptions, LoginResult } from './login.js'\n"]}
|
package/dist/node.js
CHANGED
|
@@ -148,6 +148,10 @@ var init_storage = __esm({
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
async getToken() {
|
|
151
|
+
const data = await this.getTokenData();
|
|
152
|
+
if (data) {
|
|
153
|
+
return data.accessToken;
|
|
154
|
+
}
|
|
151
155
|
if (!await this.init() || !this.tokenPath) return null;
|
|
152
156
|
try {
|
|
153
157
|
const fs = await import('fs/promises');
|
|
@@ -158,23 +162,45 @@ var init_storage = __esm({
|
|
|
158
162
|
`Warning: Token file has insecure permissions (${mode.toString(8)}). Expected 600. Run: chmod 600 ${this.tokenPath}`
|
|
159
163
|
);
|
|
160
164
|
}
|
|
161
|
-
const
|
|
162
|
-
|
|
165
|
+
const content = await fs.readFile(this.tokenPath, "utf-8");
|
|
166
|
+
const trimmed = content.trim();
|
|
167
|
+
if (trimmed.startsWith("{")) {
|
|
168
|
+
const data2 = JSON.parse(trimmed);
|
|
169
|
+
return data2.accessToken;
|
|
170
|
+
}
|
|
171
|
+
return trimmed;
|
|
163
172
|
} catch {
|
|
164
173
|
return null;
|
|
165
174
|
}
|
|
166
175
|
}
|
|
167
176
|
async setToken(token) {
|
|
177
|
+
await this.setTokenData({ accessToken: token.trim() });
|
|
178
|
+
}
|
|
179
|
+
async getTokenData() {
|
|
180
|
+
if (!await this.init() || !this.tokenPath) return null;
|
|
181
|
+
try {
|
|
182
|
+
const fs = await import('fs/promises');
|
|
183
|
+
const content = await fs.readFile(this.tokenPath, "utf-8");
|
|
184
|
+
const trimmed = content.trim();
|
|
185
|
+
if (trimmed.startsWith("{")) {
|
|
186
|
+
return JSON.parse(trimmed);
|
|
187
|
+
}
|
|
188
|
+
return { accessToken: trimmed };
|
|
189
|
+
} catch {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async setTokenData(data) {
|
|
168
194
|
if (!await this.init() || !this.tokenPath || !this.configDir) {
|
|
169
195
|
throw new Error("File storage not available");
|
|
170
196
|
}
|
|
171
197
|
try {
|
|
172
198
|
const fs = await import('fs/promises');
|
|
173
199
|
await fs.mkdir(this.configDir, { recursive: true, mode: 448 });
|
|
174
|
-
await fs.writeFile(this.tokenPath,
|
|
200
|
+
await fs.writeFile(this.tokenPath, JSON.stringify(data), { encoding: "utf-8", mode: 384 });
|
|
175
201
|
await fs.chmod(this.tokenPath, 384);
|
|
176
202
|
} catch (error) {
|
|
177
|
-
console.error("Failed to save token:", error);
|
|
203
|
+
console.error("Failed to save token data:", error);
|
|
178
204
|
throw error;
|
|
179
205
|
}
|
|
180
206
|
}
|
|
@@ -472,6 +498,28 @@ async function isAuthenticated(token) {
|
|
|
472
498
|
function auth() {
|
|
473
499
|
return getToken;
|
|
474
500
|
}
|
|
501
|
+
async function refreshAccessToken(refreshToken) {
|
|
502
|
+
const config = getConfig();
|
|
503
|
+
if (!config.clientId) {
|
|
504
|
+
throw new Error("Client ID is required for token refresh");
|
|
505
|
+
}
|
|
506
|
+
const response = await config.fetch("https://auth.apis.do/user_management/authenticate", {
|
|
507
|
+
method: "POST",
|
|
508
|
+
headers: {
|
|
509
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
510
|
+
},
|
|
511
|
+
body: new URLSearchParams({
|
|
512
|
+
grant_type: "refresh_token",
|
|
513
|
+
refresh_token: refreshToken,
|
|
514
|
+
client_id: config.clientId
|
|
515
|
+
})
|
|
516
|
+
});
|
|
517
|
+
if (!response.ok) {
|
|
518
|
+
const errorText = await response.text();
|
|
519
|
+
throw new Error(`Token refresh failed: ${response.status} - ${errorText}`);
|
|
520
|
+
}
|
|
521
|
+
return await response.json();
|
|
522
|
+
}
|
|
475
523
|
function buildAuthUrl(options) {
|
|
476
524
|
const config = getConfig();
|
|
477
525
|
const clientId = options.clientId || config.clientId;
|
|
@@ -576,11 +624,60 @@ init_storage();
|
|
|
576
624
|
|
|
577
625
|
// src/login.ts
|
|
578
626
|
init_storage();
|
|
627
|
+
var REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
628
|
+
function isTokenExpired(expiresAt) {
|
|
629
|
+
if (!expiresAt) return false;
|
|
630
|
+
return Date.now() >= expiresAt - REFRESH_BUFFER_MS;
|
|
631
|
+
}
|
|
579
632
|
async function ensureLoggedIn(options = {}) {
|
|
580
633
|
const { openBrowser = true, print = console.log, storage = createSecureStorage() } = options;
|
|
581
|
-
const
|
|
634
|
+
const tokenData = storage.getTokenData ? await storage.getTokenData() : null;
|
|
635
|
+
const existingToken = tokenData?.accessToken || await storage.getToken();
|
|
582
636
|
if (existingToken) {
|
|
583
|
-
|
|
637
|
+
if (tokenData && isTokenExpired(tokenData.expiresAt)) {
|
|
638
|
+
if (tokenData.refreshToken) {
|
|
639
|
+
try {
|
|
640
|
+
const newTokens = await refreshAccessToken(tokenData.refreshToken);
|
|
641
|
+
const expiresAt2 = newTokens.expires_in ? Date.now() + newTokens.expires_in * 1e3 : void 0;
|
|
642
|
+
const newData2 = {
|
|
643
|
+
accessToken: newTokens.access_token,
|
|
644
|
+
refreshToken: newTokens.refresh_token || tokenData.refreshToken,
|
|
645
|
+
expiresAt: expiresAt2
|
|
646
|
+
};
|
|
647
|
+
if (storage.setTokenData) {
|
|
648
|
+
await storage.setTokenData(newData2);
|
|
649
|
+
} else {
|
|
650
|
+
await storage.setToken(newTokens.access_token);
|
|
651
|
+
}
|
|
652
|
+
return { token: newTokens.access_token, isNewLogin: false };
|
|
653
|
+
} catch (error) {
|
|
654
|
+
console.warn("Token refresh failed:", error);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
} else {
|
|
658
|
+
const { user } = await getUser(existingToken);
|
|
659
|
+
if (user) {
|
|
660
|
+
return { token: existingToken, isNewLogin: false };
|
|
661
|
+
}
|
|
662
|
+
if (tokenData?.refreshToken) {
|
|
663
|
+
try {
|
|
664
|
+
const newTokens = await refreshAccessToken(tokenData.refreshToken);
|
|
665
|
+
const expiresAt2 = newTokens.expires_in ? Date.now() + newTokens.expires_in * 1e3 : void 0;
|
|
666
|
+
const newData2 = {
|
|
667
|
+
accessToken: newTokens.access_token,
|
|
668
|
+
refreshToken: newTokens.refresh_token || tokenData.refreshToken,
|
|
669
|
+
expiresAt: expiresAt2
|
|
670
|
+
};
|
|
671
|
+
if (storage.setTokenData) {
|
|
672
|
+
await storage.setTokenData(newData2);
|
|
673
|
+
} else {
|
|
674
|
+
await storage.setToken(newTokens.access_token);
|
|
675
|
+
}
|
|
676
|
+
return { token: newTokens.access_token, isNewLogin: false };
|
|
677
|
+
} catch {
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
584
681
|
}
|
|
585
682
|
print("\nLogging in...\n");
|
|
586
683
|
const authResponse = await authorizeDevice();
|
|
@@ -604,7 +701,17 @@ async function ensureLoggedIn(options = {}) {
|
|
|
604
701
|
authResponse.interval,
|
|
605
702
|
authResponse.expires_in
|
|
606
703
|
);
|
|
607
|
-
|
|
704
|
+
const expiresAt = tokenResponse.expires_in ? Date.now() + tokenResponse.expires_in * 1e3 : void 0;
|
|
705
|
+
const newData = {
|
|
706
|
+
accessToken: tokenResponse.access_token,
|
|
707
|
+
refreshToken: tokenResponse.refresh_token,
|
|
708
|
+
expiresAt
|
|
709
|
+
};
|
|
710
|
+
if (storage.setTokenData) {
|
|
711
|
+
await storage.setTokenData(newData);
|
|
712
|
+
} else {
|
|
713
|
+
await storage.setToken(tokenResponse.access_token);
|
|
714
|
+
}
|
|
608
715
|
print("Login successful!\n");
|
|
609
716
|
return { token: tokenResponse.access_token, isNewLogin: true };
|
|
610
717
|
}
|
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/storage.ts","../src/config.ts","../src/auth.ts","../src/device.ts","../src/index.ts","../src/login.ts"],"names":["getEnv","createSecureStorage"],"mappings":"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","file":"node.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\tconst imported = await import('keytar')\n\t\t\t// Handle ESM/CJS interop - keytar is CommonJS, so functions may be on .default\n\t\t\tconst keytarModule = (imported as any).default || imported\n\t\t\tthis.keytar = keytarModule as typeof import('keytar')\n\n\t\t\t// Verify the module loaded correctly by checking for expected function\n\t\t\tif (typeof this.keytar.getPassword !== 'function') {\n\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\tconsole.warn('Keytar module loaded but getPassword is not a function:', Object.keys(this.keytar))\n\t\t\t\t}\n\t\t\t\tthis.keytar = null\n\t\t\t\treturn null\n\t\t\t}\n\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\tthrow new Error('Keychain storage not available')\n\t\t\t}\n\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error: any) {\n\t\t\t// Check if this is a native module error vs an actual keychain error\n\t\t\tif (error?.code === 'MODULE_NOT_FOUND' || error?.message?.includes('Cannot find module')) {\n\t\t\t\tthrow new Error('Keychain storage not available: native module not built')\n\t\t\t}\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Try a read operation to verify keychain access\n\t\t\t// This will throw if native module is not built\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain not available:', error)\n\t\t\t}\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 the default storage for Node.js CLI because it doesn't require\n * GUI authorization popups like the keychain does on macOS.\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\t/**\n\t * Get information about the storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'file'; secure: boolean; path: string | null }> {\n\t\tawait this.init()\n\t\treturn { type: 'file', secure: true, path: this.tokenPath }\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 secure file storage (~/.oauth.do/token with 0600 permissions)\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n *\n * Note: We use file storage by default because keychain storage on macOS\n * requires GUI authorization popups, which breaks automation and agent workflows.\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use secure file storage (no keychain popups)\n\tif (isNode()) {\n\t\treturn new SecureFileTokenStorage()\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 * Resolve a secret that could be a plain string or a secrets store binding\n * Secrets store bindings have a .get() method that returns a Promise<string>\n * @see https://developers.cloudflare.com/workers/configuration/secrets/#secrets-store\n */\nasync function resolveSecret(value: unknown): Promise<string | null> {\n\tif (!value) return null\n\tif (typeof value === 'string') return value\n\tif (typeof value === 'object' && typeof (value as any).get === 'function') {\n\t\treturn await (value as any).get()\n\t}\n\treturn null\n}\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 getUser(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. globalThis.DO_ADMIN_TOKEN / DO_TOKEN (Workers legacy)\n * 2. process.env.DO_ADMIN_TOKEN / DO_TOKEN (Node.js)\n * 3. cloudflare:workers env import (Workers 2025+) - supports secrets store bindings\n * 4. Stored token (keychain/secure file)\n *\n * @see https://developers.cloudflare.com/changelog/2025-03-17-importable-env/\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers legacy, 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 cloudflare:workers env import (Workers 2025+)\n\t// Supports both plain strings and secrets store bindings\n\ttry {\n\t\t// @ts-ignore - cloudflare:workers only available in Workers runtime\n\t\tconst { env } = await import('cloudflare:workers')\n\n\t\tconst cfAdminToken = await resolveSecret((env as any).DO_ADMIN_TOKEN)\n\t\tif (cfAdminToken) return cfAdminToken\n\n\t\tconst cfToken = await resolveSecret((env as any).DO_TOKEN)\n\t\tif (cfToken) return cfToken\n\t} catch {\n\t\t// Not in Workers environment or env not available\n\t}\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 getUser(token)\n\treturn result.user !== null\n}\n\n/**\n * Auth provider function type for HTTP clients\n */\nexport type AuthProvider = () => string | null | undefined | Promise<string | null | undefined>\n\n/**\n * Create an auth provider function for HTTP clients (apis.do, rpc.do)\n * Returns a function that resolves to a token string\n *\n * @example\n * import { auth } from 'oauth.do'\n * const getAuth = auth()\n * const token = await getAuth()\n */\nexport function auth(): AuthProvider {\n\treturn getToken\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({\n\t\t\tclient_id: config.clientId,\n\t\t\tscope: 'openid profile email',\n\t\t})\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 * oauth.do - OAuth authentication SDK and CLI for .do Platform\n *\n * This is the browser-safe entry point.\n * For CLI utilities that open the browser, import from 'oauth.do/cli'\n *\n * @packageDocumentation\n */\n\n// Browser-safe auth utilities\nexport { auth, getUser, login, logout, getToken, isAuthenticated, buildAuthUrl } from './auth.js'\nexport type { AuthProvider } from './auth.js'\nexport { configure, getConfig } from './config.js'\nexport { authorizeDevice, pollForTokens } from './device.js'\n\n// Storage utilities (browser-safe - uses dynamic imports for Node.js features)\nexport {\n\tFileTokenStorage,\n\tMemoryTokenStorage,\n\tLocalStorageTokenStorage,\n\tSecureFileTokenStorage,\n\tKeychainTokenStorage,\n\tCompositeTokenStorage,\n\tcreateSecureStorage,\n} from './storage.js'\n\n// Types\nexport type {\n\tOAuthConfig,\n\tUser,\n\tAuthResult,\n\tDeviceAuthorizationResponse,\n\tTokenResponse,\n\tTokenError,\n\tTokenStorage,\n} from './types.js'\n\n// Re-export login types only (not functions - they use 'open' package)\nexport type { LoginOptions, LoginResult } from './login.js'\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\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"]}
|
|
1
|
+
{"version":3,"sources":["../src/storage.ts","../src/config.ts","../src/auth.ts","../src/device.ts","../src/index.ts","../src/login.ts"],"names":["getEnv","data","createSecureStorage","expiresAt","newData"],"mappings":"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","file":"node.js","sourcesContent":["import type { TokenStorage, StoredTokenData } 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\tconst imported = await import('keytar')\n\t\t\t// Handle ESM/CJS interop - keytar is CommonJS, so functions may be on .default\n\t\t\tconst keytarModule = (imported as any).default || imported\n\t\t\tthis.keytar = keytarModule as typeof import('keytar')\n\n\t\t\t// Verify the module loaded correctly by checking for expected function\n\t\t\tif (typeof this.keytar.getPassword !== 'function') {\n\t\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\t\tconsole.warn('Keytar module loaded but getPassword is not a function:', Object.keys(this.keytar))\n\t\t\t\t}\n\t\t\t\tthis.keytar = null\n\t\t\t\treturn null\n\t\t\t}\n\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\tthrow new Error('Keychain storage not available')\n\t\t\t}\n\n\t\t\tawait keytar.setPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, token)\n\t\t} catch (error: any) {\n\t\t\t// Check if this is a native module error vs an actual keychain error\n\t\t\tif (error?.code === 'MODULE_NOT_FOUND' || error?.message?.includes('Cannot find module')) {\n\t\t\t\tthrow new Error('Keychain storage not available: native module not built')\n\t\t\t}\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\ttry {\n\t\t\tconst keytar = await this.getKeytar()\n\t\t\tif (!keytar) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Try a read operation to verify keychain access\n\t\t\t// This will throw if native module is not built\n\t\t\tawait keytar.getPassword(KEYCHAIN_SERVICE, '__test__')\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (getEnv('DEBUG')) {\n\t\t\t\tconsole.warn('Keychain not available:', error)\n\t\t\t}\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 the default storage for Node.js CLI because it doesn't require\n * GUI authorization popups like the keychain does on macOS.\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\t// Try to get from token data first (new format)\n\t\tconst data = await this.getTokenData()\n\t\tif (data) {\n\t\t\treturn data.accessToken\n\t\t}\n\n\t\t// Fall back to legacy plain text format\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 stats = await fs.stat(this.tokenPath)\n\t\t\tconst mode = stats.mode & 0o777\n\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 content = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\tconst trimmed = content.trim()\n\n\t\t\t// Check if it's JSON (new format) or plain token (legacy)\n\t\t\tif (trimmed.startsWith('{')) {\n\t\t\t\tconst data = JSON.parse(trimmed) as StoredTokenData\n\t\t\t\treturn data.accessToken\n\t\t\t}\n\n\t\t\treturn trimmed\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setToken(token: string): Promise<void> {\n\t\t// Store as token data for consistency, trimming whitespace\n\t\tawait this.setTokenData({ accessToken: token.trim() })\n\t}\n\n\tasync getTokenData(): Promise<StoredTokenData | 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 content = await fs.readFile(this.tokenPath, 'utf-8')\n\t\t\tconst trimmed = content.trim()\n\n\t\t\t// Check if it's JSON format\n\t\t\tif (trimmed.startsWith('{')) {\n\t\t\t\treturn JSON.parse(trimmed) as StoredTokenData\n\t\t\t}\n\n\t\t\t// Legacy plain text format - convert to token data\n\t\t\treturn { accessToken: trimmed }\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tasync setTokenData(data: StoredTokenData): 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, mode: 0o700 })\n\t\t\tawait fs.writeFile(this.tokenPath, JSON.stringify(data), { encoding: 'utf-8', mode: 0o600 })\n\t\t\tawait fs.chmod(this.tokenPath, 0o600)\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to save token data:', 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\t/**\n\t * Get information about the storage backend\n\t */\n\tasync getStorageInfo(): Promise<{ type: 'file'; secure: boolean; path: string | null }> {\n\t\tawait this.init()\n\t\treturn { type: 'file', secure: true, path: this.tokenPath }\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 secure file storage (~/.oauth.do/token with 0600 permissions)\n * - Browser: Uses localStorage\n * - Worker: Uses in-memory storage (tokens should be passed via env bindings)\n *\n * Note: We use file storage by default because keychain storage on macOS\n * requires GUI authorization popups, which breaks automation and agent workflows.\n */\nexport function createSecureStorage(): TokenStorage {\n\t// Node.js - use secure file storage (no keychain popups)\n\tif (isNode()) {\n\t\treturn new SecureFileTokenStorage()\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, TokenResponse, StoredTokenData } from './types.js'\n\n/**\n * Resolve a secret that could be a plain string or a secrets store binding\n * Secrets store bindings have a .get() method that returns a Promise<string>\n * @see https://developers.cloudflare.com/workers/configuration/secrets/#secrets-store\n */\nasync function resolveSecret(value: unknown): Promise<string | null> {\n\tif (!value) return null\n\tif (typeof value === 'string') return value\n\tif (typeof value === 'object' && typeof (value as any).get === 'function') {\n\t\treturn await (value as any).get()\n\t}\n\treturn null\n}\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 getUser(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. globalThis.DO_ADMIN_TOKEN / DO_TOKEN (Workers legacy)\n * 2. process.env.DO_ADMIN_TOKEN / DO_TOKEN (Node.js)\n * 3. cloudflare:workers env import (Workers 2025+) - supports secrets store bindings\n * 4. Stored token (keychain/secure file)\n *\n * @see https://developers.cloudflare.com/changelog/2025-03-17-importable-env/\n */\nexport async function getToken(): Promise<string | null> {\n\t// Check env vars first (globalThis for Workers legacy, 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 cloudflare:workers env import (Workers 2025+)\n\t// Supports both plain strings and secrets store bindings\n\ttry {\n\t\t// @ts-ignore - cloudflare:workers only available in Workers runtime\n\t\tconst { env } = await import('cloudflare:workers')\n\n\t\tconst cfAdminToken = await resolveSecret((env as any).DO_ADMIN_TOKEN)\n\t\tif (cfAdminToken) return cfAdminToken\n\n\t\tconst cfToken = await resolveSecret((env as any).DO_TOKEN)\n\t\tif (cfToken) return cfToken\n\t} catch {\n\t\t// Not in Workers environment or env not available\n\t}\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 getUser(token)\n\treturn result.user !== null\n}\n\n/**\n * Auth provider function type for HTTP clients\n */\nexport type AuthProvider = () => string | null | undefined | Promise<string | null | undefined>\n\n/**\n * Create an auth provider function for HTTP clients (apis.do, rpc.do)\n * Returns a function that resolves to a token string\n *\n * @example\n * import { auth } from 'oauth.do'\n * const getAuth = auth()\n * const token = await getAuth()\n */\nexport function auth(): AuthProvider {\n\treturn getToken\n}\n\n/**\n * Refresh an access token using a refresh token\n *\n * @param refreshToken - The refresh token from the original auth response\n * @returns New token response with fresh access_token (and possibly new refresh_token)\n */\nexport async function refreshAccessToken(refreshToken: string): Promise<TokenResponse> {\n\tconst config = getConfig()\n\n\tif (!config.clientId) {\n\t\tthrow new Error('Client ID is required for token refresh')\n\t}\n\n\tconst response = await config.fetch('https://auth.apis.do/user_management/authenticate', {\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t},\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: 'refresh_token',\n\t\t\trefresh_token: refreshToken,\n\t\t\tclient_id: config.clientId,\n\t\t}),\n\t})\n\n\tif (!response.ok) {\n\t\tconst errorText = await response.text()\n\t\tthrow new Error(`Token refresh failed: ${response.status} - ${errorText}`)\n\t}\n\n\treturn (await response.json()) as TokenResponse\n}\n\n/**\n * Get stored token data from storage\n */\nexport async function getStoredTokenData(): Promise<StoredTokenData | null> {\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\tif (storage.getTokenData) {\n\t\t\treturn await storage.getTokenData()\n\t\t}\n\t\t// Fall back to just access token\n\t\tconst token = await storage.getToken()\n\t\treturn token ? { accessToken: token } : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Store token data including refresh token\n */\nexport async function storeTokenData(data: StoredTokenData): Promise<void> {\n\ttry {\n\t\tconst { createSecureStorage } = await import('./storage.js')\n\t\tconst storage = createSecureStorage()\n\t\tif (storage.setTokenData) {\n\t\t\tawait storage.setTokenData(data)\n\t\t} else {\n\t\t\tawait storage.setToken(data.accessToken)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('Failed to store token data:', error)\n\t\tthrow error\n\t}\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({\n\t\t\tclient_id: config.clientId,\n\t\t\tscope: 'openid profile email',\n\t\t})\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 * oauth.do - OAuth authentication SDK and CLI for .do Platform\n *\n * This is the browser-safe entry point.\n * For CLI utilities that open the browser, import from 'oauth.do/cli'\n *\n * @packageDocumentation\n */\n\n// Browser-safe auth utilities\nexport { auth, getUser, login, logout, getToken, isAuthenticated, buildAuthUrl } from './auth.js'\nexport type { AuthProvider } from './auth.js'\nexport { configure, getConfig } from './config.js'\nexport { authorizeDevice, pollForTokens } from './device.js'\n\n// Storage utilities (browser-safe - uses dynamic imports for Node.js features)\nexport {\n\tFileTokenStorage,\n\tMemoryTokenStorage,\n\tLocalStorageTokenStorage,\n\tSecureFileTokenStorage,\n\tKeychainTokenStorage,\n\tCompositeTokenStorage,\n\tcreateSecureStorage,\n} from './storage.js'\n\n// Types\nexport type {\n\tOAuthConfig,\n\tUser,\n\tAuthResult,\n\tDeviceAuthorizationResponse,\n\tTokenResponse,\n\tTokenError,\n\tTokenStorage,\n} from './types.js'\n\n// Re-export login types only (not functions - they use 'open' package)\nexport type { LoginOptions, LoginResult } from './login.js'\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'\nimport { refreshAccessToken, getUser } from './auth.js'\nimport type { StoredTokenData } from './types.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\tgetTokenData?: () => Promise<StoredTokenData | null>\n\t\tsetTokenData?: (data: StoredTokenData) => Promise<void>\n\t}\n}\n\nexport interface LoginResult {\n\ttoken: string\n\tisNewLogin: boolean\n}\n\n// Buffer time before expiration to trigger refresh (5 minutes)\nconst REFRESH_BUFFER_MS = 5 * 60 * 1000\n\n/**\n * Check if token is expired or about to expire\n */\nfunction isTokenExpired(expiresAt?: number): boolean {\n\tif (!expiresAt) return false // Can't determine, assume valid\n\treturn Date.now() >= expiresAt - REFRESH_BUFFER_MS\n}\n\n/**\n * Get existing token or perform device flow login\n * Handles browser launch and token storage automatically\n * Automatically refreshes expired tokens if refresh_token is available\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 data\n\tconst tokenData = storage.getTokenData ? await storage.getTokenData() : null\n\tconst existingToken = tokenData?.accessToken || (await storage.getToken())\n\n\tif (existingToken) {\n\t\t// Check if token is expired\n\t\tif (tokenData && isTokenExpired(tokenData.expiresAt)) {\n\t\t\t// Try to refresh\n\t\t\tif (tokenData.refreshToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst newTokens = await refreshAccessToken(tokenData.refreshToken)\n\n\t\t\t\t\t// Calculate new expiration time\n\t\t\t\t\tconst expiresAt = newTokens.expires_in\n\t\t\t\t\t\t? Date.now() + newTokens.expires_in * 1000\n\t\t\t\t\t\t: undefined\n\n\t\t\t\t\t// Store new token data\n\t\t\t\t\tconst newData: StoredTokenData = {\n\t\t\t\t\t\taccessToken: newTokens.access_token,\n\t\t\t\t\t\trefreshToken: newTokens.refresh_token || tokenData.refreshToken,\n\t\t\t\t\t\texpiresAt,\n\t\t\t\t\t}\n\n\t\t\t\t\tif (storage.setTokenData) {\n\t\t\t\t\t\tawait storage.setTokenData(newData)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait storage.setToken(newTokens.access_token)\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { token: newTokens.access_token, isNewLogin: false }\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Refresh failed - might need to re-login\n\t\t\t\t\tconsole.warn('Token refresh failed:', error)\n\t\t\t\t\t// Fall through to device flow\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Token exists and not expired - validate it\n\t\t\tconst { user } = await getUser(existingToken)\n\t\t\tif (user) {\n\t\t\t\treturn { token: existingToken, isNewLogin: false }\n\t\t\t}\n\t\t\t// Token invalid - try refresh if available\n\t\t\tif (tokenData?.refreshToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst newTokens = await refreshAccessToken(tokenData.refreshToken)\n\t\t\t\t\tconst expiresAt = newTokens.expires_in\n\t\t\t\t\t\t? Date.now() + newTokens.expires_in * 1000\n\t\t\t\t\t\t: undefined\n\n\t\t\t\t\tconst newData: StoredTokenData = {\n\t\t\t\t\t\taccessToken: newTokens.access_token,\n\t\t\t\t\t\trefreshToken: newTokens.refresh_token || tokenData.refreshToken,\n\t\t\t\t\t\texpiresAt,\n\t\t\t\t\t}\n\n\t\t\t\t\tif (storage.setTokenData) {\n\t\t\t\t\t\tawait storage.setTokenData(newData)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait storage.setToken(newTokens.access_token)\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { token: newTokens.access_token, isNewLogin: false }\n\t\t\t\t} catch {\n\t\t\t\t\t// Refresh failed - need to re-login\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// No valid 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\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\t// Calculate expiration time\n\tconst expiresAt = tokenResponse.expires_in\n\t\t? Date.now() + tokenResponse.expires_in * 1000\n\t\t: undefined\n\n\t// Store full token data including refresh token\n\tconst newData: StoredTokenData = {\n\t\taccessToken: tokenResponse.access_token,\n\t\trefreshToken: tokenResponse.refresh_token,\n\t\texpiresAt,\n\t}\n\n\tif (storage.setTokenData) {\n\t\tawait storage.setTokenData(newData)\n\t} else {\n\t\tawait storage.setToken(tokenResponse.access_token)\n\t}\n\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oauth.do",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "OAuth authentication SDK and CLI for .do Platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"dev": "tsup --watch",
|
|
31
31
|
"test": "vitest run",
|
|
32
32
|
"test:watch": "vitest",
|
|
33
|
-
"
|
|
33
|
+
"check:publish": "node -e \"const pkg = require('./package.json'); const deps = JSON.stringify(pkg.dependencies || {}); if (deps.includes('workspace:')) { console.error('ERROR: workspace: protocol found in dependencies. Replace with actual versions before publishing.'); process.exit(1); }\"",
|
|
34
|
+
"prepublishOnly": "pnpm check:publish && pnpm build && pnpm test"
|
|
34
35
|
},
|
|
35
36
|
"keywords": [
|
|
36
37
|
"oauth",
|