@doist/cli-core 0.8.0 → 0.10.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/CHANGELOG.md +12 -0
- package/README.md +206 -38
- package/dist/auth/errors.d.ts +1 -1
- package/dist/auth/errors.d.ts.map +1 -1
- package/dist/auth/flow.d.ts +6 -1
- package/dist/auth/flow.d.ts.map +1 -1
- package/dist/auth/flow.js +6 -1
- package/dist/auth/flow.js.map +1 -1
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +4 -0
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/login.d.ts +54 -0
- package/dist/auth/login.d.ts.map +1 -0
- package/dist/auth/login.js +61 -0
- package/dist/auth/login.js.map +1 -0
- package/dist/auth/logout.d.ts +33 -0
- package/dist/auth/logout.d.ts.map +1 -0
- package/dist/auth/logout.js +33 -0
- package/dist/auth/logout.js.map +1 -0
- package/dist/auth/status.d.ts +58 -0
- package/dist/auth/status.d.ts.map +1 -0
- package/dist/auth/status.js +56 -0
- package/dist/auth/status.js.map +1 -0
- package/dist/auth/token-view.d.ts +24 -0
- package/dist/auth/token-view.d.ts.map +1 -0
- package/dist/auth/token-view.js +32 -0
- package/dist/auth/token-view.js.map +1 -0
- package/dist/auth/types.d.ts +3 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [0.10.0](https://github.com/Doist/cli-core/compare/v0.9.0...v0.10.0) (2026-05-12)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **auth:** add logout/status/token-view Commander attachers ([#16](https://github.com/Doist/cli-core/issues/16)) ([b7e5385](https://github.com/Doist/cli-core/commit/b7e538543e11c667da6c13938a83eca00836fd88))
|
|
6
|
+
|
|
7
|
+
## [0.9.0](https://github.com/Doist/cli-core/compare/v0.8.0...v0.9.0) (2026-05-09)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **auth:** add attachLoginCommand Commander helper ([#13](https://github.com/Doist/cli-core/issues/13)) ([bb921b8](https://github.com/Doist/cli-core/commit/bb921b83cee128c627bf7c318a016ef4a3b85582))
|
|
12
|
+
|
|
1
13
|
## [0.8.0](https://github.com/Doist/cli-core/compare/v0.7.1...v0.8.0) (2026-05-09)
|
|
2
14
|
|
|
3
15
|
### Features
|
package/README.md
CHANGED
|
@@ -12,20 +12,20 @@ npm install @doist/cli-core
|
|
|
12
12
|
|
|
13
13
|
## What's in it
|
|
14
14
|
|
|
15
|
-
| Module | Key exports
|
|
16
|
-
| -------------------- |
|
|
17
|
-
| `auth` (subpath) | `
|
|
18
|
-
| `commands` (subpath) | `registerChangelogCommand`, `registerUpdateCommand` (+ semver helpers)
|
|
19
|
-
| `config` | `getConfigPath`, `readConfig`, `readConfigStrict`, `writeConfig`, `updateConfig`, `CoreConfig`, `UpdateChannel`
|
|
20
|
-
| `empty` | `printEmpty`
|
|
21
|
-
| `errors` | `CliError`
|
|
22
|
-
| `global-args` | `parseGlobalArgs`, `createGlobalArgsStore`, `createAccessibleGate`, `createSpinnerGate`, `getProgressJsonlPath`, `isProgressJsonlEnabled`
|
|
23
|
-
| `json` | `formatJson`, `formatNdjson`
|
|
24
|
-
| `markdown` (subpath) | `preloadMarkdown`, `renderMarkdown`, `TerminalRendererOptions`
|
|
25
|
-
| `options` | `ViewOptions`
|
|
26
|
-
| `spinner` | `createSpinner`
|
|
27
|
-
| `terminal` | `isCI`, `isStderrTTY`, `isStdinTTY`, `isStdoutTTY`
|
|
28
|
-
| `testing` (subpath) | `describeEmptyMachineOutput`
|
|
15
|
+
| Module | Key exports | Purpose |
|
|
16
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `auth` (subpath) | `attachLoginCommand`, `attachLogoutCommand`, `attachStatusCommand`, `attachTokenViewCommand`, `runOAuthFlow`, `createPkceProvider`, PKCE helpers, `AuthProvider` / `TokenStore` types | OAuth runtime plus the Commander attachers for `<cli> [auth] login` / `logout` / `status` / `token`. Ships the standard public-client PKCE flow (`createPkceProvider`); `AuthProvider` and `TokenStore` are the escape hatches for DCR, OS-keychain, multi-account, etc. — consumers implement `TokenStore` directly (a single-user config-file version is ~30 LoC). `commander` (when using the attachers) and `open` (browser launch) are optional peer-deps. |
|
|
18
|
+
| `commands` (subpath) | `registerChangelogCommand`, `registerUpdateCommand` (+ semver helpers) | Commander wiring for cli-core's standard commands (e.g. `<cli> changelog`, `<cli> update`, `<cli> update switch`). **Requires** `commander` as an optional peer-dep. |
|
|
19
|
+
| `config` | `getConfigPath`, `readConfig`, `readConfigStrict`, `writeConfig`, `updateConfig`, `CoreConfig`, `UpdateChannel` | Read / write a per-CLI JSON config file with typed error codes; `CoreConfig` is the shape of fields cli-core itself owns (extend it for per-CLI fields). |
|
|
20
|
+
| `empty` | `printEmpty` | Print an empty-state message gated on `--json` / `--ndjson` so machine consumers never see human strings on stdout. |
|
|
21
|
+
| `errors` | `CliError` | Typed CLI error class with `code` and exit-code mapping. |
|
|
22
|
+
| `global-args` | `parseGlobalArgs`, `createGlobalArgsStore`, `createAccessibleGate`, `createSpinnerGate`, `getProgressJsonlPath`, `isProgressJsonlEnabled` | Parse well-known global flags (`--json`, `--ndjson`, `--quiet`, `--verbose`, `--accessible`, `--no-spinner`, `--progress-jsonl`) and derive predicates from them. |
|
|
23
|
+
| `json` | `formatJson`, `formatNdjson` | Stable JSON / newline-delimited JSON formatting for stdout. |
|
|
24
|
+
| `markdown` (subpath) | `preloadMarkdown`, `renderMarkdown`, `TerminalRendererOptions` | Lazy-init terminal markdown renderer. **Requires** `marked` and `marked-terminal-renderer` as peer-deps — install only if your CLI uses this subpath. |
|
|
25
|
+
| `options` | `ViewOptions` | Type contract for `{ json?, ndjson? }` per-command options that machine-output gates derive from. |
|
|
26
|
+
| `spinner` | `createSpinner` | Loading spinner factory wrapping `yocto-spinner` with disable gates. |
|
|
27
|
+
| `terminal` | `isCI`, `isStderrTTY`, `isStdinTTY`, `isStdoutTTY` | TTY / CI detection helpers. |
|
|
28
|
+
| `testing` (subpath) | `describeEmptyMachineOutput` | Vitest helpers reusable by consuming CLIs (e.g. parametrised empty-state suite covering `--json` / `--ndjson` / human modes). |
|
|
29
29
|
|
|
30
30
|
## Usage
|
|
31
31
|
|
|
@@ -124,55 +124,223 @@ The semver helpers (`parseVersion`, `compareVersions`, `isNewer`, `getInstallTag
|
|
|
124
124
|
|
|
125
125
|
### Auth (optional subpath)
|
|
126
126
|
|
|
127
|
-
Wire `<cli> [auth] login` and the supporting OAuth runtime
|
|
127
|
+
Wire `<cli> [auth] login` and the supporting OAuth runtime. cli-core ships the standard public-client PKCE flow (`createPkceProvider`) and the `attachLoginCommand` Commander helper that drives `runOAuthFlow` end-to-end. Bespoke flows (Dynamic Client Registration, device code, magic link, username / password) implement the `AuthProvider` interface directly — no cli-core release needed. Token storage is a `TokenStore` the consumer provides; cli-core does not ship a default.
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
Install peer-deps in the consuming CLI:
|
|
129
|
+
#### Install
|
|
132
130
|
|
|
133
131
|
```bash
|
|
134
|
-
npm install commander open
|
|
132
|
+
npm install commander open
|
|
135
133
|
```
|
|
136
134
|
|
|
137
|
-
|
|
135
|
+
`commander` is required when using `attachLoginCommand`. `open` is optional — when it's missing or `open()` throws, the authorize URL is surfaced via `onAuthorizeUrl` (or printed to stdout in human mode, stderr in `--json` / `--ndjson` mode) so the user can complete the flow manually.
|
|
136
|
+
|
|
137
|
+
#### Quick start (PKCE)
|
|
138
138
|
|
|
139
139
|
```ts
|
|
140
|
-
import {
|
|
141
|
-
import {
|
|
142
|
-
createConfigTokenStore,
|
|
143
|
-
createPkceProvider,
|
|
144
|
-
registerAuthCommand,
|
|
145
|
-
} from '@doist/cli-core/auth'
|
|
140
|
+
import { attachLoginCommand, createPkceProvider } from '@doist/cli-core/auth'
|
|
141
|
+
import type { TokenStore } from '@doist/cli-core/auth'
|
|
146
142
|
|
|
147
143
|
type Account = { id: string; label?: string; email: string }
|
|
148
144
|
|
|
149
|
-
const
|
|
150
|
-
const store = createConfigTokenStore<Account>({ configPath })
|
|
145
|
+
const store: TokenStore<Account> = createTokenStore() // see "Implementing TokenStore" below
|
|
151
146
|
|
|
152
147
|
const provider = createPkceProvider<Account>({
|
|
153
148
|
authorizeUrl: ({ handshake }) => `${handshake.baseUrl as string}/oauth/authorize`,
|
|
154
149
|
tokenUrl: ({ handshake }) => `${handshake.baseUrl as string}/oauth/token`,
|
|
155
150
|
clientId: ({ flags }) => flags.clientId as string,
|
|
156
|
-
scopes: ['read', 'write'],
|
|
157
151
|
validate: async ({ token, handshake }) => probeUser(token, handshake.baseUrl as string),
|
|
158
152
|
})
|
|
159
153
|
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
displayName: 'Outline',
|
|
154
|
+
const auth = program.command('auth')
|
|
155
|
+
attachLoginCommand<Account>(auth, {
|
|
163
156
|
provider,
|
|
164
157
|
store,
|
|
158
|
+
preferredPort: 54969,
|
|
159
|
+
portFallbackCount: 5,
|
|
165
160
|
resolveScopes: ({ readOnly }) => (readOnly ? ['read'] : ['read', 'write']),
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
161
|
+
renderSuccess: () => `<html>...</html>`,
|
|
162
|
+
renderError: (message) => `<html>${message}</html>`,
|
|
163
|
+
onSuccess: ({ account, view }) => {
|
|
164
|
+
if (view.json) console.log(JSON.stringify({ account }))
|
|
165
|
+
else console.log(`Signed in as ${account.label ?? account.id}`)
|
|
166
|
+
},
|
|
167
|
+
}).description('Authenticate via OAuth')
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
`attachLoginCommand` returns the new `Command` so you can chain `.description(...)` / `.option(...)` / `.addHelpText(...)`. Any consumer-attached options land in the `flags` object passed to `resolveScopes`, `onSuccess`, and the provider hooks.
|
|
171
|
+
|
|
172
|
+
#### Sibling attachers (`logout` / `status` / `token`)
|
|
173
|
+
|
|
174
|
+
The same registrar shape covers the other three auth subcommands. Each returns the new `Command` for chaining and shares the same `TokenStore<TAccount>` instance.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
import {
|
|
178
|
+
attachLogoutCommand,
|
|
179
|
+
attachStatusCommand,
|
|
180
|
+
attachTokenViewCommand,
|
|
181
|
+
} from '@doist/cli-core/auth'
|
|
182
|
+
|
|
183
|
+
attachLogoutCommand<Account>(auth, {
|
|
184
|
+
store,
|
|
185
|
+
onCleared: ({ account, view }) => {
|
|
186
|
+
// Optional follow-up — surface keyring-fallback warnings, etc.
|
|
187
|
+
// Route extra prose to stderr in machine-output mode.
|
|
188
|
+
if (!view.json && !view.ndjson && account) {
|
|
189
|
+
console.log(`Cleared credential for ${account.label ?? account.id}.`)
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
attachStatusCommand<Account>(auth, {
|
|
195
|
+
store,
|
|
196
|
+
fetchLive: async ({ token }) => probeUser(token), // throws CliError on 401
|
|
197
|
+
renderText: ({ account }) => [
|
|
198
|
+
`Signed in as ${account.label ?? account.id}`,
|
|
199
|
+
` Email: ${account.email}`,
|
|
200
|
+
],
|
|
201
|
+
renderJson: ({ account }) => ({ id: account.id, email: account.email }),
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
attachTokenViewCommand<Account>(auth, {
|
|
205
|
+
store,
|
|
206
|
+
envVarName: 'TODOIST_API_TOKEN', // refuse to print when the env var is populated
|
|
170
207
|
})
|
|
171
208
|
```
|
|
172
209
|
|
|
173
|
-
|
|
210
|
+
`attachLogoutCommand` snapshots `store.active()` (only when `onCleared` is supplied — skipped otherwise to avoid keyring / file I/O), calls `store.clear()`, then emits `✓ Logged out` (human) or `{ "ok": true }` (`--json`, silent under `--ndjson`) before firing `onCleared({ account, view, flags })`.
|
|
211
|
+
|
|
212
|
+
`attachStatusCommand` reads `store.active()`, optionally runs `fetchLive` (consumer translates 401 → `CliError('NO_TOKEN', …)`), then dispatches to `renderJson` (`--json` / `--ndjson` via `formatJson` / `formatNdjson`, defaults to the account itself, **only invoked in machine-output mode**) or `renderText` (human mode, string or array of lines). When the store is empty it throws `CliError('NOT_AUTHENTICATED', 'Not signed in.')` unless `onNotAuthenticated` is supplied.
|
|
213
|
+
|
|
214
|
+
Both attachers strip the standard `--json` / `--ndjson` registrar flags from the parsed options and pass the remainder to their callbacks as `flags` — same escape hatch `attachLoginCommand` uses, so a consumer can chain e.g. `.option('--user <ref>')` and read it in `onCleared` / `renderText` / `fetchLive` / `renderJson` / `onNotAuthenticated`.
|
|
215
|
+
|
|
216
|
+
`attachTokenViewCommand` writes the bare stored token to stdout (no envelope, pipe-safe) and appends a trailing newline only when stdout is a TTY. When `envVarName` is set and the env var is populated, it throws `CliError('TOKEN_FROM_ENV', …)` to avoid disclosing a token the CLI did not manage. Defaults to subcommand name `token`; pass `name: 'view'` to nest under an existing `token` group.
|
|
217
|
+
|
|
218
|
+
#### Standard flag set
|
|
219
|
+
|
|
220
|
+
`attachLoginCommand` registers four flags on the `login` subcommand:
|
|
221
|
+
|
|
222
|
+
| Flag | Effect |
|
|
223
|
+
| ------------------------ | -------------------------------------------------------------------------------------- |
|
|
224
|
+
| `--read-only` | Threaded through to `resolveScopes` and the provider hooks via `readOnly`. |
|
|
225
|
+
| `--callback-port <port>` | Override `preferredPort` per invocation. Validated as `[0..65535]`; `0` = OS-assigned. |
|
|
226
|
+
| `--json` | Machine-output mode. Authorize-URL fallback is routed to stderr. |
|
|
227
|
+
| `--ndjson` | Machine-output mode. Same fallback routing. |
|
|
228
|
+
|
|
229
|
+
Under `--json` / `--ndjson`, the authorize-URL fallback (printed when `open` is missing or `open()` throws) goes to stderr so the JSON / NDJSON envelope on stdout stays clean. Pass `onAuthorizeUrl` to override the destination. The success / error HTML returned by `renderSuccess` / `renderError` is a render hook — every CLI brings its own template (no shared layout enforced).
|
|
230
|
+
|
|
231
|
+
#### Implementing `TokenStore`
|
|
232
|
+
|
|
233
|
+
A single-user, config-file backed store using cli-core's own config helpers:
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
import { getConfigPath, readConfig, updateConfig, writeConfig } from '@doist/cli-core'
|
|
237
|
+
import type { TokenStore } from '@doist/cli-core/auth'
|
|
238
|
+
|
|
239
|
+
type Account = { id: string; label?: string; email: string }
|
|
240
|
+
type StoredAuth = { account: Account; token: string }
|
|
241
|
+
|
|
242
|
+
const configPath = getConfigPath('todoist-cli')
|
|
243
|
+
|
|
244
|
+
export const tokenStore: TokenStore<Account> = {
|
|
245
|
+
async active() {
|
|
246
|
+
const config = await readConfig<{ auth?: StoredAuth }>(configPath)
|
|
247
|
+
return config.auth ? { account: config.auth.account, token: config.auth.token } : null
|
|
248
|
+
},
|
|
249
|
+
async set(account, token) {
|
|
250
|
+
await updateConfig<{ auth: StoredAuth }>(configPath, { auth: { account, token } })
|
|
251
|
+
},
|
|
252
|
+
async clear() {
|
|
253
|
+
const { auth: _drop, ...rest } = await readConfig<{ auth?: StoredAuth }>(configPath)
|
|
254
|
+
await writeConfig(configPath, rest)
|
|
255
|
+
},
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
For OS-keychain-backed or multi-account storage, implement the same three-method interface against your backend of choice. cli-core does not ship a default because the right answer varies per CLI (single-user vs. multi-account, config file vs. keychain, sync vs. lazy decrypt).
|
|
260
|
+
|
|
261
|
+
#### Custom `AuthProvider` (non-PKCE flows)
|
|
262
|
+
|
|
263
|
+
Implement `AuthProvider` directly for Dynamic Client Registration, device code, magic-link, etc. The four hooks fire in this order during `runOAuthFlow`:
|
|
264
|
+
|
|
265
|
+
| Hook | When | Purpose |
|
|
266
|
+
| --------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
267
|
+
| `prepare?` | Before the callback server binds | Pre-flight (e.g. DCR to mint a `client_id`). The returned `handshake` is threaded into every later hook. |
|
|
268
|
+
| `authorize` | After the callback server is up | Build the URL the user opens. Returns the URL plus any handshake state needed at exchange (PKCE verifier, …). |
|
|
269
|
+
| `exchangeCode` | After the browser callback fires | Trade the `code` for an `accessToken`. Optionally returns a fully-resolved `account` to skip `validateToken`. |
|
|
270
|
+
| `validateToken` | When `exchangeCode` had no account | Probe an authenticated endpoint to resolve the account. |
|
|
271
|
+
|
|
272
|
+
Skeleton:
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
import type { AuthProvider } from '@doist/cli-core/auth'
|
|
276
|
+
|
|
277
|
+
const provider: AuthProvider<Account> = {
|
|
278
|
+
async prepare({ redirectUri, flags }) {
|
|
279
|
+
const { clientId } = await registerClient(redirectUri)
|
|
280
|
+
return { handshake: { clientId } }
|
|
281
|
+
},
|
|
282
|
+
async authorize({ redirectUri, state, scopes, handshake }) {
|
|
283
|
+
const url = buildAuthorizeUrl(handshake.clientId as string, redirectUri, state, scopes)
|
|
284
|
+
return { authorizeUrl: url, handshake }
|
|
285
|
+
},
|
|
286
|
+
async exchangeCode({ code, redirectUri, handshake }) {
|
|
287
|
+
const { access_token } = await postToken(handshake, code, redirectUri)
|
|
288
|
+
return { accessToken: access_token }
|
|
289
|
+
},
|
|
290
|
+
async validateToken({ token }) {
|
|
291
|
+
return probeUser(token)
|
|
292
|
+
},
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
The `handshake` is shared mutable state across hooks. `runOAuthFlow` folds the runtime `flags` and `readOnly` values into the handshake before `exchangeCode` and `validateToken`, so resolvers see the same view they had at `authorize` time without you having to re-thread them.
|
|
297
|
+
|
|
298
|
+
#### Errors
|
|
299
|
+
|
|
300
|
+
Every failure in this subpath surfaces as a `CliError`:
|
|
301
|
+
|
|
302
|
+
| Code | Cause |
|
|
303
|
+
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
304
|
+
| `AUTH_OAUTH_FAILED` | Provider returned `?error=...`, the flow was aborted via `signal`, or the callback server stopped before completion. |
|
|
305
|
+
| `AUTH_CALLBACK_TIMEOUT` | No valid callback within `timeoutMs` (default 3 minutes). |
|
|
306
|
+
| `AUTH_PORT_BIND_FAILED` | Could not bind any port in `[preferredPort, preferredPort + portFallbackCount]`, or `--callback-port` was out of range. |
|
|
307
|
+
| `AUTH_TOKEN_EXCHANGE_FAILED` | Token endpoint network error, non-2xx response, non-JSON body, or missing `access_token`. |
|
|
308
|
+
| `AUTH_STORE_WRITE_FAILED` | `TokenStore.set` threw a non-`CliError`. (`CliError`s thrown from `set` propagate unchanged.) |
|
|
309
|
+
| `NOT_AUTHENTICATED` | `status` / `token` ran with an empty `TokenStore` (and no `onNotAuthenticated` callback for `status`). Default message: `'Not signed in.'`. |
|
|
310
|
+
| `TOKEN_FROM_ENV` | `attachTokenViewCommand` refused to print: `envVarName` was set and the env var is populated. |
|
|
311
|
+
|
|
312
|
+
The consumer's top-level error handler formats and exits.
|
|
313
|
+
|
|
314
|
+
#### Lower-level: `runOAuthFlow`
|
|
315
|
+
|
|
316
|
+
For custom Commander wiring (different command name, programmatic invocation, embedding in a non-Commander host) call `runOAuthFlow` directly with the same option set `attachLoginCommand` builds internally:
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
import { runOAuthFlow } from '@doist/cli-core/auth'
|
|
320
|
+
|
|
321
|
+
const result = await runOAuthFlow({
|
|
322
|
+
provider,
|
|
323
|
+
store,
|
|
324
|
+
scopes: ['read', 'write'],
|
|
325
|
+
readOnly: false,
|
|
326
|
+
flags: {},
|
|
327
|
+
preferredPort: 54969,
|
|
328
|
+
renderSuccess: () => `<html>...</html>`,
|
|
329
|
+
renderError: (message) => `<html>${message}</html>`,
|
|
330
|
+
})
|
|
331
|
+
console.log(result.account)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Pass `signal` (an `AbortSignal`) to wire Ctrl-C cancellation; pass `timeoutMs`, `callbackPath`, or `callbackHost` to override the defaults (3 min / `/callback` / `127.0.0.1`).
|
|
335
|
+
|
|
336
|
+
#### PKCE primitives
|
|
337
|
+
|
|
338
|
+
For `AuthProvider` implementations that need RFC 7636 helpers without going through `createPkceProvider`:
|
|
174
339
|
|
|
175
|
-
|
|
340
|
+
- `generateVerifier({ length?, alphabet? })` — RFC 7636 verifier (43–128 chars, default 64). Pass a custom `alphabet` to match a specific server's canonicalisation (Todoist drops `.` and `~`).
|
|
341
|
+
- `deriveChallenge(verifier)` — `base64url(sha256(verifier))`, the S256 `code_challenge`.
|
|
342
|
+
- `generateState()` — 128-bit hex CSRF token suitable for the OAuth `state` parameter.
|
|
343
|
+
- `DEFAULT_VERIFIER_ALPHABET` — the 66-char RFC 7636 unreserved set.
|
|
176
344
|
|
|
177
345
|
## Development
|
|
178
346
|
|
package/dist/auth/errors.d.ts
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* aggregator in `../errors.ts` so consumers don't have to redeclare them in
|
|
4
4
|
* their own `TCode` union when catching.
|
|
5
5
|
*/
|
|
6
|
-
export type AuthErrorCode = 'AUTH_OAUTH_FAILED' | 'AUTH_CALLBACK_TIMEOUT' | 'AUTH_PORT_BIND_FAILED' | 'AUTH_TOKEN_EXCHANGE_FAILED' | 'AUTH_STORE_WRITE_FAILED';
|
|
6
|
+
export type AuthErrorCode = 'AUTH_OAUTH_FAILED' | 'AUTH_CALLBACK_TIMEOUT' | 'AUTH_PORT_BIND_FAILED' | 'AUTH_TOKEN_EXCHANGE_FAILED' | 'AUTH_STORE_WRITE_FAILED' | 'NOT_AUTHENTICATED' | 'TOKEN_FROM_ENV';
|
|
7
7
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,aAAa,GACnB,mBAAmB,GACnB,uBAAuB,GACvB,uBAAuB,GACvB,4BAA4B,GAC5B,yBAAyB,CAAA"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,aAAa,GACnB,mBAAmB,GACnB,uBAAuB,GACvB,uBAAuB,GACvB,4BAA4B,GAC5B,yBAAyB,GACzB,mBAAmB,GACnB,gBAAgB,CAAA"}
|
package/dist/auth/flow.d.ts
CHANGED
|
@@ -37,7 +37,12 @@ export type RunOAuthFlowResult<TAccount extends AuthAccount = AuthAccount> = {
|
|
|
37
37
|
* Drive the OAuth dance end-to-end and persist the resulting token.
|
|
38
38
|
*
|
|
39
39
|
* `prepare?` → bind callback server → `authorize` → open browser →
|
|
40
|
-
* wait for callback → `exchangeCode` → `validateToken
|
|
40
|
+
* wait for callback → `exchangeCode` → `validateToken?` → `store.set`.
|
|
41
|
+
* (`validateToken` is skipped when `exchangeCode` already returned an
|
|
42
|
+
* `account`.)
|
|
43
|
+
*
|
|
44
|
+
* Aborting `signal` throws `AUTH_OAUTH_FAILED`. A timeout throws
|
|
45
|
+
* `AUTH_CALLBACK_TIMEOUT`. Bind failures throw `AUTH_PORT_BIND_FAILED`.
|
|
41
46
|
*
|
|
42
47
|
* The local HTTP callback server is an internal implementation detail; it
|
|
43
48
|
* is not a separately reusable module since OAuth login is its only
|
package/dist/auth/flow.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvE,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IAC1E,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAChC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC3B,sCAAsC;IACtC,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAA;IACjB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAA;IACrB,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,MAAM,CAAA;IAC3B,qFAAqF;IACrF,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;IACxC,qFAAqF;IACrF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,sFAAsF;IACtF,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,kBAAkB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACzE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,QAAQ,CAAA;CACpB,CAAA;AAOD
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvE,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IAC1E,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAChC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC3B,sCAAsC;IACtC,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAA;IACjB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAA;IACrB,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,MAAM,CAAA;IAC3B,qFAAqF;IACrF,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;IACxC,qFAAqF;IACrF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,sFAAsF;IACtF,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,kBAAkB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACzE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,QAAQ,CAAA;CACpB,CAAA;AAOD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAAC,QAAQ,SAAS,WAAW,EAC3D,OAAO,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GACvC,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CA0GvC"}
|
package/dist/auth/flow.js
CHANGED
|
@@ -10,7 +10,12 @@ const DEFAULT_CALLBACK_HOST = '127.0.0.1';
|
|
|
10
10
|
* Drive the OAuth dance end-to-end and persist the resulting token.
|
|
11
11
|
*
|
|
12
12
|
* `prepare?` → bind callback server → `authorize` → open browser →
|
|
13
|
-
* wait for callback → `exchangeCode` → `validateToken
|
|
13
|
+
* wait for callback → `exchangeCode` → `validateToken?` → `store.set`.
|
|
14
|
+
* (`validateToken` is skipped when `exchangeCode` already returned an
|
|
15
|
+
* `account`.)
|
|
16
|
+
*
|
|
17
|
+
* Aborting `signal` throws `AUTH_OAUTH_FAILED`. A timeout throws
|
|
18
|
+
* `AUTH_CALLBACK_TIMEOUT`. Bind failures throw `AUTH_PORT_BIND_FAILED`.
|
|
14
19
|
*
|
|
15
20
|
* The local HTTP callback server is an internal implementation detail; it
|
|
16
21
|
* is not a separately reusable module since OAuth login is its only
|
package/dist/auth/flow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0D,YAAY,EAAE,MAAM,WAAW,CAAA;AAChG,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAuCzC,MAAM,2BAA2B,GAAG,CAAC,CAAA;AACrC,MAAM,2BAA2B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;AACjD,MAAM,qBAAqB,GAAG,WAAW,CAAA;AACzC,MAAM,qBAAqB,GAAG,WAAW,CAAA;AAEzC
|
|
1
|
+
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
export type { AuthErrorCode } from './errors.js';
|
|
2
2
|
export { runOAuthFlow } from './flow.js';
|
|
3
3
|
export type { RunOAuthFlowOptions, RunOAuthFlowResult } from './flow.js';
|
|
4
|
+
export { attachLoginCommand } from './login.js';
|
|
5
|
+
export type { AttachLoginCommandOptions, AttachLoginContext } from './login.js';
|
|
6
|
+
export { attachLogoutCommand } from './logout.js';
|
|
7
|
+
export type { AttachLogoutCommandOptions, AttachLogoutContext } from './logout.js';
|
|
8
|
+
export { attachStatusCommand } from './status.js';
|
|
9
|
+
export type { AttachStatusCommandOptions, AttachStatusContext } from './status.js';
|
|
10
|
+
export { attachTokenViewCommand } from './token-view.js';
|
|
11
|
+
export type { AttachTokenViewCommandOptions } from './token-view.js';
|
|
4
12
|
export { DEFAULT_VERIFIER_ALPHABET, deriveChallenge, generateState, generateVerifier, } from './pkce.js';
|
|
5
13
|
export type { GenerateVerifierOptions } from './pkce.js';
|
|
6
14
|
export { createPkceProvider } from './providers/pkce.js';
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACxE,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,gBAAgB,GACnB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9E,YAAY,EACR,WAAW,EACX,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,GAChB,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/C,YAAY,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,YAAY,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,YAAY,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,YAAY,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAA;AACpE,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,gBAAgB,GACnB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9E,YAAY,EACR,WAAW,EACX,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,GAChB,MAAM,YAAY,CAAA"}
|
package/dist/auth/index.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export { runOAuthFlow } from './flow.js';
|
|
2
|
+
export { attachLoginCommand } from './login.js';
|
|
3
|
+
export { attachLogoutCommand } from './logout.js';
|
|
4
|
+
export { attachStatusCommand } from './status.js';
|
|
5
|
+
export { attachTokenViewCommand } from './token-view.js';
|
|
2
6
|
export { DEFAULT_VERIFIER_ALPHABET, deriveChallenge, generateState, generateVerifier, } from './pkce.js';
|
|
3
7
|
export { createPkceProvider } from './providers/pkce.js';
|
|
4
8
|
//# sourceMappingURL=index.js.map
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,gBAAgB,GACnB,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAExD,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,gBAAgB,GACnB,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { ViewOptions } from '../options.js';
|
|
3
|
+
import type { AuthAccount, AuthProvider, TokenStore } from './types.js';
|
|
4
|
+
export type AttachLoginContext<TAccount extends AuthAccount> = {
|
|
5
|
+
account: TAccount;
|
|
6
|
+
/** `--json` / `--ndjson` flag values, both present (defaulted to `false`). */
|
|
7
|
+
view: Required<ViewOptions>;
|
|
8
|
+
/**
|
|
9
|
+
* Stripped per-CLI flags — the parsed options object with the standard
|
|
10
|
+
* registrar flags (`--read-only`, `--callback-port`, `--json`, `--ndjson`)
|
|
11
|
+
* removed. Same view `resolveScopes` saw at flow start.
|
|
12
|
+
*/
|
|
13
|
+
flags: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
export type AttachLoginCommandOptions<TAccount extends AuthAccount = AuthAccount> = {
|
|
16
|
+
provider: AuthProvider<TAccount>;
|
|
17
|
+
store: TokenStore<TAccount>;
|
|
18
|
+
/** Default local OAuth callback port. Overridable per-invocation via `--callback-port`. */
|
|
19
|
+
preferredPort: number;
|
|
20
|
+
/** Walk up this many sequential ports if `preferredPort` is busy. Default: 5. */
|
|
21
|
+
portFallbackCount?: number;
|
|
22
|
+
/** Resolve the scope list to request from the runtime flags + read-only state. */
|
|
23
|
+
resolveScopes(ctx: {
|
|
24
|
+
readOnly: boolean;
|
|
25
|
+
flags: Record<string, unknown>;
|
|
26
|
+
}): string[];
|
|
27
|
+
renderSuccess(): string;
|
|
28
|
+
renderError(message: string): string;
|
|
29
|
+
/** Override the browser opener (tests). When omitted, `runOAuthFlow` imports `open`. */
|
|
30
|
+
openBrowser?(url: string): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Override the authorize-URL fallback callback that fires when the browser
|
|
33
|
+
* can't be opened (no `open` peer / opener throws). When omitted, the URL
|
|
34
|
+
* is written to stderr in machine-output mode (so the JSON / NDJSON
|
|
35
|
+
* envelope on stdout stays clean) and to stdout via `runOAuthFlow`'s
|
|
36
|
+
* default in human mode.
|
|
37
|
+
*/
|
|
38
|
+
onAuthorizeUrl?(url: string): void;
|
|
39
|
+
/** Called after the token is persisted. */
|
|
40
|
+
onSuccess(ctx: AttachLoginContext<TAccount>): void | Promise<void>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Attach `login` as a subcommand of `parent`. Wires the standard flag set
|
|
44
|
+
* (`--read-only`, `--callback-port`, `--json`, `--ndjson`) and drives
|
|
45
|
+
* `runOAuthFlow`. Returns the new `Command` so the consumer can chain
|
|
46
|
+
* `.description(...)` / `.option(...)` / `.addHelpText(...)` for additional
|
|
47
|
+
* flags or help text.
|
|
48
|
+
*
|
|
49
|
+
* Additional Commander options the consumer attaches to the returned command
|
|
50
|
+
* land on the same parsed options object Commander hands to the action, so
|
|
51
|
+
* `resolveScopes` and `onSuccess` see them via `flags`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function attachLoginCommand<TAccount extends AuthAccount>(parent: Command, options: AttachLoginCommandOptions<TAccount>): Command;
|
|
54
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvE,MAAM,MAAM,kBAAkB,CAAC,QAAQ,SAAS,WAAW,IAAI;IAC3D,OAAO,EAAE,QAAQ,CAAA;IACjB,8EAA8E;IAC9E,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC3B;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,yBAAyB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IAChF,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAChC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC3B,2FAA2F;IAC3F,aAAa,EAAE,MAAM,CAAA;IACrB,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,kFAAkF;IAClF,aAAa,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,MAAM,EAAE,CAAA;IACnF,aAAa,IAAI,MAAM,CAAA;IACvB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IACpC,wFAAwF;IACxF,WAAW,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC;;;;;;OAMG;IACH,cAAc,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,2CAA2C;IAC3C,SAAS,CAAC,GAAG,EAAE,kBAAkB,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACrE,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,SAAS,WAAW,EAC3D,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,GAC7C,OAAO,CAwCT"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { CliError } from '../errors.js';
|
|
2
|
+
import { runOAuthFlow } from './flow.js';
|
|
3
|
+
/**
|
|
4
|
+
* Attach `login` as a subcommand of `parent`. Wires the standard flag set
|
|
5
|
+
* (`--read-only`, `--callback-port`, `--json`, `--ndjson`) and drives
|
|
6
|
+
* `runOAuthFlow`. Returns the new `Command` so the consumer can chain
|
|
7
|
+
* `.description(...)` / `.option(...)` / `.addHelpText(...)` for additional
|
|
8
|
+
* flags or help text.
|
|
9
|
+
*
|
|
10
|
+
* Additional Commander options the consumer attaches to the returned command
|
|
11
|
+
* land on the same parsed options object Commander hands to the action, so
|
|
12
|
+
* `resolveScopes` and `onSuccess` see them via `flags`.
|
|
13
|
+
*/
|
|
14
|
+
export function attachLoginCommand(parent, options) {
|
|
15
|
+
return parent
|
|
16
|
+
.command('login')
|
|
17
|
+
.option('--read-only', 'Request read-only scopes')
|
|
18
|
+
.option('--callback-port <port>', 'Override the local OAuth callback port', parsePort)
|
|
19
|
+
.option('--json', 'Emit machine-readable JSON output')
|
|
20
|
+
.option('--ndjson', 'Emit machine-readable NDJSON output')
|
|
21
|
+
.action(async (cmd) => {
|
|
22
|
+
const { readOnly, callbackPort, json, ndjson, ...flags } = cmd;
|
|
23
|
+
const view = {
|
|
24
|
+
json: Boolean(json),
|
|
25
|
+
ndjson: Boolean(ndjson),
|
|
26
|
+
};
|
|
27
|
+
const machineOutput = view.json || view.ndjson;
|
|
28
|
+
const result = await runOAuthFlow({
|
|
29
|
+
provider: options.provider,
|
|
30
|
+
store: options.store,
|
|
31
|
+
scopes: options.resolveScopes({ readOnly: Boolean(readOnly), flags }),
|
|
32
|
+
readOnly: Boolean(readOnly),
|
|
33
|
+
flags,
|
|
34
|
+
preferredPort: callbackPort ?? options.preferredPort,
|
|
35
|
+
portFallbackCount: options.portFallbackCount,
|
|
36
|
+
renderSuccess: options.renderSuccess,
|
|
37
|
+
renderError: options.renderError,
|
|
38
|
+
openBrowser: options.openBrowser,
|
|
39
|
+
// In machine-output mode, route the fallback URL to stderr so
|
|
40
|
+
// the JSON / NDJSON envelope on stdout stays clean — the user
|
|
41
|
+
// can still see the URL if `open` is missing or throws. In
|
|
42
|
+
// human mode, leave it undefined so `runOAuthFlow`'s TTY
|
|
43
|
+
// default (stdout) fires. Consumer override wins either way.
|
|
44
|
+
onAuthorizeUrl: options.onAuthorizeUrl ??
|
|
45
|
+
(machineOutput
|
|
46
|
+
? (url) => {
|
|
47
|
+
process.stderr.write(`Open this URL in your browser:\n ${url}\n`);
|
|
48
|
+
}
|
|
49
|
+
: undefined),
|
|
50
|
+
});
|
|
51
|
+
await options.onSuccess({ account: result.account, view, flags });
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function parsePort(raw) {
|
|
55
|
+
const port = /^\d+$/.test(raw) ? Number(raw) : Number.NaN;
|
|
56
|
+
if (!Number.isFinite(port) || port > 65535) {
|
|
57
|
+
throw new CliError('AUTH_PORT_BIND_FAILED', `Invalid --callback-port '${raw}': expected an integer in [0..65535].`);
|
|
58
|
+
}
|
|
59
|
+
return port;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAwCxC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAC9B,MAAe,EACf,OAA4C;IAE5C,OAAO,MAAM;SACR,OAAO,CAAC,OAAO,CAAC;SAChB,MAAM,CAAC,aAAa,EAAE,0BAA0B,CAAC;SACjD,MAAM,CAAC,wBAAwB,EAAE,wCAAwC,EAAE,SAAS,CAAC;SACrF,MAAM,CAAC,QAAQ,EAAE,mCAAmC,CAAC;SACrD,MAAM,CAAC,UAAU,EAAE,qCAAqC,CAAC;SACzD,MAAM,CAAC,KAAK,EAAE,GAA4B,EAAE,EAAE;QAC3C,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,GAAG,CAAA;QAC9D,MAAM,IAAI,GAA0B;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;YACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC;SAC1B,CAAA;QACD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAA;QAC9C,MAAM,MAAM,GAAG,MAAM,YAAY,CAAW;YACxC,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;YACrE,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC;YAC3B,KAAK;YACL,aAAa,EAAG,YAAmC,IAAI,OAAO,CAAC,aAAa;YAC5E,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;YAC5C,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,8DAA8D;YAC9D,8DAA8D;YAC9D,2DAA2D;YAC3D,yDAAyD;YACzD,6DAA6D;YAC7D,cAAc,EACV,OAAO,CAAC,cAAc;gBACtB,CAAC,aAAa;oBACV,CAAC,CAAC,CAAC,GAAW,EAAE,EAAE;wBACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,GAAG,IAAI,CAAC,CAAA;oBACtE,CAAC;oBACH,CAAC,CAAC,SAAS,CAAC;SACvB,CAAC,CAAA;QACF,MAAM,OAAO,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACrE,CAAC,CAAC,CAAA;AACV,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAA;IACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QACzC,MAAM,IAAI,QAAQ,CACd,uBAAuB,EACvB,4BAA4B,GAAG,uCAAuC,CACzE,CAAA;IACL,CAAC;IACD,OAAO,IAAI,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { ViewOptions } from '../options.js';
|
|
3
|
+
import type { AuthAccount, TokenStore } from './types.js';
|
|
4
|
+
export type AttachLogoutContext<TAccount extends AuthAccount> = {
|
|
5
|
+
/** The account that was active immediately before `clear()` ran, or `null` if nothing was stored. */
|
|
6
|
+
account: TAccount | null;
|
|
7
|
+
view: Required<ViewOptions>;
|
|
8
|
+
/**
|
|
9
|
+
* Stripped per-CLI flags — the parsed options object with the standard
|
|
10
|
+
* registrar flags (`--json`, `--ndjson`) removed. Any consumer-attached
|
|
11
|
+
* `.option(...)` lands here (e.g. `--user <ref>` from a multi-user CLI).
|
|
12
|
+
*/
|
|
13
|
+
flags: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
export type AttachLogoutCommandOptions<TAccount extends AuthAccount = AuthAccount> = {
|
|
16
|
+
store: TokenStore<TAccount>;
|
|
17
|
+
/** Override the subcommand description. */
|
|
18
|
+
description?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Fires after `store.clear()` resolves. Use to surface keyring-fallback
|
|
21
|
+
* warnings or other CLI-specific follow-ups. Consumers in machine-output
|
|
22
|
+
* mode should route any extra prose to stderr to keep stdout parseable.
|
|
23
|
+
*/
|
|
24
|
+
onCleared?(ctx: AttachLogoutContext<TAccount>): void | Promise<void>;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Attach `logout` as a subcommand of `parent`. Snapshots the active account,
|
|
28
|
+
* calls `store.clear()`, emits a sensible default success line gated on
|
|
29
|
+
* `--json` / `--ndjson`, then invokes `onCleared` for follow-ups. Returns the
|
|
30
|
+
* new `Command` so the consumer can chain.
|
|
31
|
+
*/
|
|
32
|
+
export declare function attachLogoutCommand<TAccount extends AuthAccount = AuthAccount>(parent: Command, options: AttachLogoutCommandOptions<TAccount>): Command;
|
|
33
|
+
//# sourceMappingURL=logout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/auth/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEzD,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,IAAI;IAC5D,qGAAqG;IACrG,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAA;IACxB,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC3B;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,0BAA0B,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACjF,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC3B,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,SAAS,CAAC,CAAC,GAAG,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvE,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1E,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,GAC9C,OAAO,CAuBT"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { formatJson } from '../json.js';
|
|
2
|
+
/**
|
|
3
|
+
* Attach `logout` as a subcommand of `parent`. Snapshots the active account,
|
|
4
|
+
* calls `store.clear()`, emits a sensible default success line gated on
|
|
5
|
+
* `--json` / `--ndjson`, then invokes `onCleared` for follow-ups. Returns the
|
|
6
|
+
* new `Command` so the consumer can chain.
|
|
7
|
+
*/
|
|
8
|
+
export function attachLogoutCommand(parent, options) {
|
|
9
|
+
return parent
|
|
10
|
+
.command('logout')
|
|
11
|
+
.description(options.description ?? 'Remove the saved authentication token')
|
|
12
|
+
.option('--json', 'Emit machine-readable JSON output')
|
|
13
|
+
.option('--ndjson', 'Emit machine-readable NDJSON output')
|
|
14
|
+
.action(async (cmd) => {
|
|
15
|
+
const { json, ndjson, ...flags } = cmd;
|
|
16
|
+
const view = {
|
|
17
|
+
json: Boolean(json),
|
|
18
|
+
ndjson: Boolean(ndjson),
|
|
19
|
+
};
|
|
20
|
+
// Skip the keyring/file read when no callback consumes the snapshot.
|
|
21
|
+
const snapshot = options.onCleared ? await options.store.active() : null;
|
|
22
|
+
const account = snapshot?.account ?? null;
|
|
23
|
+
await options.store.clear();
|
|
24
|
+
if (view.json) {
|
|
25
|
+
console.log(formatJson({ ok: true }));
|
|
26
|
+
}
|
|
27
|
+
else if (!view.ndjson) {
|
|
28
|
+
console.log('✓ Logged out');
|
|
29
|
+
}
|
|
30
|
+
await options.onCleared?.({ account, view, flags });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/auth/logout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AA4BvC;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAC/B,MAAe,EACf,OAA6C;IAE7C,OAAO,MAAM;SACR,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,OAAO,CAAC,WAAW,IAAI,uCAAuC,CAAC;SAC3E,MAAM,CAAC,QAAQ,EAAE,mCAAmC,CAAC;SACrD,MAAM,CAAC,UAAU,EAAE,qCAAqC,CAAC;SACzD,MAAM,CAAC,KAAK,EAAE,GAA4B,EAAE,EAAE;QAC3C,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,GAAG,CAAA;QACtC,MAAM,IAAI,GAA0B;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;YACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC;SAC1B,CAAA;QACD,qEAAqE;QACrE,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QACxE,MAAM,OAAO,GAAG,QAAQ,EAAE,OAAO,IAAI,IAAI,CAAA;QACzC,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QAC3B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QACzC,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;QAC/B,CAAC;QACD,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;AACV,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { ViewOptions } from '../options.js';
|
|
3
|
+
import type { AuthAccount, TokenStore } from './types.js';
|
|
4
|
+
export type AttachStatusContext<TAccount extends AuthAccount> = {
|
|
5
|
+
account: TAccount;
|
|
6
|
+
view: Required<ViewOptions>;
|
|
7
|
+
/**
|
|
8
|
+
* Stripped per-CLI flags — the parsed options object with the standard
|
|
9
|
+
* registrar flags (`--json`, `--ndjson`) removed. Any consumer-attached
|
|
10
|
+
* `.option(...)` lands here (e.g. `--full`, `--user <ref>`).
|
|
11
|
+
*/
|
|
12
|
+
flags: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
export type AttachStatusCommandOptions<TAccount extends AuthAccount = AuthAccount> = {
|
|
15
|
+
store: TokenStore<TAccount>;
|
|
16
|
+
description?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional live probe. Receives the stored account + token and returns the
|
|
19
|
+
* canonical account to render — typically a fresh API call that confirms
|
|
20
|
+
* the token still works. Throws (e.g. a `CliError('NO_TOKEN', …)` translation
|
|
21
|
+
* of a 401) propagate to the top-level handler.
|
|
22
|
+
*/
|
|
23
|
+
fetchLive?(ctx: {
|
|
24
|
+
account: TAccount;
|
|
25
|
+
token: string;
|
|
26
|
+
view: Required<ViewOptions>;
|
|
27
|
+
flags: Record<string, unknown>;
|
|
28
|
+
}): Promise<TAccount>;
|
|
29
|
+
/**
|
|
30
|
+
* Human-mode renderer. May return a single string or an array of lines;
|
|
31
|
+
* lines are joined with `\n` on output.
|
|
32
|
+
*/
|
|
33
|
+
renderText(ctx: AttachStatusContext<TAccount>): string | readonly string[];
|
|
34
|
+
/**
|
|
35
|
+
* Machine-mode payload. Returned value is serialized as-is via
|
|
36
|
+
* `formatJson` / `formatNdjson`. Defaults to the account object. Only
|
|
37
|
+
* invoked under `--json` / `--ndjson`.
|
|
38
|
+
*/
|
|
39
|
+
renderJson?(ctx: {
|
|
40
|
+
account: TAccount;
|
|
41
|
+
flags: Record<string, unknown>;
|
|
42
|
+
}): unknown;
|
|
43
|
+
/**
|
|
44
|
+
* Called when `store.active()` returns null. Default behaviour throws
|
|
45
|
+
* `CliError('NOT_AUTHENTICATED', …)`.
|
|
46
|
+
*/
|
|
47
|
+
onNotAuthenticated?(ctx: {
|
|
48
|
+
view: Required<ViewOptions>;
|
|
49
|
+
flags: Record<string, unknown>;
|
|
50
|
+
}): void | Promise<void>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Attach `status` as a subcommand of `parent`. Reads `store.active()`, optionally
|
|
54
|
+
* confirms via `fetchLive`, then dispatches to `renderText` (human) or
|
|
55
|
+
* `renderJson` (machine). Returns the new `Command` so the consumer can chain.
|
|
56
|
+
*/
|
|
57
|
+
export declare function attachStatusCommand<TAccount extends AuthAccount = AuthAccount>(parent: Command, options: AttachStatusCommandOptions<TAccount>): Command;
|
|
58
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/auth/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEzD,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,IAAI;IAC5D,OAAO,EAAE,QAAQ,CAAA;IACjB,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC3B;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,0BAA0B,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACjF,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;OAKG;IACH,SAAS,CAAC,CAAC,GAAG,EAAE;QACZ,OAAO,EAAE,QAAQ,CAAA;QACjB,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;QAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACjC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACrB;;;OAGG;IACH,UAAU,CAAC,GAAG,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;IAC1E;;;;OAIG;IACH,UAAU,CAAC,CAAC,GAAG,EAAE;QAAE,OAAO,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAA;IAChF;;;OAGG;IACH,kBAAkB,CAAC,CAAC,GAAG,EAAE;QACrB,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;QAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACjC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B,CAAA;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1E,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,GAC9C,OAAO,CA8CT"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { CliError } from '../errors.js';
|
|
2
|
+
import { formatJson, formatNdjson } from '../json.js';
|
|
3
|
+
/**
|
|
4
|
+
* Attach `status` as a subcommand of `parent`. Reads `store.active()`, optionally
|
|
5
|
+
* confirms via `fetchLive`, then dispatches to `renderText` (human) or
|
|
6
|
+
* `renderJson` (machine). Returns the new `Command` so the consumer can chain.
|
|
7
|
+
*/
|
|
8
|
+
export function attachStatusCommand(parent, options) {
|
|
9
|
+
return parent
|
|
10
|
+
.command('status')
|
|
11
|
+
.description(options.description ?? 'Show the current authentication status')
|
|
12
|
+
.option('--json', 'Emit machine-readable JSON output')
|
|
13
|
+
.option('--ndjson', 'Emit machine-readable NDJSON output')
|
|
14
|
+
.action(async (cmd) => {
|
|
15
|
+
const { json, ndjson, ...flags } = cmd;
|
|
16
|
+
const view = {
|
|
17
|
+
json: Boolean(json),
|
|
18
|
+
ndjson: Boolean(ndjson),
|
|
19
|
+
};
|
|
20
|
+
const snapshot = await options.store.active();
|
|
21
|
+
if (!snapshot) {
|
|
22
|
+
if (options.onNotAuthenticated) {
|
|
23
|
+
await options.onNotAuthenticated({ view, flags });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
throw new CliError('NOT_AUTHENTICATED', 'Not signed in.');
|
|
27
|
+
}
|
|
28
|
+
const account = options.fetchLive
|
|
29
|
+
? await options.fetchLive({
|
|
30
|
+
account: snapshot.account,
|
|
31
|
+
token: snapshot.token,
|
|
32
|
+
view,
|
|
33
|
+
flags,
|
|
34
|
+
})
|
|
35
|
+
: snapshot.account;
|
|
36
|
+
if (view.json) {
|
|
37
|
+
const payload = options.renderJson
|
|
38
|
+
? options.renderJson({ account, flags })
|
|
39
|
+
: account;
|
|
40
|
+
console.log(formatJson(payload));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (view.ndjson) {
|
|
44
|
+
const payload = options.renderJson
|
|
45
|
+
? options.renderJson({ account, flags })
|
|
46
|
+
: account;
|
|
47
|
+
console.log(formatNdjson([payload]));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const text = options.renderText({ account, view, flags });
|
|
51
|
+
const lines = typeof text === 'string' ? [text] : text;
|
|
52
|
+
for (const line of lines)
|
|
53
|
+
console.log(line);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/auth/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAmDrD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAC/B,MAAe,EACf,OAA6C;IAE7C,OAAO,MAAM;SACR,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,OAAO,CAAC,WAAW,IAAI,wCAAwC,CAAC;SAC5E,MAAM,CAAC,QAAQ,EAAE,mCAAmC,CAAC;SACrD,MAAM,CAAC,UAAU,EAAE,qCAAqC,CAAC;SACzD,MAAM,CAAC,KAAK,EAAE,GAA4B,EAAE,EAAE;QAC3C,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,GAAG,CAAA;QACtC,MAAM,IAAI,GAA0B;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;YACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC;SAC1B,CAAA;QACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;QAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;gBAC7B,MAAM,OAAO,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;gBACjD,OAAM;YACV,CAAC;YACD,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAA;QAC7D,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS;YAC7B,CAAC,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC;gBACpB,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,IAAI;gBACJ,KAAK;aACR,CAAC;YACJ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAA;QACtB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU;gBAC9B,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;gBACxC,CAAC,CAAC,OAAO,CAAA;YACb,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAA;YAChC,OAAM;QACV,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU;gBAC9B,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;gBACxC,CAAC,CAAC,OAAO,CAAA;YACb,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;YACpC,OAAM;QACV,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QACzD,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QACtD,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;AACV,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { AuthAccount, TokenStore } from './types.js';
|
|
3
|
+
export type AttachTokenViewCommandOptions<TAccount extends AuthAccount = AuthAccount> = {
|
|
4
|
+
store: TokenStore<TAccount>;
|
|
5
|
+
/** Subcommand name. Defaults to `'token'`. Pass `'view'` to nest under an existing `token` group. */
|
|
6
|
+
name?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
/**
|
|
9
|
+
* When set, refuses to print if `process.env[envVarName]` is populated.
|
|
10
|
+
* Guards against disclosing a token the CLI didn't manage — the env var
|
|
11
|
+
* typically takes precedence over the stored token elsewhere in the CLI,
|
|
12
|
+
* so printing the stored token here would be misleading at best.
|
|
13
|
+
*/
|
|
14
|
+
envVarName?: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Attach a "print the saved token" subcommand to `parent`. Writes the bare
|
|
18
|
+
* token to stdout with no envelope so the output is pipe-safe (e.g. `eval $(td
|
|
19
|
+
* auth token)`). Throws `CliError('TOKEN_FROM_ENV', …)` when `envVarName` is
|
|
20
|
+
* set and the env var is populated, and `CliError('NOT_AUTHENTICATED', …)`
|
|
21
|
+
* when no token is stored. Returns the new `Command` for chaining.
|
|
22
|
+
*/
|
|
23
|
+
export declare function attachTokenViewCommand<TAccount extends AuthAccount = AuthAccount>(parent: Command, options: AttachTokenViewCommandOptions<TAccount>): Command;
|
|
24
|
+
//# sourceMappingURL=token-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-view.d.ts","sourceRoot":"","sources":["../../src/auth/token-view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGxC,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEzD,MAAM,MAAM,6BAA6B,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACpF,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC3B,qGAAqG;IACrG,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC7E,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,6BAA6B,CAAC,QAAQ,CAAC,GACjD,OAAO,CAwBT"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CliError } from '../errors.js';
|
|
2
|
+
import { isStdoutTTY } from '../terminal.js';
|
|
3
|
+
/**
|
|
4
|
+
* Attach a "print the saved token" subcommand to `parent`. Writes the bare
|
|
5
|
+
* token to stdout with no envelope so the output is pipe-safe (e.g. `eval $(td
|
|
6
|
+
* auth token)`). Throws `CliError('TOKEN_FROM_ENV', …)` when `envVarName` is
|
|
7
|
+
* set and the env var is populated, and `CliError('NOT_AUTHENTICATED', …)`
|
|
8
|
+
* when no token is stored. Returns the new `Command` for chaining.
|
|
9
|
+
*/
|
|
10
|
+
export function attachTokenViewCommand(parent, options) {
|
|
11
|
+
return parent
|
|
12
|
+
.command(options.name ?? 'token')
|
|
13
|
+
.description(options.description ?? 'Print the saved authentication token')
|
|
14
|
+
.action(async () => {
|
|
15
|
+
if (options.envVarName && process.env[options.envVarName]) {
|
|
16
|
+
throw new CliError('TOKEN_FROM_ENV', `Refusing to print: token is being read from $${options.envVarName}, not the saved store.`, {
|
|
17
|
+
hints: [
|
|
18
|
+
`Unset ${options.envVarName} to view the stored token.`,
|
|
19
|
+
'The env var takes precedence over saved tokens; printing it would disclose a secret the CLI did not manage.',
|
|
20
|
+
],
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const snapshot = await options.store.active();
|
|
24
|
+
if (!snapshot) {
|
|
25
|
+
throw new CliError('NOT_AUTHENTICATED', 'Not signed in.');
|
|
26
|
+
}
|
|
27
|
+
process.stdout.write(snapshot.token);
|
|
28
|
+
if (isStdoutTTY())
|
|
29
|
+
process.stdout.write('\n');
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=token-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-view.js","sourceRoot":"","sources":["../../src/auth/token-view.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAiB5C;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAClC,MAAe,EACf,OAAgD;IAEhD,OAAO,MAAM;SACR,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC;SAChC,WAAW,CAAC,OAAO,CAAC,WAAW,IAAI,sCAAsC,CAAC;SAC1E,MAAM,CAAC,KAAK,IAAI,EAAE;QACf,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,QAAQ,CACd,gBAAgB,EAChB,gDAAgD,OAAO,CAAC,UAAU,wBAAwB,EAC1F;gBACI,KAAK,EAAE;oBACH,SAAS,OAAO,CAAC,UAAU,4BAA4B;oBACvD,6GAA6G;iBAChH;aACJ,CACJ,CAAA;QACL,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;QAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAA;QAC7D,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACpC,IAAI,WAAW,EAAE;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjD,CAAC,CAAC,CAAA;AACV,CAAC"}
|
package/dist/auth/types.d.ts
CHANGED
|
@@ -71,11 +71,14 @@ export type AuthProvider<TAccount extends AuthAccount = AuthAccount> = {
|
|
|
71
71
|
* single-user case.
|
|
72
72
|
*/
|
|
73
73
|
export type TokenStore<TAccount extends AuthAccount = AuthAccount> = {
|
|
74
|
+
/** The currently signed-in identity, or `null` when nothing is stored. */
|
|
74
75
|
active(): Promise<{
|
|
75
76
|
token: string;
|
|
76
77
|
account: TAccount;
|
|
77
78
|
} | null>;
|
|
79
|
+
/** Persist `token` for `account`, replacing any previous entry. Throw `CliError` to surface a typed failure; any other thrown value is wrapped as `AUTH_STORE_WRITE_FAILED`. */
|
|
78
80
|
set(account: TAccount, token: string): Promise<void>;
|
|
81
|
+
/** Remove the active credential. No-op when nothing is stored. */
|
|
79
82
|
clear(): Promise<void>;
|
|
80
83
|
};
|
|
81
84
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/auth/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IACxB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACrE,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yFAAyF;IACzF,OAAO,CAAC,EAAE,QAAQ,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACnE,8EAA8E;IAC9E,OAAO,CAAC,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACrD,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC1D,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAA;IACrE,iEAAiE;IACjE,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACzD,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACjE,MAAM,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,QAAQ,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IAC9D,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB,CAAA"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IACxB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACrE,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yFAAyF;IACzF,OAAO,CAAC,EAAE,QAAQ,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACnE,8EAA8E;IAC9E,OAAO,CAAC,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACrD,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC1D,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAA;IACrE,iEAAiE;IACjE,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACzD,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACjE,0EAA0E;IAC1E,MAAM,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,QAAQ,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IAC9D,gLAAgL;IAChL,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,kEAAkE;IAClE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB,CAAA"}
|