@doow/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -0
- package/dist/cjs/auth/api-key.js +159 -0
- package/dist/cjs/auth/api-key.js.map +1 -0
- package/dist/cjs/auth/detect.js +173 -0
- package/dist/cjs/auth/detect.js.map +1 -0
- package/dist/cjs/auth/device-flow.js +135 -0
- package/dist/cjs/auth/device-flow.js.map +1 -0
- package/dist/cjs/auth/keyring.js +118 -0
- package/dist/cjs/auth/keyring.js.map +1 -0
- package/dist/cjs/auth/pkce.js +243 -0
- package/dist/cjs/auth/pkce.js.map +1 -0
- package/dist/cjs/auth/refresh.js +203 -0
- package/dist/cjs/auth/refresh.js.map +1 -0
- package/dist/cjs/config/env.js +44 -0
- package/dist/cjs/config/env.js.map +1 -0
- package/dist/cjs/config/store.js +178 -0
- package/dist/cjs/config/store.js.map +1 -0
- package/dist/cjs/index.js +48 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cli.cjs +34372 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/esm/auth/api-key.js +154 -0
- package/dist/esm/auth/api-key.js.map +1 -0
- package/dist/esm/auth/detect.js +150 -0
- package/dist/esm/auth/detect.js.map +1 -0
- package/dist/esm/auth/device-flow.js +132 -0
- package/dist/esm/auth/device-flow.js.map +1 -0
- package/dist/esm/auth/keyring.js +116 -0
- package/dist/esm/auth/keyring.js.map +1 -0
- package/dist/esm/auth/pkce.js +220 -0
- package/dist/esm/auth/pkce.js.map +1 -0
- package/dist/esm/auth/refresh.js +198 -0
- package/dist/esm/auth/refresh.js.map +1 -0
- package/dist/esm/config/env.js +38 -0
- package/dist/esm/config/env.js.map +1 -0
- package/dist/esm/config/store.js +166 -0
- package/dist/esm/config/store.js.map +1 -0
- package/dist/esm/index.js +15 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/mcp.cjs +8 -0
- package/dist/mcp.cjs.map +1 -0
- package/dist/types/index.d.ts +369 -0
- package/package.json +62 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { clearProfileCredentials, deleteProfile, getActiveProfile, getConfigDir, getProfileCredentials, readConfig, readCredentials, setActiveProfile, setProfileCredentials, writeConfig, writeCredentials } from './config/store.js';
|
|
2
|
+
export { getApiUrl, isAgentMode, isCI, isTTY, shouldShowUI } from './config/env.js';
|
|
3
|
+
export { createCredentialStore } from './auth/keyring.js';
|
|
4
|
+
export { executePkceFlow, generatePkcePair } from './auth/pkce.js';
|
|
5
|
+
export { executeDeviceFlow } from './auth/device-flow.js';
|
|
6
|
+
export { authenticateWithApiKey, readTokenFromStdin, resolveAuth, validateApiKey } from './auth/api-key.js';
|
|
7
|
+
export { acquireLock, needsRefresh, refreshToken, releaseLock } from './auth/refresh.js';
|
|
8
|
+
export { canBindLocalhost, detectAuthMethod, executeAutoLogin } from './auth/detect.js';
|
|
9
|
+
|
|
10
|
+
// @doow/cli library entry point
|
|
11
|
+
// Re-exports for programmatic usage
|
|
12
|
+
const VERSION = '0.1.0';
|
|
13
|
+
|
|
14
|
+
export { VERSION };
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;AAAA;AACA;AAEO,MAAM,OAAO,GAAG;;;;"}
|
package/dist/mcp.cjs
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// MCP server entry point — placeholder for Phase 4 (E45)
|
|
5
|
+
// Will use @modelcontextprotocol/sdk for stdio + Streamable HTTP transport
|
|
6
|
+
console.error('doow mcp server: not yet implemented (Phase 4 — E45)');
|
|
7
|
+
process.exit(1);
|
|
8
|
+
//# sourceMappingURL=mcp.cjs.map
|
package/dist/mcp.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.cjs","sources":["../src/mcp.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAAA;AACA;AAEA,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC;AACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;;"}
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile — one named context (org + API endpoint)
|
|
3
|
+
*/
|
|
4
|
+
interface Profile {
|
|
5
|
+
name: string;
|
|
6
|
+
apiUrl?: string;
|
|
7
|
+
organizationId?: string;
|
|
8
|
+
email?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Top-level config stored in ~/.doow/config.json
|
|
12
|
+
*/
|
|
13
|
+
interface DoowConfig {
|
|
14
|
+
activeProfile: string;
|
|
15
|
+
profiles: Record<string, Profile>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Stored credentials for a single profile (tokens / API key)
|
|
19
|
+
*/
|
|
20
|
+
interface ProfileCredentials {
|
|
21
|
+
accessToken?: string;
|
|
22
|
+
refreshToken?: string;
|
|
23
|
+
/** ISO-8601 datetime string */
|
|
24
|
+
expiresAt?: string;
|
|
25
|
+
apiKey?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Top-level credentials stored in ~/.doow/credentials.json
|
|
29
|
+
*/
|
|
30
|
+
interface Credentials {
|
|
31
|
+
profiles: Record<string, ProfileCredentials>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns the Doow config directory path.
|
|
36
|
+
* Prefers $DOOW_CONFIG_DIR when set; falls back to ~/.doow.
|
|
37
|
+
* Creates the directory (mode 0o700) if it does not yet exist.
|
|
38
|
+
*/
|
|
39
|
+
declare function getConfigDir(): Promise<string>;
|
|
40
|
+
/** Reads ~/.doow/config.json. Returns the default config if the file is absent. */
|
|
41
|
+
declare function readConfig(): Promise<DoowConfig>;
|
|
42
|
+
/** Writes ~/.doow/config.json atomically with 0o600 perms. */
|
|
43
|
+
declare function writeConfig(config: DoowConfig): Promise<void>;
|
|
44
|
+
/** Reads ~/.doow/credentials.json. Returns empty credentials if absent. */
|
|
45
|
+
declare function readCredentials(): Promise<Credentials>;
|
|
46
|
+
/** Writes ~/.doow/credentials.json atomically with 0o600 perms. */
|
|
47
|
+
declare function writeCredentials(creds: Credentials): Promise<void>;
|
|
48
|
+
/** Returns the currently active Profile object. */
|
|
49
|
+
declare function getActiveProfile(): Promise<Profile>;
|
|
50
|
+
/** Sets the active profile name and persists config. Throws if the profile doesn't exist. */
|
|
51
|
+
declare function setActiveProfile(name: string): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Returns credentials for the given profile name.
|
|
54
|
+
* Defaults to the currently active profile if name is omitted.
|
|
55
|
+
*/
|
|
56
|
+
declare function getProfileCredentials(profileName?: string): Promise<ProfileCredentials | undefined>;
|
|
57
|
+
/** Stores credentials for the given profile, merging with existing. */
|
|
58
|
+
declare function setProfileCredentials(profileName: string, creds: ProfileCredentials): Promise<void>;
|
|
59
|
+
/** Removes all credentials for the given profile. */
|
|
60
|
+
declare function clearProfileCredentials(profileName: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Deletes a profile from config + credentials.
|
|
63
|
+
* Throws if the profile is currently active — caller must switch first.
|
|
64
|
+
*/
|
|
65
|
+
declare function deleteProfile(name: string): Promise<void>;
|
|
66
|
+
|
|
67
|
+
/** True when stdout is an interactive terminal. */
|
|
68
|
+
declare function isTTY(): boolean;
|
|
69
|
+
/** True when running inside a CI environment (any common CI sets $CI). */
|
|
70
|
+
declare function isCI(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* True when the CLI is invoked by an automated agent rather than a human.
|
|
73
|
+
* Detected via $DOOW_AGENT_MODE env var or the --agent CLI flag (which
|
|
74
|
+
* Commander stores on the global options object as `process.env` is the
|
|
75
|
+
* canonical signal here — Commander integration is wired up in cli.ts).
|
|
76
|
+
*/
|
|
77
|
+
declare function isAgentMode(): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* True when interactive UI (spinners, prompts, color) should be shown.
|
|
80
|
+
* Requires a real TTY, no CI env, and not running in agent mode.
|
|
81
|
+
*/
|
|
82
|
+
declare function shouldShowUI(): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Resolve the API base URL.
|
|
85
|
+
* Precedence: profile.apiUrl → $DOOW_API_URL → hardcoded default.
|
|
86
|
+
*/
|
|
87
|
+
declare function getApiUrl(profile?: Profile): string;
|
|
88
|
+
|
|
89
|
+
interface CredentialStore {
|
|
90
|
+
get(profileName: string): Promise<ProfileCredentials | undefined>;
|
|
91
|
+
set(profileName: string, creds: ProfileCredentials): Promise<void>;
|
|
92
|
+
clear(profileName: string): Promise<void>;
|
|
93
|
+
backend(): 'keyring' | 'file';
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Creates a CredentialStore backed by the system keyring when available,
|
|
97
|
+
* falling back to file storage silently when keytar is not installed or
|
|
98
|
+
* the system keyring does not respond within 3 seconds.
|
|
99
|
+
*
|
|
100
|
+
* Call this once at startup and reuse the returned instance.
|
|
101
|
+
*/
|
|
102
|
+
declare function createCredentialStore(): Promise<CredentialStore>;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* pkce.ts
|
|
106
|
+
*
|
|
107
|
+
* OAuth 2.0 PKCE (RFC 7636) interactive login flow for the Doow CLI.
|
|
108
|
+
*
|
|
109
|
+
* Steps:
|
|
110
|
+
* 1. Generate PKCE code_verifier + code_challenge
|
|
111
|
+
* 2. Generate CSRF state token
|
|
112
|
+
* 3. Start a localhost HTTP server on a random port
|
|
113
|
+
* 4. Open browser to the authorize URL
|
|
114
|
+
* 5. Wait for the OAuth callback (120 s default timeout)
|
|
115
|
+
* 6. Exchange authorization code for tokens
|
|
116
|
+
* 7. Store tokens via CredentialStore
|
|
117
|
+
* 8. Close server and return result
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
interface PkceFlowOptions {
|
|
121
|
+
apiUrl?: string;
|
|
122
|
+
profileName?: string;
|
|
123
|
+
credentialStore?: CredentialStore;
|
|
124
|
+
/** Milliseconds. Default 120_000 (2 minutes). */
|
|
125
|
+
timeout?: number;
|
|
126
|
+
}
|
|
127
|
+
interface PkceFlowResult {
|
|
128
|
+
accessToken: string;
|
|
129
|
+
refreshToken: string;
|
|
130
|
+
expiresAt: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Generates a PKCE code_verifier and code_challenge pair.
|
|
134
|
+
* - code_verifier: 32 random bytes, base64url-encoded (43 chars)
|
|
135
|
+
* - code_challenge: SHA-256 of verifier, base64url-encoded
|
|
136
|
+
*/
|
|
137
|
+
declare function generatePkcePair(): {
|
|
138
|
+
codeVerifier: string;
|
|
139
|
+
codeChallenge: string;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Executes the full PKCE browser-based OAuth 2.0 login flow.
|
|
143
|
+
*
|
|
144
|
+
* Opens the system browser to the Doow authorize endpoint, waits for the
|
|
145
|
+
* localhost callback, exchanges the authorization code for tokens, and
|
|
146
|
+
* persists the tokens via the credential store.
|
|
147
|
+
*/
|
|
148
|
+
declare function executePkceFlow(options?: PkceFlowOptions): Promise<PkceFlowResult>;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* device-flow.ts
|
|
152
|
+
*
|
|
153
|
+
* RFC 8628 OAuth 2.0 Device Authorization flow for headless/SSH/container
|
|
154
|
+
* environments where a browser cannot be opened on the same machine.
|
|
155
|
+
*
|
|
156
|
+
* Steps:
|
|
157
|
+
* 1. POST /v1/auth/device/authorize → get device_code + user_code
|
|
158
|
+
* 2. Display verification URI + user_code on stderr
|
|
159
|
+
* 3. Optionally open the browser (best-effort)
|
|
160
|
+
* 4. Poll POST /v1/auth/device/token until granted or expired
|
|
161
|
+
* 5. Store tokens in the credential store
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
interface DeviceFlowOptions {
|
|
165
|
+
apiUrl?: string;
|
|
166
|
+
profileName?: string;
|
|
167
|
+
credentialStore?: CredentialStore;
|
|
168
|
+
/**
|
|
169
|
+
* Injectable URL opener — defaults to the `open` npm package.
|
|
170
|
+
* Provide a custom function in tests to avoid spawning a real browser process.
|
|
171
|
+
*/
|
|
172
|
+
openUrl?: (url: string) => Promise<unknown>;
|
|
173
|
+
}
|
|
174
|
+
interface DeviceFlowResult {
|
|
175
|
+
accessToken: string;
|
|
176
|
+
refreshToken: string;
|
|
177
|
+
expiresAt: string;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Execute the RFC 8628 device authorization flow.
|
|
181
|
+
*
|
|
182
|
+
* All user-facing output goes to stderr so stdout stays clean for piping.
|
|
183
|
+
*
|
|
184
|
+
* @throws {Error} if authorization fails or the device code expires.
|
|
185
|
+
*/
|
|
186
|
+
declare function executeDeviceFlow(options?: DeviceFlowOptions): Promise<DeviceFlowResult>;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* api-key.ts
|
|
190
|
+
*
|
|
191
|
+
* PAT (Personal Access Token) authentication for CI/scripting contexts.
|
|
192
|
+
*
|
|
193
|
+
* Provides:
|
|
194
|
+
* - validateApiKey — pure format check (dak_ prefix, length ≥ 20)
|
|
195
|
+
* - authenticateWithApiKey — store key + optionally verify against API
|
|
196
|
+
* - readTokenFromStdin — read a piped token from stdin
|
|
197
|
+
* - resolveAuth — precedence chain: flag > env > stdin > stored > none
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
interface ApiKeyAuthOptions {
|
|
201
|
+
key: string;
|
|
202
|
+
apiUrl?: string;
|
|
203
|
+
profileName?: string;
|
|
204
|
+
credentialStore?: CredentialStore;
|
|
205
|
+
/** default true — hit capabilities endpoint to confirm key works */
|
|
206
|
+
verify?: boolean;
|
|
207
|
+
}
|
|
208
|
+
interface ApiKeyAuthResult {
|
|
209
|
+
apiKey: string;
|
|
210
|
+
verified: boolean;
|
|
211
|
+
}
|
|
212
|
+
interface ResolveAuthOptions {
|
|
213
|
+
/** --api-key flag value */
|
|
214
|
+
apiKeyFlag?: string;
|
|
215
|
+
/** --token-stdin flag */
|
|
216
|
+
tokenStdin?: boolean;
|
|
217
|
+
profileName?: string;
|
|
218
|
+
credentialStore?: CredentialStore;
|
|
219
|
+
}
|
|
220
|
+
interface ResolvedAuth {
|
|
221
|
+
type: 'api-key' | 'oauth-token' | 'none';
|
|
222
|
+
/** the bearer token (api key or access token) */
|
|
223
|
+
token?: string;
|
|
224
|
+
/** human-readable source: '--api-key flag', 'DOOW_API_KEY env', 'stdin', 'stored profile' */
|
|
225
|
+
source: string;
|
|
226
|
+
/** true if stored token is expired (expiresAt < now + 60s buffer) */
|
|
227
|
+
needsRefresh?: boolean;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Returns true if key starts with 'dak_' (case-sensitive) and is at least
|
|
231
|
+
* 20 characters total. Pure function — no network call.
|
|
232
|
+
*/
|
|
233
|
+
declare function validateApiKey(key: string): boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Validates the key format, stores it in the credential store, and optionally
|
|
236
|
+
* verifies it works by hitting GET /v1/auth/capabilities.
|
|
237
|
+
*
|
|
238
|
+
* @throws {Error} if the key does not have the dak_ prefix
|
|
239
|
+
* @throws {Error} if verify is true and the capabilities request fails
|
|
240
|
+
*/
|
|
241
|
+
declare function authenticateWithApiKey(options: ApiKeyAuthOptions): Promise<ApiKeyAuthResult>;
|
|
242
|
+
/**
|
|
243
|
+
* Reads a token from piped stdin input.
|
|
244
|
+
*
|
|
245
|
+
* @throws {Error} if stdin is a TTY (not piped)
|
|
246
|
+
* @throws {Error} if the resulting string is empty after trim
|
|
247
|
+
*/
|
|
248
|
+
declare function readTokenFromStdin(): Promise<string>;
|
|
249
|
+
/**
|
|
250
|
+
* Resolves the active auth context by walking the precedence chain:
|
|
251
|
+
* --api-key flag > DOOW_API_KEY env > --token-stdin > stored profile > none
|
|
252
|
+
*/
|
|
253
|
+
declare function resolveAuth(options?: ResolveAuthOptions): Promise<ResolvedAuth>;
|
|
254
|
+
|
|
255
|
+
interface RefreshOptions {
|
|
256
|
+
apiUrl?: string;
|
|
257
|
+
profileName?: string;
|
|
258
|
+
credentialStore?: CredentialStore;
|
|
259
|
+
}
|
|
260
|
+
interface RefreshResult {
|
|
261
|
+
accessToken: string;
|
|
262
|
+
refreshToken: string;
|
|
263
|
+
expiresAt: string;
|
|
264
|
+
/** false if another process already refreshed before we could */
|
|
265
|
+
wasRefreshed: boolean;
|
|
266
|
+
}
|
|
267
|
+
interface LockHandle {
|
|
268
|
+
lockPath: string;
|
|
269
|
+
release(): Promise<void>;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Returns true when the credential token needs a refresh:
|
|
273
|
+
* - no expiresAt present, OR
|
|
274
|
+
* - token expires within the 60-second buffer window
|
|
275
|
+
*
|
|
276
|
+
* Pure function — no I/O.
|
|
277
|
+
*/
|
|
278
|
+
declare function needsRefresh(creds: ProfileCredentials): boolean;
|
|
279
|
+
/**
|
|
280
|
+
* Acquires an exclusive per-profile lock file.
|
|
281
|
+
*
|
|
282
|
+
* Uses O_EXCL (writeFile flag:'wx') for atomic exclusive creation.
|
|
283
|
+
* If a lock exists, checks staleness (>60s or dead PID) and cleans up if stale.
|
|
284
|
+
* Retries up to 10 times with 500ms back-off before throwing.
|
|
285
|
+
*/
|
|
286
|
+
declare function acquireLock(profileName: string): Promise<LockHandle>;
|
|
287
|
+
/**
|
|
288
|
+
* Releases a previously acquired lock handle. Best-effort — never throws.
|
|
289
|
+
*/
|
|
290
|
+
declare function releaseLock(handle: LockHandle): Promise<void>;
|
|
291
|
+
/**
|
|
292
|
+
* Performs a transparent token refresh with double-checked locking.
|
|
293
|
+
*
|
|
294
|
+
* 1. Acquires a per-profile lockfile
|
|
295
|
+
* 2. Re-reads credentials — another process may have already refreshed
|
|
296
|
+
* 3. If tokens are still fresh, skips the network call (wasRefreshed: false)
|
|
297
|
+
* 4. Otherwise calls POST /v1/auth/refresh and stores the new tokens
|
|
298
|
+
* 5. Always releases the lock in a finally block
|
|
299
|
+
*
|
|
300
|
+
* Throws with a user-friendly message if the session has expired.
|
|
301
|
+
*/
|
|
302
|
+
declare function refreshToken(options?: RefreshOptions): Promise<RefreshResult>;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* detect.ts
|
|
306
|
+
*
|
|
307
|
+
* S122 — Auth auto-detection for the Doow CLI.
|
|
308
|
+
*
|
|
309
|
+
* Determines whether to use PKCE, device, or API-key authentication based on
|
|
310
|
+
* the current runtime environment, then executes the appropriate flow.
|
|
311
|
+
*
|
|
312
|
+
* Detection order:
|
|
313
|
+
* 1. --api-key provided + valid format → api-key
|
|
314
|
+
* 2. --device flag → device
|
|
315
|
+
* 3. Running inside CI ($CI set) → device
|
|
316
|
+
* 4. Non-interactive stdout (!isTTY) → device
|
|
317
|
+
* 5. Can bind 127.0.0.1 on a free port → pkce
|
|
318
|
+
* 6. Fallback → device
|
|
319
|
+
*/
|
|
320
|
+
|
|
321
|
+
type AuthMethod = 'pkce' | 'device' | 'api-key';
|
|
322
|
+
interface DetectOptions {
|
|
323
|
+
/** --device flag: force device flow even in interactive environments */
|
|
324
|
+
forceDevice?: boolean;
|
|
325
|
+
/** --api-key flag value */
|
|
326
|
+
apiKey?: string;
|
|
327
|
+
}
|
|
328
|
+
interface AutoLoginOptions {
|
|
329
|
+
forceDevice?: boolean;
|
|
330
|
+
apiKey?: string;
|
|
331
|
+
apiUrl?: string;
|
|
332
|
+
profileName?: string;
|
|
333
|
+
credentialStore?: CredentialStore;
|
|
334
|
+
/** PKCE callback timeout in ms. Default: 120_000 */
|
|
335
|
+
timeout?: number;
|
|
336
|
+
}
|
|
337
|
+
interface LoginResult {
|
|
338
|
+
method: AuthMethod;
|
|
339
|
+
accessToken?: string;
|
|
340
|
+
refreshToken?: string;
|
|
341
|
+
expiresAt?: string;
|
|
342
|
+
apiKey?: string;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Tests whether the process can bind a TCP server on 127.0.0.1 using an
|
|
346
|
+
* OS-assigned ephemeral port. The server is closed immediately on success.
|
|
347
|
+
*
|
|
348
|
+
* Returns true → PKCE callback server will work.
|
|
349
|
+
* Returns false → Network stack can't bind (containers with restricted network
|
|
350
|
+
* policies, permission denied, etc.) — use device flow instead.
|
|
351
|
+
*/
|
|
352
|
+
declare function canBindLocalhost(): Promise<boolean>;
|
|
353
|
+
/**
|
|
354
|
+
* Returns the best authentication method for the current environment.
|
|
355
|
+
*/
|
|
356
|
+
declare function detectAuthMethod(options?: DetectOptions): Promise<AuthMethod>;
|
|
357
|
+
/**
|
|
358
|
+
* The main login orchestrator.
|
|
359
|
+
*
|
|
360
|
+
* 1. Detects the best auth method.
|
|
361
|
+
* 2. Executes the corresponding flow.
|
|
362
|
+
* 3. If PKCE fails with a server bind error, automatically retries with device flow.
|
|
363
|
+
*/
|
|
364
|
+
declare function executeAutoLogin(options?: AutoLoginOptions): Promise<LoginResult>;
|
|
365
|
+
|
|
366
|
+
declare const VERSION = "0.1.0";
|
|
367
|
+
|
|
368
|
+
export { VERSION, acquireLock, authenticateWithApiKey, canBindLocalhost, clearProfileCredentials, createCredentialStore, deleteProfile, detectAuthMethod, executeAutoLogin, executeDeviceFlow, executePkceFlow, generatePkcePair, getActiveProfile, getApiUrl, getConfigDir, getProfileCredentials, isAgentMode, isCI, isTTY, needsRefresh, readConfig, readCredentials, readTokenFromStdin, refreshToken, releaseLock, resolveAuth, setActiveProfile, setProfileCredentials, shouldShowUI, validateApiKey, writeConfig, writeCredentials };
|
|
369
|
+
export type { ApiKeyAuthOptions, ApiKeyAuthResult, AuthMethod, AutoLoginOptions, CredentialStore, Credentials, DetectOptions, DeviceFlowOptions, DeviceFlowResult, DoowConfig, LockHandle, LoginResult, PkceFlowOptions, PkceFlowResult, Profile, ProfileCredentials, RefreshOptions, RefreshResult, ResolveAuthOptions, ResolvedAuth };
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@doow/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Doow CLI — manage SaaS spend from your terminal and coding agents",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Doow",
|
|
7
|
+
"main": "./dist/cjs/index.js",
|
|
8
|
+
"module": "./dist/esm/index.js",
|
|
9
|
+
"types": "./dist/types/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/esm/index.js",
|
|
13
|
+
"require": "./dist/cjs/index.js",
|
|
14
|
+
"types": "./dist/types/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"doow": "./dist/cli.cjs"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "rollup -c rollup.config.mjs",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
29
|
+
"prepublishOnly": "npm run build"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
33
|
+
"commander": "^12.1.0",
|
|
34
|
+
"open": "^10.1.0",
|
|
35
|
+
"zod": "^4.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@rollup/plugin-commonjs": "^25.0.8",
|
|
39
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
40
|
+
"@rollup/plugin-node-resolve": "^15.3.1",
|
|
41
|
+
"@rollup/plugin-replace": "^5.0.7",
|
|
42
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
43
|
+
"rollup": "^4.60.2",
|
|
44
|
+
"rollup-plugin-dts": "^6.4.1",
|
|
45
|
+
"tslib": "^2.8.1",
|
|
46
|
+
"typescript": "^5.9.3",
|
|
47
|
+
"vitest": "^1.6.1"
|
|
48
|
+
},
|
|
49
|
+
"optionalDependencies": {
|
|
50
|
+
"keytar": "^7.0.0"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=18.0.0"
|
|
54
|
+
},
|
|
55
|
+
"keywords": [
|
|
56
|
+
"doow",
|
|
57
|
+
"cli",
|
|
58
|
+
"saas",
|
|
59
|
+
"spend",
|
|
60
|
+
"mcp"
|
|
61
|
+
]
|
|
62
|
+
}
|