@doist/outline-cli 1.6.0 → 1.7.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
+ ## [1.7.0](https://github.com/Doist/outline-cli/compare/v1.6.0...v1.7.0) (2026-05-17)
2
+
3
+ ### Features
4
+
5
+ * **auth:** store API tokens in the OS keyring via @doist/cli-core ([#73](https://github.com/Doist/outline-cli/issues/73)) ([b353aea](https://github.com/Doist/outline-cli/commit/b353aeae3cdcc63308ec8de899f08c1dda23f22c))
6
+
1
7
  ## [1.6.0](https://github.com/Doist/outline-cli/compare/v1.5.3...v1.6.0) (2026-05-15)
2
8
 
3
9
  ### Features
@@ -1,2 +1,14 @@
1
+ import { type TokenStorageResult } from '@doist/cli-core/auth';
1
2
  import type { Command } from 'commander';
3
+ /**
4
+ * Surface a `TokenStorageResult` from a save/clear: the human-readable
5
+ * confirmation goes to stdout, any keyring-fallback warning goes to stderr.
6
+ * Pass `isMachineOutput: true` to suppress the stdout confirmation in
7
+ * `--json` / `--ndjson` mode while still routing the warning to stderr.
8
+ *
9
+ * Exported for direct unit testing — the alternative (driving this via
10
+ * mocked cli-core login/logout hooks) would require stubbing the entire
11
+ * store contract just to assert two console calls.
12
+ */
13
+ export declare function logTokenStorageResult(result: TokenStorageResult, secureStoreMessage: string, isMachineOutput?: boolean): void;
2
14
  export declare function registerAuthCommand(program: Command): void;
@@ -1,10 +1,9 @@
1
- import { attachLoginCommand } from '@doist/cli-core/auth';
1
+ import { attachLoginCommand, attachLogoutCommand, attachStatusCommand, } from '@doist/cli-core/auth';
2
2
  import chalk from 'chalk';
3
3
  import { apiRequest } from '../lib/api.js';
4
4
  import { renderError, renderSuccess } from '../lib/auth-pages.js';
5
- import { createOutlineAuthProvider, createOutlineTokenStore } from '../lib/auth-provider.js';
6
- import { clearConfig, getBaseUrl, getTokenSource } from '../lib/auth.js';
7
- import { formatError } from '../lib/output.js';
5
+ import { createOutlineAuthProvider, createOutlineTokenStore, getActiveTokenSource, } from '../lib/auth-provider.js';
6
+ import { CliError } from '../lib/errors.js';
8
7
  const DEFAULT_OAUTH_CALLBACK_PORT = 54969;
9
8
  function resolvePreferredCallbackPort() {
10
9
  const raw = process.env.OUTLINE_OAUTH_CALLBACK_PORT?.trim();
@@ -16,6 +15,24 @@ function resolvePreferredCallbackPort() {
16
15
  }
17
16
  return parsed;
18
17
  }
18
+ /**
19
+ * Surface a `TokenStorageResult` from a save/clear: the human-readable
20
+ * confirmation goes to stdout, any keyring-fallback warning goes to stderr.
21
+ * Pass `isMachineOutput: true` to suppress the stdout confirmation in
22
+ * `--json` / `--ndjson` mode while still routing the warning to stderr.
23
+ *
24
+ * Exported for direct unit testing — the alternative (driving this via
25
+ * mocked cli-core login/logout hooks) would require stubbing the entire
26
+ * store contract just to assert two console calls.
27
+ */
28
+ export function logTokenStorageResult(result, secureStoreMessage, isMachineOutput = false) {
29
+ if (!isMachineOutput && result.storage === 'secure-store') {
30
+ console.log(chalk.dim(secureStoreMessage));
31
+ }
32
+ if (result.warning) {
33
+ console.error(chalk.yellow('Warning:'), result.warning);
34
+ }
35
+ }
19
36
  export function registerAuthCommand(program) {
20
37
  const auth = program.command('auth').description('Manage authentication');
21
38
  const provider = createOutlineAuthProvider();
@@ -28,43 +45,84 @@ export function registerAuthCommand(program) {
28
45
  renderSuccess,
29
46
  renderError,
30
47
  onSuccess({ view, account }) {
31
- if (view.json || view.ndjson)
32
- return;
33
- console.log(chalk.green(`Authenticated to ${account.teamName} as ${account.label}`));
48
+ const isMachineOutput = view.json || view.ndjson;
49
+ if (!isMachineOutput) {
50
+ console.log(chalk.green(`Authenticated to ${account.teamName} as ${account.label}`));
51
+ }
52
+ const result = store.getLastStorageResult();
53
+ if (result) {
54
+ logTokenStorageResult(result, 'Token stored securely in the system credential manager', isMachineOutput);
55
+ }
34
56
  },
35
57
  })
36
58
  .description('Authenticate with an Outline instance via OAuth')
37
59
  .option('--base-url <url>', 'Outline base URL to use for this login (saved for future logins)')
38
60
  .option('--client-id <clientId>', 'OAuth client ID to use for this login (saved for future logins)');
39
- auth.command('status')
40
- .description('Show current authentication state')
41
- .action(async () => {
42
- const source = await getTokenSource();
43
- if (!source) {
44
- console.log(chalk.yellow('Not authenticated. Run: ol auth login'));
45
- return;
46
- }
47
- console.log(chalk.dim(`Token source: ${source}`));
48
- console.log(chalk.dim(`Base URL: ${await getBaseUrl()}`));
49
- try {
50
- const { data } = await apiRequest('auth.info');
51
- console.log(`Team: ${chalk.bold(data.team.name)}`);
52
- console.log(`User: ${data.user.name} (${data.user.email})`);
53
- }
54
- catch (err) {
55
- console.error(formatError('AUTH_VERIFICATION_FAILED', `Could not fetch auth info: ${err.message}`, [
56
- 'Check that your API token is valid',
57
- 'Verify the base URL is correct',
58
- "Run 'ol auth login' to re-authenticate",
59
- ]));
60
- process.exit(1);
61
- }
61
+ // `attachStatusCommand` guarantees `fetchLive` runs before `renderText` /
62
+ // `renderJson` within a single invocation, so the stash is always
63
+ // populated by the time the render hooks read it.
64
+ let statusData = null;
65
+ attachStatusCommand(auth, {
66
+ store,
67
+ description: 'Show current authentication state',
68
+ async fetchLive({ token, account }) {
69
+ try {
70
+ const [{ data: info }, source] = await Promise.all([
71
+ apiRequest('auth.info', {}, { token, baseUrl: account.baseUrl }),
72
+ getActiveTokenSource(),
73
+ ]);
74
+ statusData = { email: info.user.email, source };
75
+ return {
76
+ ...account,
77
+ id: info.user.id,
78
+ label: info.user.name,
79
+ teamName: info.team.name,
80
+ };
81
+ }
82
+ catch (err) {
83
+ const message = err instanceof Error ? err.message : '';
84
+ if (/\b401\b/.test(message) || /Authentication required/i.test(message)) {
85
+ throw new CliError('NO_TOKEN', 'Not authenticated (token expired or invalid)', [
86
+ 'Run `ol auth login` to re-authenticate',
87
+ ]);
88
+ }
89
+ throw err;
90
+ }
91
+ },
92
+ renderText({ account }) {
93
+ if (!statusData)
94
+ throw new Error('status renderText called before fetchLive');
95
+ return [
96
+ `${chalk.green('✓')} Authenticated`,
97
+ ` Team: ${chalk.bold(account.teamName ?? '')}`,
98
+ ` User: ${account.label} (${statusData.email})`,
99
+ ` Base URL: ${account.baseUrl}`,
100
+ ` Token source: ${statusData.source}`,
101
+ ];
102
+ },
103
+ renderJson({ account }) {
104
+ if (!statusData)
105
+ throw new Error('status renderJson called before fetchLive');
106
+ return {
107
+ id: account.id,
108
+ team: account.teamName,
109
+ baseUrl: account.baseUrl,
110
+ source: statusData.source,
111
+ };
112
+ },
113
+ onNotAuthenticated() {
114
+ throw new CliError('NOT_AUTHENTICATED', 'Not authenticated. Run: ol auth login');
115
+ },
62
116
  });
63
- auth.command('logout')
64
- .description('Clear saved authentication')
65
- .action(async () => {
66
- await clearConfig();
67
- console.log('Logged out.');
117
+ attachLogoutCommand(auth, {
118
+ store,
119
+ description: 'Clear saved authentication',
120
+ onCleared({ view }) {
121
+ const result = store.getLastClearResult();
122
+ if (!result)
123
+ return;
124
+ logTokenStorageResult(result, 'Stored token removed from the system credential manager', view.json || view.ndjson);
125
+ },
68
126
  });
69
127
  }
70
128
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { Config } from './config.js';
2
+ /** OS keyring `service` identifier for every outline-cli secret. */
3
+ export declare const SECURE_STORE_SERVICE = "outline-cli";
4
+ /** Env var that short-circuits the token store with a manually-supplied token. */
5
+ export declare const TOKEN_ENV_VAR = "OUTLINE_API_TOKEN";
6
+ /**
7
+ * Legacy single-user keyring slot. Outline never wrote a token to the
8
+ * keyring before this migration, so there is no real legacy slot to read —
9
+ * `migrateLegacyAuth` still expects the option, and its best-effort delete
10
+ * after migration is a harmless no-op on an empty entry.
11
+ */
12
+ export declare const LEGACY_KEYRING_ACCOUNT = "api-token";
13
+ /**
14
+ * `updateConfig` payload that wipes every v1 auth key. Used by both the
15
+ * one-shot migration `cleanupLegacyConfig` and the runtime
16
+ * `dischargeLegacyState` so both paths stay in lockstep.
17
+ */
18
+ export declare const LEGACY_CLEAR_PAYLOAD: Partial<Config>;
@@ -0,0 +1,25 @@
1
+ /** OS keyring `service` identifier for every outline-cli secret. */
2
+ export const SECURE_STORE_SERVICE = 'outline-cli';
3
+ /** Env var that short-circuits the token store with a manually-supplied token. */
4
+ export const TOKEN_ENV_VAR = 'OUTLINE_API_TOKEN';
5
+ /**
6
+ * Legacy single-user keyring slot. Outline never wrote a token to the
7
+ * keyring before this migration, so there is no real legacy slot to read —
8
+ * `migrateLegacyAuth` still expects the option, and its best-effort delete
9
+ * after migration is a harmless no-op on an empty entry.
10
+ */
11
+ export const LEGACY_KEYRING_ACCOUNT = 'api-token';
12
+ /**
13
+ * `updateConfig` payload that wipes every v1 auth key. Used by both the
14
+ * one-shot migration `cleanupLegacyConfig` and the runtime
15
+ * `dischargeLegacyState` so both paths stay in lockstep.
16
+ */
17
+ export const LEGACY_CLEAR_PAYLOAD = {
18
+ api_token: undefined,
19
+ base_url: undefined,
20
+ oauth_client_id: undefined,
21
+ auth_user_id: undefined,
22
+ auth_user_name: undefined,
23
+ auth_team_name: undefined,
24
+ };
25
+ //# sourceMappingURL=auth-constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-constants.js","sourceRoot":"","sources":["../../src/lib/auth-constants.ts"],"names":[],"mappings":"AAEA,oEAAoE;AACpE,MAAM,CAAC,MAAM,oBAAoB,GAAG,aAAa,CAAA;AAEjD,kFAAkF;AAClF,MAAM,CAAC,MAAM,aAAa,GAAG,mBAAmB,CAAA;AAEhD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAA;AAEjD;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAoB;IACjD,SAAS,EAAE,SAAS;IACpB,QAAQ,EAAE,SAAS;IACnB,eAAe,EAAE,SAAS;IAC1B,YAAY,EAAE,SAAS;IACvB,cAAc,EAAE,SAAS;IACzB,cAAc,EAAE,SAAS;CAC5B,CAAA"}
@@ -1,10 +1,59 @@
1
- import { type AuthAccount, type AuthProvider, type TokenStore } from '@doist/cli-core/auth';
2
- export type OutlineAccount = AuthAccount & {
3
- id: string;
4
- label: string;
5
- baseUrl: string;
6
- oauthClientId: string;
7
- teamName?: string;
1
+ import { type AccountRef, type AuthProvider, type KeyringTokenStore } from '@doist/cli-core/auth';
2
+ import { type OutlineAccount } from './outline-account.js';
3
+ export type { OutlineAccount } from './outline-account.js';
4
+ export type AuthInfoResponse = {
5
+ user: {
6
+ id: string;
7
+ name: string;
8
+ email: string;
9
+ };
10
+ team: {
11
+ name: string;
12
+ subdomain: string;
13
+ };
8
14
  };
15
+ export type OutlineTokenStore = KeyringTokenStore<OutlineAccount>;
9
16
  export declare function createOutlineAuthProvider(): AuthProvider<OutlineAccount>;
10
- export declare function createOutlineTokenStore(): TokenStore<OutlineAccount>;
17
+ /**
18
+ * Accepts the Outline user UUID or display name. Id matches are
19
+ * case-sensitive (UUIDs are canonical); label matches are
20
+ * case-insensitive so users can pass the name they see in `auth status`.
21
+ */
22
+ export declare function matchOutlineAccount(account: OutlineAccount, ref: AccountRef): boolean;
23
+ /**
24
+ * True when the v2 store is empty but a legacy v1 token snapshot is still
25
+ * the only thing keeping the CLI authenticated — typically because
26
+ * `migrateLegacyAuth` couldn't reach the Outline API to identify the
27
+ * account (`MigrateSkipReason: 'identify-failed'`) or the OS keyring is
28
+ * unreachable (`'legacy-keyring-unreachable'`, although outline has no
29
+ * v1 keyring slot to read from). Useful for downstream diagnostics.
30
+ */
31
+ export declare function isLegacyAuthActive(): Promise<boolean>;
32
+ /**
33
+ * `OUTLINE_API_TOKEN` short-circuits `active()` only when no explicit ref
34
+ * is supplied — cli-core's `KeyringTokenStore` doesn't know about the env
35
+ * var, and an explicit ref means the caller targets a specific stored
36
+ * account.
37
+ *
38
+ * `ensureMigrated()` runs **before** every mutating v2 op so the post-op
39
+ * legacy discharge can't race a still-pending migration into re-grabbing
40
+ * the legacy `api_token` we just consumed. `set()` / `clear()` then
41
+ * discharge legacy state **after** the v2 op succeeds. `set()` swallows
42
+ * the cleanup failure (v2 wins in `active()` regardless); `clear()`
43
+ * propagates it so a failed logout fails loudly instead of leaving the
44
+ * user authenticated via the legacy fallback.
45
+ */
46
+ export declare function createOutlineTokenStore(): OutlineTokenStore;
47
+ /**
48
+ * Where the currently-active token lives. Mirrors `active()`'s resolution
49
+ * order — env → v2 record → legacy plaintext — so the answer can never
50
+ * contradict the token the runtime is actually using.
51
+ *
52
+ * The precedence cascade is intentionally duplicated with `active()`:
53
+ * the only true dedupe options either (a) add an extra config read on
54
+ * every `apiRequest` call (regressing the request hot path) or (b)
55
+ * augment cli-core's `TokenStore` contract. The drift the duplication
56
+ * invites is guarded by the `getActiveTokenSource` regression test that
57
+ * asserts v2-record presence wins over a lingering v1 `api_token`.
58
+ */
59
+ export declare function getActiveTokenSource(): Promise<'env' | 'secure-store' | 'config-file'>;
@@ -1,11 +1,13 @@
1
1
  import { createInterface } from 'node:readline/promises';
2
- import { deriveChallenge, generateVerifier, } from '@doist/cli-core/auth';
2
+ import { createKeyringTokenStore, deriveChallenge, generateVerifier, } from '@doist/cli-core/auth';
3
3
  import { fetchWithRetry } from '../transport/fetch-with-retry.js';
4
4
  import { apiRequest } from './api.js';
5
- import { clearConfig, getBaseUrl, getOAuthClientId } from './auth.js';
6
- import { getConfig, updateConfig } from './config.js';
7
- import { CliError } from './errors.js';
8
- const DEFAULT_BASE_URL = 'https://app.getoutline.com';
5
+ import { LEGACY_CLEAR_PAYLOAD, SECURE_STORE_SERVICE, TOKEN_ENV_VAR } from './auth-constants.js';
6
+ import { getBaseUrl, getOAuthClientId } from './auth.js';
7
+ import { getConfig, getConfigPath, updateConfig } from './config.js';
8
+ import { runMigrateLegacyAuth } from './migrate-auth.js';
9
+ import { makeOutlineAccount } from './outline-account.js';
10
+ import { createOutlineUserRecordStore, getDefaultUserRecord } from './user-records.js';
9
11
  function asHandshake(value) {
10
12
  return value;
11
13
  }
@@ -100,99 +102,198 @@ export function createOutlineAuthProvider() {
100
102
  token,
101
103
  baseUrl: hs.baseUrl,
102
104
  });
103
- return {
105
+ return makeOutlineAccount({
104
106
  id: data.user.id,
105
107
  label: data.user.name,
106
108
  baseUrl: hs.baseUrl,
107
109
  oauthClientId: hs.clientId,
108
110
  teamName: data.team.name,
109
- };
111
+ });
110
112
  },
111
113
  };
112
114
  }
113
- export function createOutlineTokenStore() {
114
- /**
115
- * Derive a snapshot from an already-loaded config. Pure, so ref-aware
116
- * callers can validate without a second config read.
117
- */
118
- function deriveSnapshot(config) {
119
- if (!config.api_token)
120
- return null;
121
- const id = config.auth_user_id;
122
- const label = config.auth_user_name;
123
- if (!id || !label) {
124
- // Stored token predates this adapter (env var, pre-upgrade
125
- // config). No persisted identity to round-trip.
126
- return null;
127
- }
128
- return {
129
- token: config.api_token,
130
- account: {
131
- id,
132
- label,
133
- baseUrl: config.base_url ?? DEFAULT_BASE_URL,
134
- oauthClientId: config.oauth_client_id ?? '',
135
- teamName: config.auth_team_name,
136
- },
137
- };
138
- }
139
- /**
140
- * Match the stored account against `--user <ref>`. Outline accounts use
141
- * UUID ids and a display name — id matches are case-sensitive (UUIDs
142
- * are canonical), label matches are case-insensitive so users can pass
143
- * the name they see in `auth status` regardless of casing.
144
- */
145
- function matchesRef(account, ref) {
146
- if (account.id === ref)
147
- return true;
148
- return account.label.toLowerCase() === ref.toLowerCase();
115
+ /**
116
+ * Accepts the Outline user UUID or display name. Id matches are
117
+ * case-sensitive (UUIDs are canonical); label matches are
118
+ * case-insensitive so users can pass the name they see in `auth status`.
119
+ */
120
+ export function matchOutlineAccount(account, ref) {
121
+ if (account.id === ref)
122
+ return true;
123
+ return account.label.toLowerCase() === ref.toLowerCase();
124
+ }
125
+ /** True when the v2 store is the authoritative source. */
126
+ function migrationIsConclusive(result) {
127
+ return (result.status === 'migrated' ||
128
+ result.status === 'already-migrated' ||
129
+ result.status === 'no-legacy-state');
130
+ }
131
+ /**
132
+ * Synthesise a snapshot from v1 plaintext state still on disk. Fallback for
133
+ * when migration can't complete (offline `identifyAccount`, WSL
134
+ * `legacy-keyring-unreachable`). Returns `null` when no legacy token is
135
+ * present. The synthesised account uses whatever identity fields the v1
136
+ * config has — for pre-#71 configs the id/label may be empty, but the
137
+ * runtime never renders those (status's `fetchLive` re-derives from the
138
+ * API), so empty placeholders are safe.
139
+ */
140
+ async function readLegacyTokenSnapshot() {
141
+ const config = await getConfig();
142
+ const token = config.api_token?.trim() || null;
143
+ if (!token)
144
+ return null;
145
+ return {
146
+ token,
147
+ account: makeOutlineAccount({
148
+ id: config.auth_user_id ?? '',
149
+ label: config.auth_user_name ?? '',
150
+ baseUrl: config.base_url,
151
+ oauthClientId: config.oauth_client_id,
152
+ teamName: config.auth_team_name,
153
+ }),
154
+ };
155
+ }
156
+ /**
157
+ * Discharge v1 plaintext state. Runs **after** a successful v2 write/clear
158
+ * — never before — so a v2-op failure doesn't strand the user with no
159
+ * recoverable credentials. Caller decides whether to swallow or propagate
160
+ * the `updateConfig` failure:
161
+ * - `set()` swallows (v2 record will win in `active()` regardless).
162
+ * - `clear()` propagates (v2 is empty, so a stale legacy token would
163
+ * shadow the logout via the fallback).
164
+ */
165
+ async function dischargeLegacyState() {
166
+ await updateConfig(LEGACY_CLEAR_PAYLOAD);
167
+ }
168
+ /**
169
+ * Memoised one-shot migration trigger. Resolves with `null` on rejection so
170
+ * the CLI never fails to start because of a migration error — the legacy
171
+ * snapshot fallback handles that case. Tests reset the memo with
172
+ * `vi.resetModules()` + a dynamic re-import.
173
+ */
174
+ let migrationPromise;
175
+ function ensureMigrated() {
176
+ if (!migrationPromise) {
177
+ migrationPromise = runMigrateLegacyAuth({ silent: true }).catch(() => null);
149
178
  }
150
- function refMismatch(ref) {
151
- return new CliError('ACCOUNT_NOT_FOUND', `No stored account matches "${ref}".`);
179
+ return migrationPromise;
180
+ }
181
+ /**
182
+ * True when the v2 store is empty but a legacy v1 token snapshot is still
183
+ * the only thing keeping the CLI authenticated — typically because
184
+ * `migrateLegacyAuth` couldn't reach the Outline API to identify the
185
+ * account (`MigrateSkipReason: 'identify-failed'`) or the OS keyring is
186
+ * unreachable (`'legacy-keyring-unreachable'`, although outline has no
187
+ * v1 keyring slot to read from). Useful for downstream diagnostics.
188
+ */
189
+ export async function isLegacyAuthActive() {
190
+ const result = await ensureMigrated();
191
+ if (result !== null && migrationIsConclusive(result))
192
+ return false;
193
+ const legacy = await readLegacyTokenSnapshot();
194
+ return legacy !== null;
195
+ }
196
+ /**
197
+ * `OUTLINE_API_TOKEN` short-circuits `active()` only when no explicit ref
198
+ * is supplied — cli-core's `KeyringTokenStore` doesn't know about the env
199
+ * var, and an explicit ref means the caller targets a specific stored
200
+ * account.
201
+ *
202
+ * `ensureMigrated()` runs **before** every mutating v2 op so the post-op
203
+ * legacy discharge can't race a still-pending migration into re-grabbing
204
+ * the legacy `api_token` we just consumed. `set()` / `clear()` then
205
+ * discharge legacy state **after** the v2 op succeeds. `set()` swallows
206
+ * the cleanup failure (v2 wins in `active()` regardless); `clear()`
207
+ * propagates it so a failed logout fails loudly instead of leaving the
208
+ * user authenticated via the legacy fallback.
209
+ */
210
+ export function createOutlineTokenStore() {
211
+ const inner = createKeyringTokenStore({
212
+ serviceName: SECURE_STORE_SERVICE,
213
+ userRecords: createOutlineUserRecordStore(),
214
+ recordsLocation: getConfigPath(),
215
+ matchAccount: matchOutlineAccount,
216
+ });
217
+ async function migrationIsInconclusive() {
218
+ const result = await ensureMigrated(); // memoised
219
+ return result === null || !migrationIsConclusive(result);
152
220
  }
153
221
  return {
154
222
  async active(ref) {
155
- const snapshot = deriveSnapshot(await getConfig());
156
- if (ref === undefined)
157
- return snapshot;
158
- if (!snapshot || !matchesRef(snapshot.account, ref))
159
- throw refMismatch(ref);
160
- return snapshot;
223
+ if (ref === undefined) {
224
+ const envToken = process.env[TOKEN_ENV_VAR]?.trim();
225
+ if (envToken) {
226
+ return {
227
+ token: envToken,
228
+ account: makeOutlineAccount({
229
+ id: '',
230
+ label: '',
231
+ baseUrl: await getBaseUrl(),
232
+ }),
233
+ };
234
+ }
235
+ }
236
+ await ensureMigrated();
237
+ const fromStore = await inner.active(ref);
238
+ if (fromStore)
239
+ return fromStore;
240
+ const legacy = await readLegacyTokenSnapshot();
241
+ if (legacy && (ref === undefined || matchOutlineAccount(legacy.account, ref))) {
242
+ return legacy;
243
+ }
244
+ return null;
161
245
  },
162
246
  async set(account, token) {
163
- await updateConfig({
164
- api_token: token,
165
- base_url: account.baseUrl,
166
- oauth_client_id: account.oauthClientId,
167
- auth_user_id: account.id,
168
- auth_user_name: account.label,
169
- auth_team_name: account.teamName,
170
- });
247
+ await ensureMigrated();
248
+ await inner.set(account, token);
249
+ if (await migrationIsInconclusive()) {
250
+ // Best-effort: a lingering `api_token` is dormant because
251
+ // `active()` reads v2 first.
252
+ await dischargeLegacyState().catch(() => undefined);
253
+ }
171
254
  },
172
255
  async clear(ref) {
173
- // With `ref`, validate before touching storage so a mismatch is
174
- // an `ACCOUNT_NOT_FOUND` error rather than a silent success —
175
- // `attachLogoutCommand` treats any non-throwing `clear()` as
176
- // success. Load the config once and hand it to `clearConfig`
177
- // so ref-based logout stays at one read + one write.
178
- const config = await getConfig();
179
- if (ref !== undefined) {
180
- const snapshot = deriveSnapshot(config);
181
- if (!snapshot || !matchesRef(snapshot.account, ref))
182
- throw refMismatch(ref);
256
+ await ensureMigrated();
257
+ await inner.clear(ref);
258
+ if (await migrationIsInconclusive()) {
259
+ // Must succeed: v2 is now empty, so a surviving legacy
260
+ // token would shadow the logout via the fallback.
261
+ await dischargeLegacyState();
183
262
  }
184
- await clearConfig(config);
185
263
  },
186
264
  async list() {
187
- const snapshot = deriveSnapshot(await getConfig());
188
- return snapshot ? [{ account: snapshot.account, isDefault: true }] : [];
265
+ await ensureMigrated();
266
+ return inner.list();
189
267
  },
190
268
  async setDefault(ref) {
191
- const snapshot = deriveSnapshot(await getConfig());
192
- if (!snapshot || !matchesRef(snapshot.account, ref))
193
- throw refMismatch(ref);
194
- // Single-user store — already the default once `ref` matches.
269
+ await ensureMigrated();
270
+ return inner.setDefault(ref);
195
271
  },
272
+ getLastStorageResult: () => inner.getLastStorageResult(),
273
+ getLastClearResult: () => inner.getLastClearResult(),
196
274
  };
197
275
  }
276
+ /**
277
+ * Where the currently-active token lives. Mirrors `active()`'s resolution
278
+ * order — env → v2 record → legacy plaintext — so the answer can never
279
+ * contradict the token the runtime is actually using.
280
+ *
281
+ * The precedence cascade is intentionally duplicated with `active()`:
282
+ * the only true dedupe options either (a) add an extra config read on
283
+ * every `apiRequest` call (regressing the request hot path) or (b)
284
+ * augment cli-core's `TokenStore` contract. The drift the duplication
285
+ * invites is guarded by the `getActiveTokenSource` regression test that
286
+ * asserts v2-record presence wins over a lingering v1 `api_token`.
287
+ */
288
+ export async function getActiveTokenSource() {
289
+ if (process.env[TOKEN_ENV_VAR]?.trim())
290
+ return 'env';
291
+ const config = await getConfig();
292
+ const record = getDefaultUserRecord(config);
293
+ if (record)
294
+ return record.fallbackToken ? 'config-file' : 'secure-store';
295
+ if (config.api_token?.trim())
296
+ return 'config-file';
297
+ return 'secure-store';
298
+ }
198
299
  //# sourceMappingURL=auth-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-provider.js","sourceRoot":"","sources":["../../src/lib/auth-provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-provider.js","sourceRoot":"","sources":["../../src/lib/auth-provider.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,28 @@
1
- import { type Config } from './config.js';
1
+ import { SecureStoreUnavailableError } from '@doist/cli-core/auth';
2
+ import { TOKEN_ENV_VAR } from './auth-constants.js';
3
+ import { getActiveTokenSource } from './auth-provider.js';
4
+ import { CliError } from './errors.js';
5
+ export { SecureStoreUnavailableError, getActiveTokenSource, TOKEN_ENV_VAR };
6
+ export declare class NoTokenError extends CliError {
7
+ constructor();
8
+ }
9
+ /**
10
+ * Read the active token. Hot path: when `OUTLINE_API_TOKEN` is set we
11
+ * return it directly without consulting the token store, since
12
+ * `apiRequest` already resolves the base URL separately — going through
13
+ * `store.active()` here would trigger a redundant `getBaseUrl()` lookup
14
+ * per request just to synthesise an account we don't need.
15
+ */
2
16
  export declare function getApiToken(): Promise<string>;
17
+ /**
18
+ * Base URL cascade: env var → default user record (v2) → legacy
19
+ * `base_url` config (v1) → built-in default. The record takes priority
20
+ * over the legacy slot so post-migration logins keep defaulting to the
21
+ * same Outline instance.
22
+ */
3
23
  export declare function getBaseUrl(): Promise<string>;
4
- export declare function getOAuthClientId(): Promise<string | undefined>;
5
- export declare function getTokenSource(): Promise<'env' | 'config' | null>;
6
24
  /**
7
- * Clear the auth-related keys without deleting the file. The config is now
8
- * shared with non-auth settings (notably `update_channel`); a blanket unlink
9
- * would silently reset the user's update-channel preference too.
10
- *
11
- * Pass `existing` to skip the read when the caller has already loaded the
12
- * config (e.g. ref-validated logout) — keeps that flow at one read + one
13
- * write instead of two reads.
25
+ * OAuth client id cascade: env var → default user record (v2) → legacy
26
+ * `oauth_client_id` config (v1) → undefined (caller prompts).
14
27
  */
15
- export declare function clearConfig(existing?: Partial<Config>): Promise<void>;
28
+ export declare function getOAuthClientId(): Promise<string | undefined>;
package/dist/lib/auth.js CHANGED
@@ -1,56 +1,74 @@
1
- import { getConfig, setConfig } from './config.js';
2
- const DEFAULT_BASE_URL = 'https://app.getoutline.com';
1
+ import { SecureStoreUnavailableError } from '@doist/cli-core/auth';
2
+ import { TOKEN_ENV_VAR } from './auth-constants.js';
3
+ import { createOutlineTokenStore, getActiveTokenSource, } from './auth-provider.js';
4
+ import { getConfig } from './config.js';
5
+ import { CliError } from './errors.js';
6
+ import { DEFAULT_BASE_URL } from './outline-account.js';
7
+ import { getDefaultUserRecord } from './user-records.js';
8
+ export { SecureStoreUnavailableError, getActiveTokenSource, TOKEN_ENV_VAR };
9
+ export class NoTokenError extends CliError {
10
+ constructor() {
11
+ super('NO_TOKEN', `No API token found. Set ${TOKEN_ENV_VAR} env var or run: ol auth login`, [`Set ${TOKEN_ENV_VAR} or run: ol auth login`], 'info');
12
+ this.name = 'NoTokenError';
13
+ }
14
+ }
15
+ /**
16
+ * Module-level token-store singleton. Built lazily on first call; reused
17
+ * across every `apiRequest` so the request hot path doesn't reconstruct
18
+ * the keyring + user-record adapters per POST.
19
+ */
20
+ let storeSingleton;
21
+ function tokenStore() {
22
+ if (!storeSingleton)
23
+ storeSingleton = createOutlineTokenStore();
24
+ return storeSingleton;
25
+ }
26
+ /**
27
+ * Read the active token. Hot path: when `OUTLINE_API_TOKEN` is set we
28
+ * return it directly without consulting the token store, since
29
+ * `apiRequest` already resolves the base URL separately — going through
30
+ * `store.active()` here would trigger a redundant `getBaseUrl()` lookup
31
+ * per request just to synthesise an account we don't need.
32
+ */
3
33
  export async function getApiToken() {
4
- const envToken = process.env.OUTLINE_API_TOKEN;
34
+ const envToken = process.env[TOKEN_ENV_VAR]?.trim();
5
35
  if (envToken)
6
36
  return envToken;
7
- const config = await getConfig();
8
- if (config.api_token)
9
- return config.api_token;
10
- throw new Error('No API token found. Set OUTLINE_API_TOKEN env var or run: ol auth login');
37
+ const snapshot = await tokenStore().active();
38
+ if (!snapshot?.token)
39
+ throw new NoTokenError();
40
+ return snapshot.token;
11
41
  }
42
+ /**
43
+ * Base URL cascade: env var → default user record (v2) → legacy
44
+ * `base_url` config (v1) → built-in default. The record takes priority
45
+ * over the legacy slot so post-migration logins keep defaulting to the
46
+ * same Outline instance.
47
+ */
12
48
  export async function getBaseUrl() {
13
49
  const envUrl = process.env.OUTLINE_URL;
14
50
  if (envUrl)
15
51
  return envUrl.replace(/\/$/, '');
16
52
  const config = await getConfig();
53
+ const record = getDefaultUserRecord(config);
54
+ if (record?.account.baseUrl)
55
+ return record.account.baseUrl.replace(/\/$/, '');
17
56
  if (config.base_url)
18
57
  return config.base_url.replace(/\/$/, '');
19
58
  return DEFAULT_BASE_URL;
20
59
  }
60
+ /**
61
+ * OAuth client id cascade: env var → default user record (v2) → legacy
62
+ * `oauth_client_id` config (v1) → undefined (caller prompts).
63
+ */
21
64
  export async function getOAuthClientId() {
22
65
  const envClientId = process.env.OUTLINE_OAUTH_CLIENT_ID;
23
66
  if (envClientId)
24
67
  return envClientId;
25
68
  const config = await getConfig();
69
+ const record = getDefaultUserRecord(config);
70
+ if (record?.account.oauthClientId)
71
+ return record.account.oauthClientId;
26
72
  return config.oauth_client_id;
27
73
  }
28
- export async function getTokenSource() {
29
- if (process.env.OUTLINE_API_TOKEN)
30
- return 'env';
31
- const config = await getConfig();
32
- if (config.api_token)
33
- return 'config';
34
- return null;
35
- }
36
- /**
37
- * Clear the auth-related keys without deleting the file. The config is now
38
- * shared with non-auth settings (notably `update_channel`); a blanket unlink
39
- * would silently reset the user's update-channel preference too.
40
- *
41
- * Pass `existing` to skip the read when the caller has already loaded the
42
- * config (e.g. ref-validated logout) — keeps that flow at one read + one
43
- * write instead of two reads.
44
- */
45
- export async function clearConfig(existing) {
46
- const config = existing ?? (await getConfig());
47
- const { api_token, base_url, oauth_client_id, auth_user_id, auth_user_name, auth_team_name, ...rest } = config;
48
- void api_token;
49
- void base_url;
50
- void oauth_client_id;
51
- void auth_user_id;
52
- void auth_user_name;
53
- void auth_team_name;
54
- await setConfig(rest);
55
- }
56
74
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE/D,MAAM,gBAAgB,GAAG,4BAA4B,CAAA;AAErD,MAAM,CAAC,KAAK,UAAU,WAAW;IAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAA;IAC9C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAE7B,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAA;IAChC,IAAI,MAAM,CAAC,SAAS;QAAE,OAAO,MAAM,CAAC,SAAS,CAAA;IAE7C,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAA;AAC9F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;IACtC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAE5C,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAA;IAChC,IAAI,MAAM,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAE9D,OAAO,gBAAgB,CAAA;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IAClC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAA;IACvD,IAAI,WAAW;QAAE,OAAO,WAAW,CAAA;IAEnC,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAA;IAChC,OAAO,MAAM,CAAC,eAAe,CAAA;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAChC,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAAE,OAAO,KAAK,CAAA;IAC/C,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAA;IAChC,IAAI,MAAM,CAAC,SAAS;QAAE,OAAO,QAAQ,CAAA;IACrC,OAAO,IAAI,CAAA;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAA0B;IACxD,MAAM,MAAM,GAAG,QAAQ,IAAI,CAAC,MAAM,SAAS,EAAE,CAAC,CAAA;IAC9C,MAAM,EACF,SAAS,EACT,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,cAAc,EACd,cAAc,EACd,GAAG,IAAI,EACV,GAAG,MAAM,CAAA;IACV,KAAK,SAAS,CAAA;IACd,KAAK,QAAQ,CAAA;IACb,KAAK,eAAe,CAAA;IACpB,KAAK,YAAY,CAAA;IACjB,KAAK,cAAc,CAAA;IACnB,KAAK,cAAc,CAAA;IACnB,MAAM,SAAS,CAAC,IAAc,CAAC,CAAA;AACnC,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAA;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EACH,uBAAuB,EACvB,oBAAoB,GAEvB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,aAAa,EAAE,CAAA;AAE3E,MAAM,OAAO,YAAa,SAAQ,QAAQ;IACtC;QACI,KAAK,CACD,UAAU,EACV,2BAA2B,aAAa,gCAAgC,EACxE,CAAC,OAAO,aAAa,wBAAwB,CAAC,EAC9C,MAAM,CACT,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,cAAc,CAAA;IAC9B,CAAC;CACJ;AAED;;;;GAIG;AACH,IAAI,cAA6C,CAAA;AACjD,SAAS,UAAU;IACf,IAAI,CAAC,cAAc;QAAE,cAAc,GAAG,uBAAuB,EAAE,CAAA;IAC/D,OAAO,cAAc,CAAA;AACzB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAA;IACnD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC7B,MAAM,QAAQ,GAAG,MAAM,UAAU,EAAE,CAAC,MAAM,EAAE,CAAA;IAC5C,IAAI,CAAC,QAAQ,EAAE,KAAK;QAAE,MAAM,IAAI,YAAY,EAAE,CAAA;IAC9C,OAAO,QAAQ,CAAC,KAAK,CAAA;AACzB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;IACtC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAE5C,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAA;IAChC,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;IAC3C,IAAI,MAAM,EAAE,OAAO,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC7E,IAAI,MAAM,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC9D,OAAO,gBAAgB,CAAA;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IAClC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAA;IACvD,IAAI,WAAW;QAAE,OAAO,WAAW,CAAA;IAEnC,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAA;IAChC,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;IAC3C,IAAI,MAAM,EAAE,OAAO,CAAC,aAAa;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,aAAa,CAAA;IACtE,OAAO,MAAM,CAAC,eAAe,CAAA;AACjC,CAAC"}
@@ -1,5 +1,25 @@
1
1
  import { type CoreConfig } from '@doist/cli-core';
2
+ /**
3
+ * One row of the `users[]` array. `id` is the Outline user UUID. `token` is
4
+ * a plaintext fallback persisted only when the OS keyring is unavailable at
5
+ * write time (WSL, headless Linux, missing native binary).
6
+ */
7
+ export type StoredUser = {
8
+ id: string;
9
+ name: string;
10
+ base_url?: string;
11
+ oauth_client_id?: string;
12
+ team_name?: string;
13
+ token?: string;
14
+ };
2
15
  export type Config = CoreConfig & {
16
+ config_version?: number;
17
+ users?: StoredUser[];
18
+ default_user_id?: string;
19
+ /**
20
+ * Legacy v1 single-user fields. Read by the migration helper; removed
21
+ * from disk by `cleanupLegacyConfig` after the v2 record write succeeds.
22
+ */
3
23
  api_token?: string;
4
24
  base_url?: string;
5
25
  oauth_client_id?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,aAAa,IAAI,iBAAiB,EAClC,UAAU,IAAI,cAAc,EAC5B,YAAY,IAAI,gBAAgB,EAChC,WAAW,IAAI,eAAe,GACjC,MAAM,iBAAiB,CAAA;AAExB,MAAM,QAAQ,GAAG,aAAa,CAAA;AAW9B;;;;GAIG;AACH,MAAM,UAAU,aAAa;IACzB,OAAO,iBAAiB,CAAC,QAAQ,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC3B,OAAO,cAAc,CAAS,aAAa,EAAE,CAAC,CAAA;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc;IAC1C,OAAO,eAAe,CAAC,aAAa,EAAE,EAAE,MAAM,CAAC,CAAA;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAwB;IACvD,OAAO,gBAAgB,CAAS,aAAa,EAAE,EAAE,OAAO,CAAC,CAAA;AAC7D,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,aAAa,IAAI,iBAAiB,EAClC,UAAU,IAAI,cAAc,EAC5B,YAAY,IAAI,gBAAgB,EAChC,WAAW,IAAI,eAAe,GACjC,MAAM,iBAAiB,CAAA;AAExB,MAAM,QAAQ,GAAG,aAAa,CAAA;AAiC9B;;;;GAIG;AACH,MAAM,UAAU,aAAa;IACzB,OAAO,iBAAiB,CAAC,QAAQ,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC3B,OAAO,cAAc,CAAS,aAAa,EAAE,CAAC,CAAA;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc;IAC1C,OAAO,eAAe,CAAC,aAAa,EAAE,EAAE,MAAM,CAAC,CAAA;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAwB;IACvD,OAAO,gBAAgB,CAAS,aAAa,EAAE,EAAE,OAAO,CAAC,CAAA;AAC7D,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { CliError as CoreCliError, type CliErrorCode, type ErrorType } from '@doist/cli-core';
2
2
  export { CoreCliError as BaseCliError };
3
3
  export type { ErrorType } from '@doist/cli-core';
4
- export type ErrorCode = 'ACCOUNT_NOT_FOUND' | 'AUTH_VERIFICATION_FAILED' | 'CONFIRMATION_REQUIRED' | 'CONFLICTING_OPTIONS' | 'INVALID_PARENT' | 'MISSING_OPTION' | 'OAUTH_CALLBACK_PORT_INVALID' | 'OAUTH_CALLBACK_SERVER_FAILED' | 'OAUTH_CLIENT_ID_REQUIRED' | 'OAUTH_LOGIN_FAILED' | 'UNKNOWN_AGENT';
4
+ export type ErrorCode = 'ACCOUNT_NOT_FOUND' | 'AUTH_VERIFICATION_FAILED' | 'CONFIRMATION_REQUIRED' | 'CONFLICTING_OPTIONS' | 'INVALID_PARENT' | 'MISSING_OPTION' | 'NO_TOKEN' | 'OAUTH_CALLBACK_PORT_INVALID' | 'OAUTH_CALLBACK_SERVER_FAILED' | 'OAUTH_CLIENT_ID_REQUIRED' | 'OAUTH_LOGIN_FAILED' | 'UNKNOWN_AGENT';
5
5
  export declare class CliError extends CoreCliError<ErrorCode> {
6
6
  constructor(code: ErrorCode | CliErrorCode, message: string, hints?: string[], type?: ErrorType);
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAqC,MAAM,iBAAiB,CAAA;AAE7F,OAAO,EAAE,YAAY,IAAI,YAAY,EAAE,CAAA;AAgBvC,MAAM,OAAO,QAAS,SAAQ,YAAuB;IACjD,YACI,IAA8B,EAC9B,OAAe,EACf,KAAgB,EAChB,OAAkB,OAAO;QAEzB,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACzC,CAAC;CACJ;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAqC,MAAM,iBAAiB,CAAA;AAE7F,OAAO,EAAE,YAAY,IAAI,YAAY,EAAE,CAAA;AAiBvC,MAAM,OAAO,QAAS,SAAQ,YAAuB;IACjD,YACI,IAA8B,EAC9B,OAAe,EACf,KAAgB,EAChB,OAAkB,OAAO;QAEzB,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACzC,CAAC;CACJ;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { type MigrateAuthResult } from '@doist/cli-core/auth';
2
+ import { type OutlineAccount } from './outline-account.js';
3
+ /**
4
+ * One-time migration of v1 plaintext auth state into the v2 `users[]`
5
+ * shape. Called lazily by `createOutlineTokenStore` on first store access.
6
+ * Idempotent via the `config_version` marker — once set to `>= 2`, this
7
+ * helper short-circuits with `already-migrated`.
8
+ */
9
+ export declare function runMigrateLegacyAuth(options?: {
10
+ silent: boolean;
11
+ }): Promise<MigrateAuthResult<OutlineAccount>>;
@@ -0,0 +1,92 @@
1
+ import { migrateLegacyAuth } from '@doist/cli-core/auth';
2
+ import { fetchWithRetry } from '../transport/fetch-with-retry.js';
3
+ import { LEGACY_CLEAR_PAYLOAD, LEGACY_KEYRING_ACCOUNT, SECURE_STORE_SERVICE, } from './auth-constants.js';
4
+ import { getConfig, updateConfig } from './config.js';
5
+ import { DEFAULT_BASE_URL, makeOutlineAccount } from './outline-account.js';
6
+ import { createOutlineUserRecordStore } from './user-records.js';
7
+ /**
8
+ * Pinned to this migration's target schema. Decoupled from any future
9
+ * `config_version` bump so this helper doesn't re-run for users already
10
+ * on v2 or beyond.
11
+ */
12
+ const V2_SCHEMA_VERSION = 2;
13
+ /**
14
+ * Cap migration's `auth.info` lookup so a stalled connection can't hang
15
+ * the CLI indefinitely on first command. cli-core treats the resulting
16
+ * timeout as `identify-failed`, falling back to the legacy snapshot.
17
+ */
18
+ const IDENTIFY_TIMEOUT_MS = 10_000;
19
+ /**
20
+ * Direct `auth.info` call used only by the migration path. We bypass
21
+ * `apiRequest` (and its spinner + `getApiToken`/`getBaseUrl` cascade) so
22
+ * this module stays out of the runtime auth/token-store import graph and
23
+ * so the silent migration doesn't render a spinner during postinstall-style
24
+ * invocations.
25
+ */
26
+ async function identifyOutlineAccount(token) {
27
+ const config = await getConfig();
28
+ const baseUrl = (config.base_url ?? DEFAULT_BASE_URL).replace(/\/$/, '');
29
+ const res = await fetchWithRetry({
30
+ url: `${baseUrl}/api/auth.info`,
31
+ options: {
32
+ method: 'POST',
33
+ headers: {
34
+ 'Content-Type': 'application/json',
35
+ Authorization: `Bearer ${token}`,
36
+ },
37
+ body: JSON.stringify({}),
38
+ timeout: IDENTIFY_TIMEOUT_MS,
39
+ },
40
+ });
41
+ if (!res.ok) {
42
+ throw new Error(`auth.info failed: ${res.status} ${res.statusText}`);
43
+ }
44
+ const json = await res.json();
45
+ return makeOutlineAccount({
46
+ id: json.data.user.id,
47
+ label: json.data.user.name,
48
+ baseUrl,
49
+ oauthClientId: config.oauth_client_id ?? '',
50
+ teamName: json.data.team.name,
51
+ });
52
+ }
53
+ /**
54
+ * One-time migration of v1 plaintext auth state into the v2 `users[]`
55
+ * shape. Called lazily by `createOutlineTokenStore` on first store access.
56
+ * Idempotent via the `config_version` marker — once set to `>= 2`, this
57
+ * helper short-circuits with `already-migrated`.
58
+ */
59
+ export async function runMigrateLegacyAuth(options = { silent: true }) {
60
+ return migrateLegacyAuth({
61
+ serviceName: SECURE_STORE_SERVICE,
62
+ legacyAccount: LEGACY_KEYRING_ACCOUNT,
63
+ userRecords: createOutlineUserRecordStore(),
64
+ hasMigrated: async () => {
65
+ const config = await getConfig();
66
+ // Two signals of "already on v2": the explicit marker, or
67
+ // the structural presence of `users[]` (a fresh install that
68
+ // logged in directly via cli-core writes records without ever
69
+ // setting `config_version`, so the marker alone would
70
+ // miscount that case as "needs migration").
71
+ if ((config.config_version ?? 0) >= V2_SCHEMA_VERSION)
72
+ return true;
73
+ if ((config.users ?? []).length > 0)
74
+ return true;
75
+ return false;
76
+ },
77
+ markMigrated: async () => {
78
+ await updateConfig({ config_version: V2_SCHEMA_VERSION });
79
+ },
80
+ loadLegacyPlaintextToken: async () => {
81
+ const config = await getConfig();
82
+ return config.api_token?.trim() || null;
83
+ },
84
+ identifyAccount: identifyOutlineAccount,
85
+ cleanupLegacyConfig: async () => {
86
+ await updateConfig(LEGACY_CLEAR_PAYLOAD);
87
+ },
88
+ silent: options.silent,
89
+ logPrefix: 'outline-cli',
90
+ });
91
+ }
92
+ //# sourceMappingURL=migrate-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-auth.js","sourceRoot":"","sources":["../../src/lib/migrate-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { AuthAccount } from '@doist/cli-core/auth';
2
+ /**
3
+ * Narrow account shape persisted by the keyring-backed token store.
4
+ *
5
+ * `id` is the Outline user UUID; `label` is the user's display name.
6
+ * `baseUrl` and `oauthClientId` ride along on the account because Outline
7
+ * is self-hostable — every persisted token is tied to the instance it was
8
+ * issued for, not to a global default. `teamName` is rendered by
9
+ * `ol auth status`; it's the only field we cache for display.
10
+ */
11
+ export type OutlineAccount = AuthAccount & {
12
+ id: string;
13
+ label: string;
14
+ baseUrl: string;
15
+ oauthClientId: string;
16
+ teamName?: string;
17
+ };
18
+ export declare const DEFAULT_BASE_URL = "https://app.getoutline.com";
19
+ /** Canonical `OutlineAccount` factory. Applies the `baseUrl` default. */
20
+ export declare function makeOutlineAccount(input: {
21
+ id: string;
22
+ label: string;
23
+ baseUrl?: string;
24
+ oauthClientId?: string;
25
+ teamName?: string;
26
+ }): OutlineAccount;
@@ -0,0 +1,12 @@
1
+ export const DEFAULT_BASE_URL = 'https://app.getoutline.com';
2
+ /** Canonical `OutlineAccount` factory. Applies the `baseUrl` default. */
3
+ export function makeOutlineAccount(input) {
4
+ return {
5
+ id: input.id,
6
+ label: input.label,
7
+ baseUrl: input.baseUrl ?? DEFAULT_BASE_URL,
8
+ oauthClientId: input.oauthClientId ?? '',
9
+ teamName: input.teamName,
10
+ };
11
+ }
12
+ //# sourceMappingURL=outline-account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outline-account.js","sourceRoot":"","sources":["../../src/lib/outline-account.ts"],"names":[],"mappings":"AAmBA,MAAM,CAAC,MAAM,gBAAgB,GAAG,4BAA4B,CAAA;AAE5D,yEAAyE;AACzE,MAAM,UAAU,kBAAkB,CAAC,KAMlC;IACG,OAAO;QACH,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,gBAAgB;QAC1C,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,EAAE;QACxC,QAAQ,EAAE,KAAK,CAAC,QAAQ;KAC3B,CAAA;AACL,CAAC"}
@@ -1,3 +1,3 @@
1
1
  export declare const SKILL_NAME = "outline-cli";
2
2
  export declare const SKILL_DESCRIPTION = "Search and manage Outline wiki documents and collections via the ol CLI";
3
- export declare const SKILL_CONTENT = "# Outline CLI (ol)\n\nUse this skill when the user wants to interact with their Outline wiki/knowledge base.\n\n## Quick Reference\n\n- `ol search \"query\"` - Search documents\n- `ol doc list` - List documents\n- `ol doc get <id>` - Read a document\n- `ol doc open <id>` - Open document in browser\n- `ol doc create --title \"Title\" --collection <id>` - Create document\n- `ol col list` - List collections\n\n## Output Formats\n\nAll list commands support:\n- `--json` - JSON output (essential fields)\n- `--ndjson` - Newline-delimited JSON (streaming)\n- `--full` - Include all fields in JSON\n\n## Document References\n\nDocuments can be referenced by:\n- URL ID (the slug suffix after the last hyphen)\n- Full Outline URL (auto-extracted)\n- Document ID\n\n## Commands\n\n### Search\n```bash\nol search \"query\"\nol search \"query\" --limit 10\nol search \"query\" --collection <id>\nol search \"query\" --status published\nol search \"query\" --json\n```\n\n### Documents\n```bash\nol doc list --collection <id> --limit 25\nol doc list --sort title --direction ASC\nol doc get <id> # Rendered markdown\nol doc get <id> --raw # Raw markdown\nol doc get <id> --json\nol doc open <id> # Open in browser\nol doc create --title \"Title\" --collection <id> --text \"# Content\"\nol doc create --title \"Title\" --parent <ref> --text \"# Content\" # Nest under parent (collection inferred)\nol doc create --title \"Title\" --collection <id> --file ./doc.md\nol doc update <id> --title \"New Title\"\nol doc update <id> --file ./updated.md\nol doc move <id> --collection <target-id> # Move to collection root\nol doc move <id> --parent <ref> # Nest under parent (collection inferred)\nol doc archive <id>\nol doc unarchive <id>\nol doc delete <id> --confirm\n```\n\n### Collections\n```bash\nol col list\nol col get <id>\nol col create --name \"Name\" --description \"Desc\" --color \"#hex\"\nol col create --name \"Private\" --private\nol col update <id> --name \"New Name\"\nol col delete <id> --confirm\n```\n\n### Authentication\n```bash\nol auth login # OAuth login (opens browser); prompts for base URL + client ID if needed\nol auth login --base-url <url> # Specify Outline base URL for this login (saved for future use)\nol auth login --client-id <id> # Specify OAuth client ID for this login (saved for future use)\nol auth login --callback-port <port> # Override local OAuth callback port\nol auth login --read-only # Request read-only scopes (where supported by the Outline instance)\nol auth login --json | --ndjson # Machine-readable success envelope\nol auth status # Show current auth state\nol auth logout # Clear saved credentials\n```\n\n### Update & Changelog\n```bash\nol update # Update CLI to latest version\nol update --check # Check for updates without installing, show channel\nol update --check --json # Check for updates as a JSON envelope\nol update --check --ndjson # Check for updates as NDJSON output\nol update --channel # Show current update channel\nol update switch --stable # Switch to stable release channel\nol update switch --pre-release # Switch to pre-release (next) channel\nol changelog # Show recent changelog entries\nol changelog -n 3 # Show last 3 versions\n```\n\n## Examples\n\n### Find and read a document\n```bash\nol search \"onboarding\" --json | jq '.[0].document.urlId'\nol doc get <urlId>\n```\n\n### Create a document from a file\n```bash\nol doc create --title \"Meeting Notes\" --collection <id> --file ./notes.md --publish\n```\n\n### List all collections and their documents\n```bash\nol col list --json\nol doc list --collection <id> --sort title --direction ASC\n```\n\n### Bulk export with ndjson\n```bash\nol doc list --ndjson --full | jq -r '.title'\n```\n";
3
+ export declare const SKILL_CONTENT = "# Outline CLI (ol)\n\nUse this skill when the user wants to interact with their Outline wiki/knowledge base.\n\n## Quick Reference\n\n- `ol search \"query\"` - Search documents\n- `ol doc list` - List documents\n- `ol doc get <id>` - Read a document\n- `ol doc open <id>` - Open document in browser\n- `ol doc create --title \"Title\" --collection <id>` - Create document\n- `ol col list` - List collections\n\n## Output Formats\n\nAll list commands support:\n- `--json` - JSON output (essential fields)\n- `--ndjson` - Newline-delimited JSON (streaming)\n- `--full` - Include all fields in JSON\n\n## Document References\n\nDocuments can be referenced by:\n- URL ID (the slug suffix after the last hyphen)\n- Full Outline URL (auto-extracted)\n- Document ID\n\n## Commands\n\n### Search\n```bash\nol search \"query\"\nol search \"query\" --limit 10\nol search \"query\" --collection <id>\nol search \"query\" --status published\nol search \"query\" --json\n```\n\n### Documents\n```bash\nol doc list --collection <id> --limit 25\nol doc list --sort title --direction ASC\nol doc get <id> # Rendered markdown\nol doc get <id> --raw # Raw markdown\nol doc get <id> --json\nol doc open <id> # Open in browser\nol doc create --title \"Title\" --collection <id> --text \"# Content\"\nol doc create --title \"Title\" --parent <ref> --text \"# Content\" # Nest under parent (collection inferred)\nol doc create --title \"Title\" --collection <id> --file ./doc.md\nol doc update <id> --title \"New Title\"\nol doc update <id> --file ./updated.md\nol doc move <id> --collection <target-id> # Move to collection root\nol doc move <id> --parent <ref> # Nest under parent (collection inferred)\nol doc archive <id>\nol doc unarchive <id>\nol doc delete <id> --confirm\n```\n\n### Collections\n```bash\nol col list\nol col get <id>\nol col create --name \"Name\" --description \"Desc\" --color \"#hex\"\nol col create --name \"Private\" --private\nol col update <id> --name \"New Name\"\nol col delete <id> --confirm\n```\n\n### Authentication\n```bash\nol auth login # OAuth login (opens browser); prompts for base URL + client ID if needed\nol auth login --base-url <url> # Specify Outline base URL for this login (saved for future use)\nol auth login --client-id <id> # Specify OAuth client ID for this login (saved for future use)\nol auth login --callback-port <port> # Override local OAuth callback port\nol auth login --read-only # Request read-only scopes (where supported by the Outline instance)\nol auth login --json | --ndjson # Machine-readable success envelope\nol auth status # Show current auth state\nol auth status --json | --ndjson # Machine-readable status envelope ({id, team, baseUrl, source})\nol auth logout # Clear saved credentials\nol auth logout --json | --ndjson # Machine-readable logout envelope ({ok: true}; --ndjson is silent)\n```\n\n### Update & Changelog\n```bash\nol update # Update CLI to latest version\nol update --check # Check for updates without installing, show channel\nol update --check --json # Check for updates as a JSON envelope\nol update --check --ndjson # Check for updates as NDJSON output\nol update --channel # Show current update channel\nol update switch --stable # Switch to stable release channel\nol update switch --pre-release # Switch to pre-release (next) channel\nol changelog # Show recent changelog entries\nol changelog -n 3 # Show last 3 versions\n```\n\n## Examples\n\n### Find and read a document\n```bash\nol search \"onboarding\" --json | jq '.[0].document.urlId'\nol doc get <urlId>\n```\n\n### Create a document from a file\n```bash\nol doc create --title \"Meeting Notes\" --collection <id> --file ./notes.md --publish\n```\n\n### List all collections and their documents\n```bash\nol col list --json\nol doc list --collection <id> --sort title --direction ASC\n```\n\n### Bulk export with ndjson\n```bash\nol doc list --ndjson --full | jq -r '.title'\n```\n";
@@ -77,7 +77,9 @@ ol auth login --callback-port <port> # Override local OAuth callback port
77
77
  ol auth login --read-only # Request read-only scopes (where supported by the Outline instance)
78
78
  ol auth login --json | --ndjson # Machine-readable success envelope
79
79
  ol auth status # Show current auth state
80
+ ol auth status --json | --ndjson # Machine-readable status envelope ({id, team, baseUrl, source})
80
81
  ol auth logout # Clear saved credentials
82
+ ol auth logout --json | --ndjson # Machine-readable logout envelope ({ok: true}; --ndjson is silent)
81
83
  \`\`\`
82
84
 
83
85
  ### Update & Changelog
@@ -1 +1 @@
1
- {"version":3,"file":"content.js","sourceRoot":"","sources":["../../../src/lib/skills/content.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAA;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAC1B,yEAAyE,CAAA;AAE7E,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoH5B,CAAA"}
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../../src/lib/skills/content.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAA;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAC1B,yEAAyE,CAAA;AAE7E,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsH5B,CAAA"}
@@ -0,0 +1,14 @@
1
+ import type { UserRecord, UserRecordStore } from '@doist/cli-core/auth';
2
+ import { type Config } from './config.js';
3
+ import { type OutlineAccount } from './outline-account.js';
4
+ /**
5
+ * `UserRecordStore` adapter over `config.users[]`. `StoredUser.token` is
6
+ * surfaced as `fallbackToken` — cli-core's name for the plaintext copy
7
+ * persisted only when the keyring is unreachable.
8
+ */
9
+ export declare function createOutlineUserRecordStore(): UserRecordStore<OutlineAccount>;
10
+ /**
11
+ * Resolve the default-or-first `UserRecord` from an already-loaded config.
12
+ * Returns `null` when no users are stored.
13
+ */
14
+ export declare function getDefaultUserRecord(config: Partial<Config>): UserRecord<OutlineAccount> | null;
@@ -0,0 +1,89 @@
1
+ import { getConfig, updateConfig } from './config.js';
2
+ import { makeOutlineAccount } from './outline-account.js';
3
+ /**
4
+ * `UserRecordStore` adapter over `config.users[]`. `StoredUser.token` is
5
+ * surfaced as `fallbackToken` — cli-core's name for the plaintext copy
6
+ * persisted only when the keyring is unreachable.
7
+ */
8
+ export function createOutlineUserRecordStore() {
9
+ return {
10
+ async list() {
11
+ const config = await getConfig();
12
+ return (config.users ?? []).map(toRecord);
13
+ },
14
+ async upsert(record) {
15
+ const config = await getConfig();
16
+ const existing = config.users ?? [];
17
+ const next = fromRecord(record);
18
+ const index = existing.findIndex((u) => u.id === record.account.id);
19
+ const users = index >= 0
20
+ ? [...existing.slice(0, index), next, ...existing.slice(index + 1)]
21
+ : [...existing, next];
22
+ await updateConfig({ users });
23
+ },
24
+ async remove(id) {
25
+ const config = await getConfig();
26
+ const existing = config.users ?? [];
27
+ const index = existing.findIndex((u) => u.id === id);
28
+ if (index < 0)
29
+ return;
30
+ const users = [...existing.slice(0, index), ...existing.slice(index + 1)];
31
+ const updates = { users };
32
+ if (config.default_user_id === id)
33
+ updates.default_user_id = undefined;
34
+ await updateConfig(updates);
35
+ },
36
+ async getDefaultId() {
37
+ const config = await getConfig();
38
+ return config.default_user_id ?? null;
39
+ },
40
+ async setDefaultId(id) {
41
+ await updateConfig({ default_user_id: id ?? undefined });
42
+ },
43
+ };
44
+ }
45
+ /**
46
+ * Resolve the default-or-first `UserRecord` from an already-loaded config.
47
+ * Returns `null` when no users are stored.
48
+ */
49
+ export function getDefaultUserRecord(config) {
50
+ const users = config.users ?? [];
51
+ if (users.length === 0)
52
+ return null;
53
+ const defaultId = config.default_user_id;
54
+ const user = (defaultId && users.find((u) => u.id === defaultId)) || users[0];
55
+ return toRecord(user);
56
+ }
57
+ function toRecord(user) {
58
+ const account = makeOutlineAccount({
59
+ id: user.id,
60
+ label: user.name,
61
+ baseUrl: user.base_url,
62
+ oauthClientId: user.oauth_client_id,
63
+ teamName: user.team_name,
64
+ });
65
+ const trimmed = user.token?.trim();
66
+ const record = { account };
67
+ if (trimmed)
68
+ record.fallbackToken = trimmed;
69
+ return record;
70
+ }
71
+ function fromRecord(record) {
72
+ // Replace, don't merge: an absent `fallbackToken` strips the plaintext
73
+ // slot so it can't shadow a fresh keyring-backed write. cli-core contract.
74
+ const trimmed = record.fallbackToken?.trim();
75
+ const next = {
76
+ id: record.account.id,
77
+ name: record.account.label,
78
+ };
79
+ if (record.account.baseUrl)
80
+ next.base_url = record.account.baseUrl;
81
+ if (record.account.oauthClientId)
82
+ next.oauth_client_id = record.account.oauthClientId;
83
+ if (record.account.teamName)
84
+ next.team_name = record.account.teamName;
85
+ if (trimmed && trimmed.length > 0)
86
+ next.token = trimmed;
87
+ return next;
88
+ }
89
+ //# sourceMappingURL=user-records.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-records.js","sourceRoot":"","sources":["../../src/lib/user-records.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doist/outline-cli",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "CLI for the Outline wiki/knowledge base API",
5
5
  "type": "module",
6
6
  "bin": {
@@ -48,7 +48,7 @@
48
48
  "node": ">=20.18.1"
49
49
  },
50
50
  "dependencies": {
51
- "@doist/cli-core": "0.12.0",
51
+ "@doist/cli-core": "0.16.1",
52
52
  "chalk": "5.6.2",
53
53
  "commander": "14.0.2",
54
54
  "marked": "18.0.3",