@doist/cli-core 0.11.0 → 0.12.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 CHANGED
@@ -1,3 +1,9 @@
1
+ ## [0.12.0](https://github.com/Doist/cli-core/compare/v0.11.0...v0.12.0) (2026-05-14)
2
+
3
+ ### Features
4
+
5
+ * **auth:** multi-user TokenStore contract ([#23](https://github.com/Doist/cli-core/issues/23)) ([f83310a](https://github.com/Doist/cli-core/commit/f83310a3dec62636884dab6bea2aed3c89aab502))
6
+
1
7
  ## [0.11.0](https://github.com/Doist/cli-core/compare/v0.10.0...v0.11.0) (2026-05-12)
2
8
 
3
9
  ### 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 | Purpose |
16
- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17
- | `auth` (subpath) | `attachLoginCommand`, `attachLogoutCommand`, `attachStatusCommand`, `attachTokenViewCommand`, `runOAuthFlow`, `createPkceProvider`, PKCE helpers, `AuthProvider` / `TokenStore` types, `AttachLogoutRevokeContext` | OAuth runtime plus the Commander attachers for `<cli> [auth] login` / `logout` / `status` / `token`. `attachLogoutCommand` accepts an optional `revokeToken` hook for best-effort server-side token revocation. 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). |
15
+ | Module | Key exports | Purpose |
16
+ | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17
+ | `auth` (subpath) | `attachLoginCommand`, `attachLogoutCommand`, `attachStatusCommand`, `attachTokenViewCommand`, `runOAuthFlow`, `createPkceProvider`, PKCE helpers, `AuthProvider` / `TokenStore` / `AccountRef` types, `AttachLogoutRevokeContext` | OAuth runtime plus the Commander attachers for `<cli> [auth] login` / `logout` / `status` / `token`. `attachLogoutCommand` accepts an optional `revokeToken` hook for best-effort server-side token revocation. 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 (single-user store implements `list` / `setDefault` trivially against the one account). `logout` / `status` / `token` always attach `--user <ref>` and thread the parsed ref to `store.active(ref)` (and `store.clear(ref)` on `logout`). `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`, `stripUserFlag`, `createGlobalArgsStore`, `createAccessibleGate`, `createSpinnerGate`, `getProgressJsonlPath`, `isProgressJsonlEnabled` | Parse well-known global flags (`--json`, `--ndjson`, `--quiet`, `--verbose`, `--accessible`, `--no-spinner`, `--progress-jsonl`, `--user <ref>`) and derive predicates from them. `stripUserFlag` removes `--user` tokens from argv so the cleaned array can be forwarded to Commander when the flag has no root-program attachment. |
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
 
@@ -217,7 +217,7 @@ attachTokenViewCommand<Account>(auth, {
217
217
 
218
218
  `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.
219
219
 
220
- 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 `revokeToken` / `onCleared` / `renderText` / `fetchLive` / `renderJson` / `onNotAuthenticated`.
220
+ Both attachers strip the standard `--json` / `--ndjson` / `--user` 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('--full')` and read it in `revokeToken` / `onCleared` / `renderText` / `fetchLive` / `renderJson` / `onNotAuthenticated`.
221
221
 
222
222
  `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.
223
223
 
@@ -236,33 +236,80 @@ Under `--json` / `--ndjson`, the authorize-URL fallback (printed when `open` is
236
236
 
237
237
  #### Implementing `TokenStore`
238
238
 
239
- A single-user, config-file backed store using cli-core's own config helpers:
239
+ `TokenStore` is uniformly multi-user-shaped — single-user CLIs implement `list` / `setDefault` trivially against their one stored account. There is no separate single-user contract.
240
240
 
241
241
  ```ts
242
- import { getConfigPath, readConfig, updateConfig, writeConfig } from '@doist/cli-core'
243
- import type { TokenStore } from '@doist/cli-core/auth'
242
+ import { CliError, getConfigPath, readConfig, updateConfig, writeConfig } from '@doist/cli-core'
243
+ import type { AccountRef, TokenStore } from '@doist/cli-core/auth'
244
244
 
245
245
  type Account = { id: string; label?: string; email: string }
246
246
  type StoredAuth = { account: Account; token: string }
247
247
 
248
- const configPath = getConfigPath('todoist-cli')
248
+ const configPath = getConfigPath('outline-cli')
249
+
250
+ function matches(account: Account, ref: AccountRef): boolean {
251
+ return account.id === ref || account.label === ref
252
+ }
249
253
 
254
+ // Single-user impl. Honour `ref` on every method — returning null on a miss
255
+ // is what lets the attachers translate `<cmd> --user wrong` into a typed
256
+ // `ACCOUNT_NOT_FOUND` error instead of a misleading success or
257
+ // `NOT_AUTHENTICATED`.
250
258
  export const tokenStore: TokenStore<Account> = {
251
- async active() {
259
+ async active(ref?: AccountRef) {
252
260
  const config = await readConfig<{ auth?: StoredAuth }>(configPath)
253
- return config.auth ? { account: config.auth.account, token: config.auth.token } : null
261
+ if (!config.auth) return null
262
+ if (ref !== undefined && !matches(config.auth.account, ref)) return null
263
+ return { account: config.auth.account, token: config.auth.token }
254
264
  },
255
265
  async set(account, token) {
256
266
  await updateConfig<{ auth: StoredAuth }>(configPath, { auth: { account, token } })
257
267
  },
258
- async clear() {
259
- const { auth: _drop, ...rest } = await readConfig<{ auth?: StoredAuth }>(configPath)
268
+ async clear(ref?: AccountRef) {
269
+ const config = await readConfig<{ auth?: StoredAuth }>(configPath)
270
+ if (!config.auth) return
271
+ if (ref !== undefined && !matches(config.auth.account, ref)) return
272
+ const { auth: _drop, ...rest } = config
260
273
  await writeConfig(configPath, rest)
261
274
  },
275
+ async list() {
276
+ const snapshot = await this.active()
277
+ return snapshot ? [{ account: snapshot.account, isDefault: true }] : []
278
+ },
279
+ async setDefault(ref: AccountRef) {
280
+ const snapshot = await this.active()
281
+ if (!snapshot || !matches(snapshot.account, ref)) {
282
+ throw new CliError('ACCOUNT_NOT_FOUND', `No stored account matches "${ref}".`)
283
+ }
284
+ // Single-user store — already the default.
285
+ },
262
286
  }
263
287
  ```
264
288
 
265
- 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).
289
+ For multi-account storage (OS keychain, per-user config slots, …), implement the same five methods against your backend and honour `ref` on `active` / `clear` / `setDefault`. `AccountRef` is an opaque `string` cli-core does not constrain matching semantics (id-exact, email-case-insensitive, label, …). The store impl owns that.
290
+
291
+ #### `--user <ref>` and multi-user wiring
292
+
293
+ The three account-touching attachers (`attachLogoutCommand` / `attachStatusCommand` / `attachTokenViewCommand`) always attach `--user <ref>` on their subcommand. `attachLogoutCommand` threads the parsed ref to both `store.active(ref)` and `store.clear(ref)`; `attachStatusCommand` and `attachTokenViewCommand` only call `store.active(ref)`. When `--user` is supplied but `store.active(ref)` returns `null`, each attacher throws `CliError('ACCOUNT_NOT_FOUND', …)` so the user sees a typed miss rather than `NOT_AUTHENTICATED` or a silent `✓ Logged out`. Single-user stores returning `null` for a non-matching ref is the supported way to feed this guard.
294
+
295
+ For pre-subcommand `--user` (`<cli> --user alice some-cmd`) that should apply to non-auth commands too, parse it globally and strip from argv before handing to Commander:
296
+
297
+ ```ts
298
+ import { parseGlobalArgs, stripUserFlag } from '@doist/cli-core'
299
+
300
+ const args = parseGlobalArgs(process.argv.slice(2))
301
+ console.log(args.user) // 'alice' | undefined
302
+
303
+ await program.parseAsync([
304
+ process.argv[0],
305
+ process.argv[1],
306
+ ...stripUserFlag(process.argv.slice(2)),
307
+ ])
308
+ ```
309
+
310
+ Account-selection resolvers (env > `--user` > default > single-only > error), `account list`, and `account use` subcommands stay per-CLI for now — cli-core ships only the contract until at least one consumer has shipped these end-to-end.
311
+
312
+ `ACCOUNT_NOT_FOUND` is thrown by the account-touching attachers when `--user <ref>` was supplied but `store.active(ref)` returned `null`. `NO_ACCOUNT_SELECTED` is reserved for consumer-thrown resolver failures (multiple accounts stored, no default, no `--user`); cli-core does not throw it itself.
266
313
 
267
314
  #### Custom `AuthProvider` (non-PKCE flows)
268
315
 
@@ -305,15 +352,17 @@ The `handshake` is shared mutable state across hooks. `runOAuthFlow` folds the r
305
352
 
306
353
  Every failure in this subpath surfaces as a `CliError`:
307
354
 
308
- | Code | Cause |
309
- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
310
- | `AUTH_OAUTH_FAILED` | Provider returned `?error=...`, the flow was aborted via `signal`, or the callback server stopped before completion. |
311
- | `AUTH_CALLBACK_TIMEOUT` | No valid callback within `timeoutMs` (default 3 minutes). |
312
- | `AUTH_PORT_BIND_FAILED` | Could not bind any port in `[preferredPort, preferredPort + portFallbackCount]`, or `--callback-port` was out of range. |
313
- | `AUTH_TOKEN_EXCHANGE_FAILED` | Token endpoint network error, non-2xx response, non-JSON body, or missing `access_token`. |
314
- | `AUTH_STORE_WRITE_FAILED` | `TokenStore.set` threw a non-`CliError`. (`CliError`s thrown from `set` propagate unchanged.) |
315
- | `NOT_AUTHENTICATED` | `status` / `token` ran with an empty `TokenStore` (and no `onNotAuthenticated` callback for `status`). Default message: `'Not signed in.'`. |
316
- | `TOKEN_FROM_ENV` | `attachTokenViewCommand` refused to print: `envVarName` was set and the env var is populated. |
355
+ | Code | Cause |
356
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
357
+ | `AUTH_OAUTH_FAILED` | Provider returned `?error=...`, the flow was aborted via `signal`, or the callback server stopped before completion. |
358
+ | `AUTH_CALLBACK_TIMEOUT` | No valid callback within `timeoutMs` (default 3 minutes). |
359
+ | `AUTH_PORT_BIND_FAILED` | Could not bind any port in `[preferredPort, preferredPort + portFallbackCount]`, or `--callback-port` was out of range. |
360
+ | `AUTH_TOKEN_EXCHANGE_FAILED` | Token endpoint network error, non-2xx response, non-JSON body, or missing `access_token`. |
361
+ | `AUTH_STORE_WRITE_FAILED` | `TokenStore.set` threw a non-`CliError`. (`CliError`s thrown from `set` propagate unchanged.) |
362
+ | `NOT_AUTHENTICATED` | `status` / `token` ran with an empty `TokenStore` (and no `onNotAuthenticated` callback for `status`). Default message: `'Not signed in.'`. |
363
+ | `TOKEN_FROM_ENV` | `attachTokenViewCommand` refused to print: `envVarName` was set and the env var is populated. |
364
+ | `NO_ACCOUNT_SELECTED` | Reserved for consumer-thrown resolver failures when multiple accounts are stored without a default and no `--user` was supplied. |
365
+ | `ACCOUNT_NOT_FOUND` | `logout` / `status` / `token` were invoked with `--user <ref>` but `store.active(ref)` returned `null`. Also reserved for consumer resolvers when a ref doesn't match any stored account. |
317
366
 
318
367
  The consumer's top-level error handler formats and exits.
319
368
 
@@ -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' | 'NOT_AUTHENTICATED' | 'TOKEN_FROM_ENV';
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' | 'NO_ACCOUNT_SELECTED' | 'ACCOUNT_NOT_FOUND';
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,GACzB,mBAAmB,GACnB,gBAAgB,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,GAChB,qBAAqB,GACrB,mBAAmB,CAAA"}
@@ -13,5 +13,5 @@ export { DEFAULT_VERIFIER_ALPHABET, deriveChallenge, generateState, generateVeri
13
13
  export type { GenerateVerifierOptions } from './pkce.js';
14
14
  export { createPkceProvider } from './providers/pkce.js';
15
15
  export type { PkceLazyString, PkceProviderOptions } from './providers/pkce.js';
16
- export type { AuthAccount, AuthorizeInput, AuthorizeResult, AuthProvider, ExchangeInput, ExchangeResult, PrepareInput, PrepareResult, TokenStore, ValidateInput, } from './types.js';
16
+ export type { AccountRef, AuthAccount, AuthorizeInput, AuthorizeResult, AuthProvider, ExchangeInput, ExchangeResult, PrepareInput, PrepareResult, TokenStore, ValidateInput, } from './types.js';
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -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,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,EACR,0BAA0B,EAC1B,mBAAmB,EACnB,yBAAyB,GAC5B,MAAM,aAAa,CAAA;AACpB,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"}
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,EACR,0BAA0B,EAC1B,mBAAmB,EACnB,yBAAyB,GAC5B,MAAM,aAAa,CAAA;AACpB,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,UAAU,EACV,WAAW,EACX,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,GAChB,MAAM,YAAY,CAAA"}
@@ -4,12 +4,9 @@ import type { AuthAccount, TokenStore } from './types.js';
4
4
  export type AttachLogoutContext<TAccount extends AuthAccount> = {
5
5
  /** The account that was active immediately before `clear()` ran, or `null` if nothing was stored. */
6
6
  account: TAccount | null;
7
+ /** `--json` / `--ndjson` flag values, both present (defaulted to `false`). */
7
8
  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
- */
9
+ /** Consumer-attached options. The registrar flags (`--json`, `--ndjson`, `--user`) are stripped. */
13
10
  flags: Record<string, unknown>;
14
11
  };
15
12
  export type AttachLogoutRevokeContext<TAccount extends AuthAccount> = Omit<AttachLogoutContext<TAccount>, 'account'> & {
@@ -1 +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,yBAAyB,CAAC,QAAQ,SAAS,WAAW,IAAI,IAAI,CACtE,mBAAmB,CAAC,QAAQ,CAAC,EAC7B,SAAS,CACZ,GAAG;IACA,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,OAAO,EAAE,QAAQ,CAAA;CACpB,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;;;;;;OAMG;IACH,WAAW,CAAC,CAAC,GAAG,EAAE,yBAAyB,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5E;;;;OAIG;IACH,SAAS,CAAC,CAAC,GAAG,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvE,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1E,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,GAC9C,OAAO,CA2CT"}
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;AAGzD,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,IAAI;IAC5D,qGAAqG;IACrG,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAA;IACxB,8EAA8E;IAC9E,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC3B,oGAAoG;IACpG,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,yBAAyB,CAAC,QAAQ,SAAS,WAAW,IAAI,IAAI,CACtE,mBAAmB,CAAC,QAAQ,CAAC,EAC7B,SAAS,CACZ,GAAG;IACA,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,OAAO,EAAE,QAAQ,CAAA;CACpB,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;;;;;;OAMG;IACH,WAAW,CAAC,CAAC,GAAG,EAAE,yBAAyB,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5E;;;;OAIG;IACH,SAAS,CAAC,CAAC,GAAG,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvE,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1E,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,GAC9C,OAAO,CAkDT"}
@@ -1,4 +1,5 @@
1
1
  import { formatJson } from '../json.js';
2
+ import { attachUserFlag, extractUserRef, requireSnapshotForRef } from './user-flag.js';
2
3
  /**
3
4
  * Attach `logout` as a subcommand of `parent`. Snapshots the active session
4
5
  * (only when a hook needs it), calls `store.clear()`, optionally awaits
@@ -7,30 +8,38 @@ import { formatJson } from '../json.js';
7
8
  * follow-ups. Returns the new `Command` so the consumer can chain.
8
9
  */
9
10
  export function attachLogoutCommand(parent, options) {
10
- return parent
11
+ const command = parent
11
12
  .command('logout')
12
13
  .description(options.description ?? 'Remove the saved authentication token')
13
14
  .option('--json', 'Emit machine-readable JSON output')
14
- .option('--ndjson', 'Emit machine-readable NDJSON output')
15
- .action(async (cmd) => {
16
- const { json, ndjson, ...flags } = cmd;
15
+ .option('--ndjson', 'Emit machine-readable NDJSON output');
16
+ return attachUserFlag(command).action(async (cmd) => {
17
+ const { json, ndjson, user: _user, ...flags } = cmd;
17
18
  const view = {
18
19
  json: Boolean(json),
19
20
  ndjson: Boolean(ndjson),
20
21
  };
21
- // Skip the keyring/file read when no callback consumes the snapshot.
22
- const needsSnapshot = Boolean(options.revokeToken || options.onCleared);
22
+ const ref = extractUserRef(cmd);
23
+ // Explicit ref must surface a typed miss before `clear()` runs
24
+ // `clear(ref)` is contractually a no-op on miss, so otherwise
25
+ // `logout --user mistake` would print `✓ Logged out`.
26
+ const needsSnapshot = ref !== undefined || Boolean(options.revokeToken || options.onCleared);
23
27
  let snapshot = null;
24
28
  if (needsSnapshot) {
25
- try {
26
- snapshot = await options.store.active();
29
+ if (ref !== undefined) {
30
+ snapshot = await requireSnapshotForRef(options.store, ref);
27
31
  }
28
- catch {
29
- // Snapshot lookup failures must not block local clear.
32
+ else {
33
+ try {
34
+ snapshot = await options.store.active(ref);
35
+ }
36
+ catch {
37
+ // Snapshot lookup failures must not block local clear.
38
+ }
30
39
  }
31
40
  }
32
41
  const account = snapshot?.account ?? null;
33
- await options.store.clear();
42
+ await options.store.clear(ref);
34
43
  if (options.revokeToken && snapshot) {
35
44
  try {
36
45
  await options.revokeToken({
@@ -1 +1 @@
1
- {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/auth/logout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AA8CvC;;;;;;GAMG;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,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAAA;QACvE,IAAI,QAAQ,GAAgD,IAAI,CAAA;QAChE,IAAI,aAAa,EAAE,CAAC;YAChB,IAAI,CAAC;gBACD,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;YAC3C,CAAC;YAAC,MAAM,CAAC;gBACL,uDAAuD;YAC3D,CAAC;QACL,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,EAAE,OAAO,IAAI,IAAI,CAAA;QACzC,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QAC3B,IAAI,OAAO,CAAC,WAAW,IAAI,QAAQ,EAAE,CAAC;YAClC,IAAI,CAAC;gBACD,MAAM,OAAO,CAAC,WAAW,CAAC;oBACtB,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,OAAO,EAAE,QAAQ,CAAC,OAAO;oBACzB,IAAI;oBACJ,KAAK;iBACR,CAAC,CAAA;YACN,CAAC;YAAC,MAAM,CAAC;gBACL,oEAAoE;YACxE,CAAC;QACL,CAAC;QACD,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"}
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/auth/logout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAGvC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAyCtF;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAC/B,MAAe,EACf,OAA6C;IAE7C,MAAM,OAAO,GAAG,MAAM;SACjB,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,CAAA;IAC9D,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,GAA4B,EAAE,EAAE;QACzE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,GAAG,CAAA;QACnD,MAAM,IAAI,GAA0B;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;YACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC;SAC1B,CAAA;QACD,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;QAC/B,iEAAiE;QACjE,8DAA8D;QAC9D,sDAAsD;QACtD,MAAM,aAAa,GAAG,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAAA;QAC5F,IAAI,QAAQ,GAAgD,IAAI,CAAA;QAChE,IAAI,aAAa,EAAE,CAAC;YAChB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACpB,QAAQ,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YAC9D,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC;oBACD,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;gBAC9C,CAAC;gBAAC,MAAM,CAAC;oBACL,uDAAuD;gBAC3D,CAAC;YACL,CAAC;QACL,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,EAAE,OAAO,IAAI,IAAI,CAAA;QACzC,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9B,IAAI,OAAO,CAAC,WAAW,IAAI,QAAQ,EAAE,CAAC;YAClC,IAAI,CAAC;gBACD,MAAM,OAAO,CAAC,WAAW,CAAC;oBACtB,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,OAAO,EAAE,QAAQ,CAAC,OAAO;oBACzB,IAAI;oBACJ,KAAK;iBACR,CAAC,CAAA;YACN,CAAC;YAAC,MAAM,CAAC;gBACL,oEAAoE;YACxE,CAAC;QACL,CAAC;QACD,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;AACN,CAAC"}
@@ -3,12 +3,9 @@ import type { ViewOptions } from '../options.js';
3
3
  import type { AuthAccount, TokenStore } from './types.js';
4
4
  export type AttachStatusContext<TAccount extends AuthAccount> = {
5
5
  account: TAccount;
6
+ /** `--json` / `--ndjson` flag values, both present (defaulted to `false`). */
6
7
  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
- */
8
+ /** Consumer-attached options (e.g. `--full`). The registrar flags (`--json`, `--ndjson`, `--user`) are stripped. */
12
9
  flags: Record<string, unknown>;
13
10
  };
14
11
  export type AttachStatusCommandOptions<TAccount extends AuthAccount = AuthAccount> = {
@@ -23,6 +20,7 @@ export type AttachStatusCommandOptions<TAccount extends AuthAccount = AuthAccoun
23
20
  fetchLive?(ctx: {
24
21
  account: TAccount;
25
22
  token: string;
23
+ /** `--json` / `--ndjson` flag values, both present (defaulted to `false`). */
26
24
  view: Required<ViewOptions>;
27
25
  flags: Record<string, unknown>;
28
26
  }): Promise<TAccount>;
@@ -45,6 +43,7 @@ export type AttachStatusCommandOptions<TAccount extends AuthAccount = AuthAccoun
45
43
  * `CliError('NOT_AUTHENTICATED', …)`.
46
44
  */
47
45
  onNotAuthenticated?(ctx: {
46
+ /** `--json` / `--ndjson` flag values, both present (defaulted to `false`). */
48
47
  view: Required<ViewOptions>;
49
48
  flags: Record<string, unknown>;
50
49
  }): void | Promise<void>;
@@ -1 +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"}
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;AAGzD,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,IAAI;IAC5D,OAAO,EAAE,QAAQ,CAAA;IACjB,8EAA8E;IAC9E,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC3B,oHAAoH;IACpH,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,8EAA8E;QAC9E,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,8EAA8E;QAC9E,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,CA2CT"}
@@ -1,23 +1,25 @@
1
1
  import { CliError } from '../errors.js';
2
2
  import { formatJson, formatNdjson } from '../json.js';
3
+ import { attachUserFlag, extractUserRef, requireSnapshotForRef } from './user-flag.js';
3
4
  /**
4
5
  * Attach `status` as a subcommand of `parent`. Reads `store.active()`, optionally
5
6
  * confirms via `fetchLive`, then dispatches to `renderText` (human) or
6
7
  * `renderJson` (machine). Returns the new `Command` so the consumer can chain.
7
8
  */
8
9
  export function attachStatusCommand(parent, options) {
9
- return parent
10
+ const command = parent
10
11
  .command('status')
11
12
  .description(options.description ?? 'Show the current authentication status')
12
13
  .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;
14
+ .option('--ndjson', 'Emit machine-readable NDJSON output');
15
+ return attachUserFlag(command).action(async (cmd) => {
16
+ const { json, ndjson, user: _user, ...flags } = cmd;
16
17
  const view = {
17
18
  json: Boolean(json),
18
19
  ndjson: Boolean(ndjson),
19
20
  };
20
- const snapshot = await options.store.active();
21
+ const ref = extractUserRef(cmd);
22
+ const snapshot = await requireSnapshotForRef(options.store, ref);
21
23
  if (!snapshot) {
22
24
  if (options.onNotAuthenticated) {
23
25
  await options.onNotAuthenticated({ view, flags });
@@ -34,16 +36,12 @@ export function attachStatusCommand(parent, options) {
34
36
  })
35
37
  : snapshot.account;
36
38
  if (view.json) {
37
- const payload = options.renderJson
38
- ? options.renderJson({ account, flags })
39
- : account;
39
+ const payload = options.renderJson ? options.renderJson({ account, flags }) : account;
40
40
  console.log(formatJson(payload));
41
41
  return;
42
42
  }
43
43
  if (view.ndjson) {
44
- const payload = options.renderJson
45
- ? options.renderJson({ account, flags })
46
- : account;
44
+ const payload = options.renderJson ? options.renderJson({ account, flags }) : account;
47
45
  console.log(formatNdjson([payload]));
48
46
  return;
49
47
  }
@@ -1 +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"}
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;AAGrD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAgDtF;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAC/B,MAAe,EACf,OAA6C;IAE7C,MAAM,OAAO,GAAG,MAAM;SACjB,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,CAAA;IAC9D,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,GAA4B,EAAE,EAAE;QACzE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,GAAG,CAAA;QACnD,MAAM,IAAI,GAA0B;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;YACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC;SAC1B,CAAA;QACD,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;QAC/B,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAChE,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,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;YACrF,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,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;YACrF,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;AACN,CAAC"}
@@ -1 +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"}
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;AAGzD,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,CAyBT"}
@@ -1,5 +1,6 @@
1
1
  import { CliError } from '../errors.js';
2
2
  import { isStdoutTTY } from '../terminal.js';
3
+ import { attachUserFlag, extractUserRef, requireSnapshotForRef } from './user-flag.js';
3
4
  /**
4
5
  * Attach a "print the saved token" subcommand to `parent`. Writes the bare
5
6
  * token to stdout with no envelope so the output is pipe-safe (e.g. `eval $(td
@@ -8,10 +9,10 @@ import { isStdoutTTY } from '../terminal.js';
8
9
  * when no token is stored. Returns the new `Command` for chaining.
9
10
  */
10
11
  export function attachTokenViewCommand(parent, options) {
11
- return parent
12
+ const command = parent
12
13
  .command(options.name ?? 'token')
13
- .description(options.description ?? 'Print the saved authentication token')
14
- .action(async () => {
14
+ .description(options.description ?? 'Print the saved authentication token');
15
+ return attachUserFlag(command).action(async (cmd) => {
15
16
  if (options.envVarName && process.env[options.envVarName]) {
16
17
  throw new CliError('TOKEN_FROM_ENV', `Refusing to print: token is being read from $${options.envVarName}, not the saved store.`, {
17
18
  hints: [
@@ -20,7 +21,8 @@ export function attachTokenViewCommand(parent, options) {
20
21
  ],
21
22
  });
22
23
  }
23
- const snapshot = await options.store.active();
24
+ const ref = extractUserRef(cmd);
25
+ const snapshot = await requireSnapshotForRef(options.store, ref);
24
26
  if (!snapshot) {
25
27
  throw new CliError('NOT_AUTHENTICATED', 'Not signed in.');
26
28
  }
@@ -1 +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"}
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;AAE5C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAgBtF;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAClC,MAAe,EACf,OAAgD;IAEhD,MAAM,OAAO,GAAG,MAAM;SACjB,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC;SAChC,WAAW,CAAC,OAAO,CAAC,WAAW,IAAI,sCAAsC,CAAC,CAAA;IAC/E,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,GAA4B,EAAE,EAAE;QACzE,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,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;QAC/B,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAChE,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;AACN,CAAC"}
@@ -63,22 +63,29 @@ export type AuthProvider<TAccount extends AuthAccount = AuthAccount> = {
63
63
  /** Skipped when `exchangeCode` already returned an `account`. */
64
64
  validateToken(input: ValidateInput): Promise<TAccount>;
65
65
  };
66
+ /** Opaque account selector. Stores own the matching rule (id, email, label, …). */
67
+ export type AccountRef = string;
66
68
  /**
67
- * Persistent token + account storage. Consumers implement this against
68
- * whatever storage they need (config file, OS keychain, multi-account…).
69
- * cli-core does not ship a default implementation; it's a thin enough
70
- * interface that an inline ~30-line config-file version covers the
71
- * single-user case.
69
+ * Persistent token + account storage. Uniformly multi-user-shaped single-user
70
+ * stores implement `list` / `setDefault` against their one stored account (see
71
+ * the README example).
72
72
  */
73
73
  export type TokenStore<TAccount extends AuthAccount = AuthAccount> = {
74
- /** The currently signed-in identity, or `null` when nothing is stored. */
75
- active(): Promise<{
74
+ /** Active snapshot, or `null` when nothing matches (the attachers translate a ref miss into `ACCOUNT_NOT_FOUND`). */
75
+ active(ref?: AccountRef): Promise<{
76
76
  token: string;
77
77
  account: TAccount;
78
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`. */
79
+ /** Persist `token` for `account`, replacing any previous entry. Throw `CliError` for typed failures; other thrown values become `AUTH_STORE_WRITE_FAILED`. */
80
80
  set(account: TAccount, token: string): Promise<void>;
81
- /** Remove the active credential. No-op when nothing is stored. */
82
- clear(): Promise<void>;
81
+ /** Remove a stored credential. No-op when `ref` doesn't match. */
82
+ clear(ref?: AccountRef): Promise<void>;
83
+ /** Every stored account with a default marker. */
84
+ list(): Promise<ReadonlyArray<{
85
+ account: TAccount;
86
+ isDefault: boolean;
87
+ }>>;
88
+ /** Mark `ref` as the new default. Throw `CliError('ACCOUNT_NOT_FOUND', …)` on miss. */
89
+ setDefault(ref: AccountRef): Promise<void>;
83
90
  };
84
91
  //# sourceMappingURL=types.d.ts.map
@@ -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,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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Command } from 'commander';
2
+ import type { AccountRef, AuthAccount, TokenStore } from './types.js';
3
+ export declare function attachUserFlag(command: Command): Command;
4
+ /** `cmd.user` as an `AccountRef`, or `undefined` when absent. */
5
+ export declare function extractUserRef(cmd: Record<string, unknown>): AccountRef | undefined;
6
+ /**
7
+ * Read `store.active(ref)` and throw `ACCOUNT_NOT_FOUND` if the explicit
8
+ * `ref` doesn't match. With `ref === undefined` returns the snapshot
9
+ * (possibly `null`) unchanged.
10
+ */
11
+ export declare function requireSnapshotForRef<TAccount extends AuthAccount>(store: TokenStore<TAccount>, ref: AccountRef | undefined): Promise<{
12
+ token: string;
13
+ account: TAccount;
14
+ } | null>;
15
+ //# sourceMappingURL=user-flag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-flag.d.ts","sourceRoot":"","sources":["../../src/auth/user-flag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AASrE,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAExD;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,GAAG,SAAS,CAEnF;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,SAAS,WAAW,EACpE,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,EAC3B,GAAG,EAAE,UAAU,GAAG,SAAS,GAC5B,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,GAAG,IAAI,CAAC,CAMtD"}
@@ -0,0 +1,26 @@
1
+ import { CliError } from '../errors.js';
2
+ // Shared `--user <ref>` wiring + snapshot-or-throw helper so the three auth
3
+ // attachers can't drift on flag wording or miss semantics. Internal — not
4
+ // re-exported.
5
+ const USER_FLAG = '--user <ref>';
6
+ const USER_FLAG_DESCRIPTION = 'Target a specific stored account';
7
+ export function attachUserFlag(command) {
8
+ return command.option(USER_FLAG, USER_FLAG_DESCRIPTION);
9
+ }
10
+ /** `cmd.user` as an `AccountRef`, or `undefined` when absent. */
11
+ export function extractUserRef(cmd) {
12
+ return typeof cmd.user === 'string' ? cmd.user : undefined;
13
+ }
14
+ /**
15
+ * Read `store.active(ref)` and throw `ACCOUNT_NOT_FOUND` if the explicit
16
+ * `ref` doesn't match. With `ref === undefined` returns the snapshot
17
+ * (possibly `null`) unchanged.
18
+ */
19
+ export async function requireSnapshotForRef(store, ref) {
20
+ const snapshot = await store.active(ref);
21
+ if (ref !== undefined && snapshot === null) {
22
+ throw new CliError('ACCOUNT_NOT_FOUND', `No stored account matches "${ref}".`);
23
+ }
24
+ return snapshot;
25
+ }
26
+ //# sourceMappingURL=user-flag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-flag.js","sourceRoot":"","sources":["../../src/auth/user-flag.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGvC,4EAA4E;AAC5E,0EAA0E;AAC1E,eAAe;AAEf,MAAM,SAAS,GAAG,cAAc,CAAA;AAChC,MAAM,qBAAqB,GAAG,kCAAkC,CAAA;AAEhE,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC3C,OAAO,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAA;AAC3D,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,cAAc,CAAC,GAA4B;IACvD,OAAO,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACvC,KAA2B,EAC3B,GAA2B;IAE3B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACxC,IAAI,GAAG,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACzC,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,8BAA8B,GAAG,IAAI,CAAC,CAAA;IAClF,CAAC;IACD,OAAO,QAAQ,CAAA;AACnB,CAAC"}
@@ -20,25 +20,39 @@ export type GlobalArgs = Required<Pick<ViewOptions, 'json' | 'ndjson'>> & {
20
20
  noSpinner: boolean;
21
21
  /** false = absent, true = present without path, string = path. */
22
22
  progressJsonl: string | true | false;
23
+ /** Account selector from `--user <ref>` / `--user=<ref>`; `undefined` when absent or valueless. */
24
+ user?: string;
23
25
  };
24
26
  /**
25
27
  * Parse well-known global flags from `argv`. Pure — pass an explicit array
26
28
  * for testing, or omit to read `process.argv.slice(2)`.
27
29
  *
28
- * The parser scans the entire argv: a CLI-specific positional that happens
29
- * to look like a global short flag (`td comment add 123 -q`) will flip the
30
- * matching global state. Workaround: use the standard `--` terminator
31
- * (`td comment add 123 -- -q`) so the parser stops before the positional.
32
- * The trade-off is intentional — callers run this before Commander has
33
- * parsed argv, so we can't yet distinguish positionals from option values.
30
+ * Runs before Commander so it can't distinguish positionals from option
31
+ * values: a positional that looks like a global short flag
32
+ * (`td comment add 123 -q`) flips the matching state. Use the `--`
33
+ * terminator to stop the parser before a positional that needs protecting.
34
34
  *
35
- * `--progress-jsonl` accepts only the bare form (output to stderr) and the
36
- * `--progress-jsonl=path` form. The space-separated `--progress-jsonl path`
37
- * form is intentionally unsupported because it silently consumes the next
38
- * positional argument (e.g., `td task add --progress-jsonl "Buy milk"`
39
- * would treat `Buy milk` as a file path).
35
+ * `--progress-jsonl` accepts only the bare form and the `=path` form; the
36
+ * space-separated form would silently consume the next positional (e.g.
37
+ * `td task add --progress-jsonl "Buy milk"` would treat `Buy milk` as a
38
+ * file path). `--user` accepts both forms but never consumes a following
39
+ * flag pair with `stripUserFlag` before forwarding argv to Commander.
40
40
  */
41
41
  export declare function parseGlobalArgs(argv?: string[]): GlobalArgs;
42
+ /**
43
+ * Strip pre-subcommand `--user` tokens so a Commander program with no root
44
+ * `--user` option doesn't trip on the flag. Stops at the first non-flag
45
+ * token (including `--` and the empty string) so subcommand-level `--user`
46
+ * — attached by the auth attachers — still reaches Commander.
47
+ *
48
+ * Assumes `--user` is the only space-separated root option. CLIs that
49
+ * attach other root options taking values (e.g. `--profile <name>`) must
50
+ * either strip those first or attach `--user` on the root program directly
51
+ * — this helper only knows about `--user`.
52
+ *
53
+ * Pure; does not mutate `argv`.
54
+ */
55
+ export declare function stripUserFlag(argv: string[]): string[];
42
56
  export type GlobalArgsStore<T extends GlobalArgs = GlobalArgs> = {
43
57
  get(): T;
44
58
  /** Clear the cached parse result. Call from test teardown. */
@@ -1 +1 @@
1
- {"version":3,"file":"global-args.d.ts","sourceRoot":"","sources":["../src/global-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,GAAG;IACtE,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC1B,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,kEAAkE;IAClE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,CAAA;CACvC,CAAA;AAOD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,UAAU,CAiD3D;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,IAAI;IAC7D,GAAG,IAAI,CAAC,CAAA;IACR,8DAA8D;IAC9D,KAAK,IAAI,IAAI,CAAA;CAChB,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAAC,UAAU,CAAC,CAAA;AACpE,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AAkB/F,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAEhE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAEzE;AAED,MAAM,MAAM,qBAAqB,GAAG;IAChC,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,UAAU,CAAA;CAC5B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,OAAO,CAE/E;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC7B,2FAA2F;IAC3F,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,UAAU,CAAA;IACzB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAA;CAChC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,OAAO,CAgBzE"}
1
+ {"version":3,"file":"global-args.d.ts","sourceRoot":"","sources":["../src/global-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,GAAG;IACtE,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC1B,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,kEAAkE;IAClE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,CAAA;IACpC,mGAAmG;IACnG,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAiCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,UAAU,CAuD3D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAoBtD;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,IAAI;IAC7D,GAAG,IAAI,CAAC,CAAA;IACR,8DAA8D;IAC9D,KAAK,IAAI,IAAI,CAAA;CAChB,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAAC,UAAU,CAAC,CAAA;AACpE,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AAkB/F,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAEhE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAEzE;AAED,MAAM,MAAM,qBAAqB,GAAG;IAChC,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,UAAU,CAAA;CAC5B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,OAAO,CAE/E;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC7B,2FAA2F;IAC3F,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,UAAU,CAAA;IACzB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAA;CAChC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,OAAO,CAgBzE"}
@@ -17,22 +17,41 @@ const SHORT_FLAGS = {
17
17
  q: 'quiet',
18
18
  v: 'verbose',
19
19
  };
20
+ /** Whether `token` is a usable value for a space-separated long option (not absent, not `--`, not another flag). */
21
+ function isFlagValue(token) {
22
+ return token !== undefined && token !== '--' && !token.startsWith('-');
23
+ }
24
+ /**
25
+ * If `argv[i]` is a `--user` token, return how to consume it; otherwise `null`.
26
+ * `consumed` is the number of argv slots the token occupies (2 for the
27
+ * space form, 1 for `--user=val` / valueless).
28
+ */
29
+ function readUserFlagAt(argv, i) {
30
+ const arg = argv[i];
31
+ if (arg === '--user') {
32
+ const next = argv[i + 1];
33
+ return isFlagValue(next) ? { value: next, consumed: 2 } : { value: undefined, consumed: 1 };
34
+ }
35
+ if (arg.startsWith('--user=')) {
36
+ const value = arg.slice('--user='.length);
37
+ return { value: value !== '' ? value : undefined, consumed: 1 };
38
+ }
39
+ return null;
40
+ }
20
41
  /**
21
42
  * Parse well-known global flags from `argv`. Pure — pass an explicit array
22
43
  * for testing, or omit to read `process.argv.slice(2)`.
23
44
  *
24
- * The parser scans the entire argv: a CLI-specific positional that happens
25
- * to look like a global short flag (`td comment add 123 -q`) will flip the
26
- * matching global state. Workaround: use the standard `--` terminator
27
- * (`td comment add 123 -- -q`) so the parser stops before the positional.
28
- * The trade-off is intentional — callers run this before Commander has
29
- * parsed argv, so we can't yet distinguish positionals from option values.
45
+ * Runs before Commander so it can't distinguish positionals from option
46
+ * values: a positional that looks like a global short flag
47
+ * (`td comment add 123 -q`) flips the matching state. Use the `--`
48
+ * terminator to stop the parser before a positional that needs protecting.
30
49
  *
31
- * `--progress-jsonl` accepts only the bare form (output to stderr) and the
32
- * `--progress-jsonl=path` form. The space-separated `--progress-jsonl path`
33
- * form is intentionally unsupported because it silently consumes the next
34
- * positional argument (e.g., `td task add --progress-jsonl "Buy milk"`
35
- * would treat `Buy milk` as a file path).
50
+ * `--progress-jsonl` accepts only the bare form and the `=path` form; the
51
+ * space-separated form would silently consume the next positional (e.g.
52
+ * `td task add --progress-jsonl "Buy milk"` would treat `Buy milk` as a
53
+ * file path). `--user` accepts both forms but never consumes a following
54
+ * flag pair with `stripUserFlag` before forwarding argv to Commander.
36
55
  */
37
56
  export function parseGlobalArgs(argv) {
38
57
  const args = argv ?? process.argv.slice(2);
@@ -73,6 +92,14 @@ export function parseGlobalArgs(argv) {
73
92
  else if (arg.startsWith('--progress-jsonl=')) {
74
93
  result.progressJsonl = arg.slice('--progress-jsonl='.length);
75
94
  }
95
+ else if (arg === '--user' || arg.startsWith('--user=')) {
96
+ const consumed = readUserFlagAt(args, i);
97
+ if (consumed) {
98
+ if (consumed.value !== undefined)
99
+ result.user = consumed.value;
100
+ i += consumed.consumed - 1;
101
+ }
102
+ }
76
103
  else if (arg.length > 1 && arg[0] === '-' && arg[1] !== '-') {
77
104
  // Short-flag group: -v, -vq, -vvv, etc. Unknown shorts are
78
105
  // silently ignored — they belong to Commander or subcommands.
@@ -89,6 +116,41 @@ export function parseGlobalArgs(argv) {
89
116
  }
90
117
  return result;
91
118
  }
119
+ /**
120
+ * Strip pre-subcommand `--user` tokens so a Commander program with no root
121
+ * `--user` option doesn't trip on the flag. Stops at the first non-flag
122
+ * token (including `--` and the empty string) so subcommand-level `--user`
123
+ * — attached by the auth attachers — still reaches Commander.
124
+ *
125
+ * Assumes `--user` is the only space-separated root option. CLIs that
126
+ * attach other root options taking values (e.g. `--profile <name>`) must
127
+ * either strip those first or attach `--user` on the root program directly
128
+ * — this helper only knows about `--user`.
129
+ *
130
+ * Pure; does not mutate `argv`.
131
+ */
132
+ export function stripUserFlag(argv) {
133
+ const result = [];
134
+ let i = 0;
135
+ while (i < argv.length) {
136
+ const arg = argv[i];
137
+ if (arg === '--' || isFlagValue(arg)) {
138
+ // First non-flag token (positional, `--`, or empty string) ends
139
+ // the scan; copy the rest verbatim for Commander.
140
+ for (let j = i; j < argv.length; j++)
141
+ result.push(argv[j]);
142
+ break;
143
+ }
144
+ const consumed = readUserFlagAt(argv, i);
145
+ if (consumed) {
146
+ i += consumed.consumed;
147
+ continue;
148
+ }
149
+ result.push(arg);
150
+ i += 1;
151
+ }
152
+ return result;
153
+ }
92
154
  export function createGlobalArgsStore(parse) {
93
155
  // Overloads ensure callers passing a custom `T` must supply a matching
94
156
  // parser; the implementation default only kicks in for the no-arg
@@ -1 +1 @@
1
- {"version":3,"file":"global-args.js","sourceRoot":"","sources":["../src/global-args.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"global-args.js","sourceRoot":"","sources":["../src/global-args.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export type { ConfigErrorCode, CoreConfig, ReadConfigStrictResult, UpdateChannel
3
3
  export { printEmpty } from './empty.js';
4
4
  export { CliError, getErrorMessage } from './errors.js';
5
5
  export type { CliErrorCode, CliErrorOptions, ErrorType } from './errors.js';
6
- export { createAccessibleGate, createGlobalArgsStore, createSpinnerGate, getProgressJsonlPath, isProgressJsonlEnabled, parseGlobalArgs, } from './global-args.js';
6
+ export { createAccessibleGate, createGlobalArgsStore, createSpinnerGate, getProgressJsonlPath, isProgressJsonlEnabled, parseGlobalArgs, stripUserFlag, } from './global-args.js';
7
7
  export type { AccessibleGateOptions, GlobalArgs, GlobalArgsStore, SpinnerGateOptions, } from './global-args.js';
8
8
  export { formatJson, formatNdjson } from './json.js';
9
9
  export { emitView } from './options.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,WAAW,GACd,MAAM,aAAa,CAAA;AACpB,YAAY,EACR,eAAe,EACf,UAAU,EACV,sBAAsB,EACtB,aAAa,EACb,kBAAkB,GACrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AACvD,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC3E,OAAO,EACH,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACR,qBAAqB,EACrB,UAAU,EACV,eAAe,EACf,kBAAkB,GACrB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,YAAY,EACR,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,cAAc,GACjB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,WAAW,GACd,MAAM,aAAa,CAAA;AACpB,YAAY,EACR,eAAe,EACf,UAAU,EACV,sBAAsB,EACtB,aAAa,EACb,kBAAkB,GACrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AACvD,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC3E,OAAO,EACH,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,aAAa,GAChB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACR,qBAAqB,EACrB,UAAU,EACV,eAAe,EACf,kBAAkB,GACrB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,YAAY,EACR,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,cAAc,GACjB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { BROKEN_CONFIG_STATE_TO_CODE, getConfigPath, readConfig, readConfigOrThrow, readConfigStrict, updateConfig, updateConfigOrThrow, writeConfig, } from './config.js';
2
2
  export { printEmpty } from './empty.js';
3
3
  export { CliError, getErrorMessage } from './errors.js';
4
- export { createAccessibleGate, createGlobalArgsStore, createSpinnerGate, getProgressJsonlPath, isProgressJsonlEnabled, parseGlobalArgs, } from './global-args.js';
4
+ export { createAccessibleGate, createGlobalArgsStore, createSpinnerGate, getProgressJsonlPath, isProgressJsonlEnabled, parseGlobalArgs, stripUserFlag, } from './global-args.js';
5
5
  export { formatJson, formatNdjson } from './json.js';
6
6
  export { emitView } from './options.js';
7
7
  export { createSpinner } from './spinner.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,WAAW,GACd,MAAM,aAAa,CAAA;AAQpB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAEvD,OAAO,EACH,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AAOzB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAQ5C,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,WAAW,GACd,MAAM,aAAa,CAAA;AAQpB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAEvD,OAAO,EACH,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,aAAa,GAChB,MAAM,kBAAkB,CAAA;AAOzB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAQ5C,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doist/cli-core",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Shared core utilities for Doist CLI projects",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -66,7 +66,7 @@
66
66
  "@semantic-release/changelog": "6.0.3",
67
67
  "@semantic-release/exec": "7.1.0",
68
68
  "@semantic-release/git": "10.0.1",
69
- "@types/node": "25.6.1",
69
+ "@types/node": "25.6.2",
70
70
  "commander": "14.0.3",
71
71
  "conventional-changelog-conventionalcommits": "9.3.1",
72
72
  "lefthook": "2.1.6",