@todoist/outline-cli 0.0.0-stage → 3.0.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.
Files changed (108) hide show
  1. package/CHANGELOG.md +359 -0
  2. package/README.md +160 -2
  3. package/dist/commands/account.d.ts +2 -0
  4. package/dist/commands/account.js +107 -0
  5. package/dist/commands/account.js.map +1 -0
  6. package/dist/commands/auth.d.ts +2 -0
  7. package/dist/commands/auth.js +169 -0
  8. package/dist/commands/auth.js.map +1 -0
  9. package/dist/commands/changelog.d.ts +2 -0
  10. package/dist/commands/changelog.js +15 -0
  11. package/dist/commands/changelog.js.map +1 -0
  12. package/dist/commands/collection.d.ts +2 -0
  13. package/dist/commands/collection.js +106 -0
  14. package/dist/commands/collection.js.map +1 -0
  15. package/dist/commands/document.d.ts +2 -0
  16. package/dist/commands/document.js +291 -0
  17. package/dist/commands/document.js.map +1 -0
  18. package/dist/commands/search.d.ts +2 -0
  19. package/dist/commands/search.js +49 -0
  20. package/dist/commands/search.js.map +1 -0
  21. package/dist/commands/skill.d.ts +2 -0
  22. package/dist/commands/skill.js +80 -0
  23. package/dist/commands/skill.js.map +1 -0
  24. package/dist/commands/update/index.d.ts +2 -0
  25. package/dist/commands/update/index.js +14 -0
  26. package/dist/commands/update/index.js.map +1 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.js +56 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/lib/api.d.ts +18 -0
  31. package/dist/lib/api.js +107 -0
  32. package/dist/lib/api.js.map +1 -0
  33. package/dist/lib/auth-constants.d.ts +18 -0
  34. package/dist/lib/auth-constants.js +25 -0
  35. package/dist/lib/auth-constants.js.map +1 -0
  36. package/dist/lib/auth-output.d.ts +21 -0
  37. package/dist/lib/auth-output.js +38 -0
  38. package/dist/lib/auth-output.js.map +1 -0
  39. package/dist/lib/auth-pages.d.ts +2 -0
  40. package/dist/lib/auth-pages.js +101 -0
  41. package/dist/lib/auth-pages.js.map +1 -0
  42. package/dist/lib/auth-provider.d.ts +85 -0
  43. package/dist/lib/auth-provider.js +363 -0
  44. package/dist/lib/auth-provider.js.map +1 -0
  45. package/dist/lib/auth.d.ts +73 -0
  46. package/dist/lib/auth.js +188 -0
  47. package/dist/lib/auth.js.map +1 -0
  48. package/dist/lib/config.d.ts +45 -0
  49. package/dist/lib/config.js +20 -0
  50. package/dist/lib/config.js.map +1 -0
  51. package/dist/lib/errors.d.ts +8 -0
  52. package/dist/lib/errors.js +9 -0
  53. package/dist/lib/errors.js.map +1 -0
  54. package/dist/lib/global-args.d.ts +30 -0
  55. package/dist/lib/global-args.js +66 -0
  56. package/dist/lib/global-args.js.map +1 -0
  57. package/dist/lib/markdown.d.ts +2 -0
  58. package/dist/lib/markdown.js +12 -0
  59. package/dist/lib/markdown.js.map +1 -0
  60. package/dist/lib/migrate-auth.d.ts +11 -0
  61. package/dist/lib/migrate-auth.js +92 -0
  62. package/dist/lib/migrate-auth.js.map +1 -0
  63. package/dist/lib/outline-account.d.ts +32 -0
  64. package/dist/lib/outline-account.js +22 -0
  65. package/dist/lib/outline-account.js.map +1 -0
  66. package/dist/lib/output.d.ts +15 -0
  67. package/dist/lib/output.js +85 -0
  68. package/dist/lib/output.js.map +1 -0
  69. package/dist/lib/refs.d.ts +33 -0
  70. package/dist/lib/refs.js +182 -0
  71. package/dist/lib/refs.js.map +1 -0
  72. package/dist/lib/skills/content.d.ts +3 -0
  73. package/dist/lib/skills/content.js +160 -0
  74. package/dist/lib/skills/content.js.map +1 -0
  75. package/dist/lib/skills/create-installer.d.ts +9 -0
  76. package/dist/lib/skills/create-installer.js +77 -0
  77. package/dist/lib/skills/create-installer.js.map +1 -0
  78. package/dist/lib/skills/index.d.ts +5 -0
  79. package/dist/lib/skills/index.js +40 -0
  80. package/dist/lib/skills/index.js.map +1 -0
  81. package/dist/lib/skills/types.d.ts +10 -0
  82. package/dist/lib/skills/types.js +2 -0
  83. package/dist/lib/skills/types.js.map +1 -0
  84. package/dist/lib/skills/update-installed.d.ts +6 -0
  85. package/dist/lib/skills/update-installed.js +23 -0
  86. package/dist/lib/skills/update-installed.js.map +1 -0
  87. package/dist/lib/spinner.d.ts +2 -0
  88. package/dist/lib/spinner.js +5 -0
  89. package/dist/lib/spinner.js.map +1 -0
  90. package/dist/lib/user-records.d.ts +21 -0
  91. package/dist/lib/user-records.js +126 -0
  92. package/dist/lib/user-records.js.map +1 -0
  93. package/dist/lib/user-ref-store.d.ts +16 -0
  94. package/dist/lib/user-ref-store.js +37 -0
  95. package/dist/lib/user-ref-store.js.map +1 -0
  96. package/dist/postinstall.d.ts +1 -0
  97. package/dist/postinstall.js +16 -0
  98. package/dist/postinstall.js.map +1 -0
  99. package/dist/transport/fetch-with-retry.d.ts +15 -0
  100. package/dist/transport/fetch-with-retry.js +144 -0
  101. package/dist/transport/fetch-with-retry.js.map +1 -0
  102. package/dist/transport/http-dispatcher.d.ts +37 -0
  103. package/dist/transport/http-dispatcher.js +95 -0
  104. package/dist/transport/http-dispatcher.js.map +1 -0
  105. package/package.json +72 -5
  106. package/scripts/check-skill-sync.js +40 -0
  107. package/scripts/postinstall.js +12 -0
  108. package/scripts/sync-skill.js +30 -0
@@ -0,0 +1,188 @@
1
+ import { refreshAccessToken, SecureStoreUnavailableError, } from '@todoist/cli-core/auth';
2
+ import { TOKEN_ENV_VAR } from './auth-constants.js';
3
+ import { createOutlineAuthProvider, createOutlineTokenStore, getActiveTokenSource, } from './auth-provider.js';
4
+ import { getConfig, getConfigPath } from './config.js';
5
+ import { CliError } from './errors.js';
6
+ import { getRequestedUserRef } from './global-args.js';
7
+ import { DEFAULT_BASE_URL } from './outline-account.js';
8
+ import { getDefaultUserRecord, recordForRef } from './user-records.js';
9
+ import { withUserRefAware } from './user-ref-store.js';
10
+ export { SecureStoreUnavailableError, getActiveTokenSource, TOKEN_ENV_VAR };
11
+ export class NoTokenError extends CliError {
12
+ constructor() {
13
+ 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');
14
+ this.name = 'NoTokenError';
15
+ }
16
+ }
17
+ /**
18
+ * Module-level token-store singleton. Built lazily on first call; reused
19
+ * across every `apiRequest` so the request hot path doesn't reconstruct
20
+ * the keyring + user-record adapters per POST.
21
+ */
22
+ let storeSingleton;
23
+ function tokenStore() {
24
+ // Wrapped so a global `--user <ref>` flows into every no-ref store read on
25
+ // the request hot path (token lookup + refresh). Without `--user`,
26
+ // `getRequestedUserRef()` is undefined and the wrap is a pass-through.
27
+ if (!storeSingleton)
28
+ storeSingleton = withUserRefAware(createOutlineTokenStore());
29
+ return storeSingleton;
30
+ }
31
+ /**
32
+ * The `--user` ref to apply on the request path, or `undefined` when an
33
+ * `OUTLINE_API_TOKEN` is set — an env token wins outright, so base URL and
34
+ * client id resolve from the default account rather than the named one,
35
+ * keeping token / base URL / client id pinned to the same source.
36
+ */
37
+ function requestPathUserRef() {
38
+ if (process.env[TOKEN_ENV_VAR]?.trim())
39
+ return undefined;
40
+ return getRequestedUserRef();
41
+ }
42
+ let providerSingleton;
43
+ function authProvider() {
44
+ if (!providerSingleton)
45
+ providerSingleton = createOutlineAuthProvider();
46
+ return providerSingleton;
47
+ }
48
+ // Caller-provided O_EXCL lock so concurrent `ol` invocations don't issue
49
+ // parallel refresh grants. Resolved per-call (not cached) to honour test
50
+ // config-path mocking, mirroring `getConfigPath`.
51
+ function refreshLockPath() {
52
+ return `${getConfigPath()}.refresh.lock`;
53
+ }
54
+ /**
55
+ * Best-effort proactive rotation before a request. Returns the token to use
56
+ * (the rotated one, or the current one if no rotation was needed) so the
57
+ * caller doesn't re-read the store; `undefined` when the account isn't
58
+ * refreshable (no refresh token / env / failure) — the caller then falls back
59
+ * to `getApiToken()` and the 401 path stays authoritative. The wrapped store
60
+ * scopes the bundle to any global `--user`; `handshake` pins the token
61
+ * endpoint to that account's instance + client id.
62
+ */
63
+ export async function proactiveRefresh(handshake) {
64
+ try {
65
+ const { bundle } = await refreshAccessToken({
66
+ store: tokenStore(),
67
+ provider: authProvider(),
68
+ lockPath: refreshLockPath(),
69
+ handshake,
70
+ });
71
+ return bundle.accessToken;
72
+ }
73
+ catch {
74
+ return undefined;
75
+ }
76
+ }
77
+ /**
78
+ * Refresh wiring for cli-core's `auth status` / `auth token view` attachers,
79
+ * so both hand back a token that is usable right now rather than whatever
80
+ * was last stored. The attachers pass their own (`--user`-aware) store, so
81
+ * the handshake is resolved from the account cli-core actually selected —
82
+ * pinning the refresh to that account's instance and client id. Env, legacy
83
+ * and record-less accounts carry no refresh token and are served as-is.
84
+ */
85
+ export function getTokenRefreshOptions() {
86
+ return {
87
+ provider: authProvider(),
88
+ lockPath: refreshLockPath(),
89
+ handshake: ({ account }) => ({ baseUrl: account.baseUrl, clientId: account.oauthClientId }),
90
+ };
91
+ }
92
+ /**
93
+ * Reactive rotation after a 401. Returns `true` when the token rotated (the
94
+ * caller retries once). A rejected/absent refresh token surfaces as
95
+ * `NoTokenError` (re-login); a transient failure propagates unchanged.
96
+ */
97
+ export async function reactiveRefresh(handshake) {
98
+ try {
99
+ const result = await refreshAccessToken({
100
+ store: tokenStore(),
101
+ provider: authProvider(),
102
+ lockPath: refreshLockPath(),
103
+ force: true,
104
+ handshake,
105
+ });
106
+ return result.rotated;
107
+ }
108
+ catch (err) {
109
+ // Match on the structural `.code` rather than `instanceof`: cli-core
110
+ // throws its own CliError, and class identity isn't reliable across
111
+ // package boundaries (duplicate module instances under linking).
112
+ const code = err?.code;
113
+ if (code === 'AUTH_REFRESH_EXPIRED' || code === 'AUTH_REFRESH_UNAVAILABLE') {
114
+ throw new NoTokenError();
115
+ }
116
+ throw err;
117
+ }
118
+ }
119
+ /**
120
+ * Read the active token. Hot path: when `OUTLINE_API_TOKEN` is set we
121
+ * return it directly without consulting the token store, since
122
+ * `apiRequest` already resolves the base URL separately — going through
123
+ * `store.active()` here would trigger a redundant `getBaseUrl()` lookup
124
+ * per request just to synthesise an account we don't need.
125
+ */
126
+ export async function getApiToken() {
127
+ const envToken = process.env[TOKEN_ENV_VAR]?.trim();
128
+ if (envToken)
129
+ return envToken;
130
+ const snapshot = await tokenStore().active();
131
+ if (!snapshot?.token)
132
+ throw new NoTokenError();
133
+ return snapshot.token;
134
+ }
135
+ /**
136
+ * Account-agnostic base URL cascade: env var → default user record (v2) →
137
+ * legacy `base_url` config (v1) → built-in default. Deliberately ignores the
138
+ * global `--user` selector so the login flow (which resolves its default
139
+ * prompt through here) isn't skewed by account selection; the request path
140
+ * applies `--user` separately via {@link getRequestContext}.
141
+ */
142
+ export async function getBaseUrl() {
143
+ const envUrl = process.env.OUTLINE_URL;
144
+ if (envUrl)
145
+ return envUrl.replace(/\/$/, '');
146
+ const config = await getConfig();
147
+ const record = getDefaultUserRecord(config);
148
+ if (record?.account.baseUrl)
149
+ return record.account.baseUrl.replace(/\/$/, '');
150
+ if (config.base_url)
151
+ return config.base_url.replace(/\/$/, '');
152
+ return DEFAULT_BASE_URL;
153
+ }
154
+ /**
155
+ * Account-agnostic OAuth client id cascade: env var → default user record
156
+ * (v2) → legacy `oauth_client_id` config (v1) → undefined (caller prompts).
157
+ * Like {@link getBaseUrl}, ignores `--user` so login stays default-driven.
158
+ */
159
+ export async function getOAuthClientId() {
160
+ const envClientId = process.env.OUTLINE_OAUTH_CLIENT_ID;
161
+ if (envClientId)
162
+ return envClientId;
163
+ const config = await getConfig();
164
+ const record = getDefaultUserRecord(config);
165
+ if (record?.account.oauthClientId)
166
+ return record.account.oauthClientId;
167
+ return config.oauth_client_id;
168
+ }
169
+ /**
170
+ * Resolve the base URL — and, when a `--user` account is selected, the refresh
171
+ * handshake (its instance + client id) — for a single managed request. Falls
172
+ * back to the account-agnostic {@link getBaseUrl} cascade without `--user`.
173
+ * An unknown ref resolves no handshake and the default base URL; the wrapped
174
+ * token store then raises `ACCOUNT_NOT_FOUND` when the token is read, so the
175
+ * request never fires.
176
+ */
177
+ export async function getRequestContext() {
178
+ const ref = requestPathUserRef();
179
+ if (ref !== undefined) {
180
+ const record = recordForRef(await getConfig(), ref);
181
+ if (record) {
182
+ const baseUrl = record.account.baseUrl.replace(/\/$/, '');
183
+ return { baseUrl, handshake: { baseUrl, clientId: record.account.oauthClientId } };
184
+ }
185
+ }
186
+ return { baseUrl: await getBaseUrl() };
187
+ }
188
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { type CoreConfig } from '@todoist/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
+ /** Plaintext access-token fallback, present only when the keyring was unavailable at write time. */
14
+ token?: string;
15
+ /** Access-token expiry (unix-epoch ms); drives proactive refresh. */
16
+ access_token_expires_at?: number;
17
+ /** Refresh-token expiry (unix-epoch ms), when the server returns one. */
18
+ refresh_token_expires_at?: number;
19
+ /** Whether a refresh token is stored (keyring slot or `refresh_token`). */
20
+ has_refresh_token?: boolean;
21
+ };
22
+ export type Config = CoreConfig & {
23
+ config_version?: number;
24
+ users?: StoredUser[];
25
+ default_user_id?: string;
26
+ /**
27
+ * Legacy v1 single-user fields. Read by the migration helper; removed
28
+ * from disk by `cleanupLegacyConfig` after the v2 record write succeeds.
29
+ */
30
+ api_token?: string;
31
+ base_url?: string;
32
+ oauth_client_id?: string;
33
+ auth_user_id?: string;
34
+ auth_user_name?: string;
35
+ auth_team_name?: string;
36
+ };
37
+ /**
38
+ * Resolve the canonical config path on every call. Caching at module load
39
+ * would pin the path to the unmocked `node:os.homedir` before vitest's
40
+ * `vi.mock('node:os', …)` hoist takes effect in a fresh test file.
41
+ */
42
+ export declare function getConfigPath(): string;
43
+ export declare function getConfig(): Promise<Partial<Config>>;
44
+ export declare function setConfig(config: Config): Promise<void>;
45
+ export declare function updateConfig(updates: Partial<Config>): Promise<void>;
@@ -0,0 +1,20 @@
1
+ import { getConfigPath as coreGetConfigPath, readConfig as coreReadConfig, updateConfig as coreUpdateConfig, writeConfig as coreWriteConfig, } from '@todoist/cli-core';
2
+ const APP_NAME = 'outline-cli';
3
+ /**
4
+ * Resolve the canonical config path on every call. Caching at module load
5
+ * would pin the path to the unmocked `node:os.homedir` before vitest's
6
+ * `vi.mock('node:os', …)` hoist takes effect in a fresh test file.
7
+ */
8
+ export function getConfigPath() {
9
+ return coreGetConfigPath(APP_NAME);
10
+ }
11
+ export async function getConfig() {
12
+ return coreReadConfig(getConfigPath());
13
+ }
14
+ export async function setConfig(config) {
15
+ return coreWriteConfig(getConfigPath(), config);
16
+ }
17
+ export async function updateConfig(updates) {
18
+ return coreUpdateConfig(getConfigPath(), updates);
19
+ }
20
+ //# sourceMappingURL=config.js.map
@@ -0,0 +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,mBAAmB,CAAA;AAE1B,MAAM,QAAQ,GAAG,aAAa,CAAA;AAwC9B;;;;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"}
@@ -0,0 +1,8 @@
1
+ import { CliError as CoreCliError, type CliErrorCode, type ErrorType } from '@todoist/cli-core';
2
+ export { CoreCliError as BaseCliError };
3
+ export type { ErrorType } from '@todoist/cli-core';
4
+ export type ErrorCode = 'ACCOUNT_NOT_FOUND' | 'AUTH_VERIFICATION_FAILED' | 'CONFIRMATION_REQUIRED' | 'CONFLICTING_OPTIONS' | 'DOCUMENT_CHANGED' | 'INVALID_PARENT' | 'INVALID_TIMESTAMP' | 'INVALID_USER_FLAG' | 'MISSING_OPTION' | 'NO_TOKEN' | 'OAUTH_CALLBACK_PORT_INVALID' | 'OAUTH_CALLBACK_SERVER_FAILED' | 'OAUTH_CLIENT_ID_REQUIRED' | 'OAUTH_LOGIN_FAILED' | 'UNKNOWN_AGENT';
5
+ export declare class CliError extends CoreCliError<ErrorCode> {
6
+ constructor(code: ErrorCode | CliErrorCode, message: string, hints?: string[], type?: ErrorType);
7
+ }
8
+ export { getErrorMessage } from '@todoist/cli-core';
@@ -0,0 +1,9 @@
1
+ import { CliError as CoreCliError } from '@todoist/cli-core';
2
+ export { CoreCliError as BaseCliError };
3
+ export class CliError extends CoreCliError {
4
+ constructor(code, message, hints, type = 'error') {
5
+ super(code, message, { hints, type });
6
+ }
7
+ }
8
+ export { getErrorMessage } from '@todoist/cli-core';
9
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAqC,MAAM,mBAAmB,CAAA;AAE/F,OAAO,EAAE,YAAY,IAAI,YAAY,EAAE,CAAA;AAoBvC,MAAM,OAAO,QAAS,SAAQ,YAAuB;IACjD,YACI,IAA8B,EAC9B,OAAe,EACf,KAAgB,EAChB,IAAI,GAAc,OAAO;QAEzB,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACzC,CAAC;CACJ;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,30 @@
1
+ export declare const getGlobalArgs: () => import("@todoist/cli-core").GlobalArgs;
2
+ export declare const resetGlobalArgs: () => void;
3
+ export declare const isAccessible: () => boolean;
4
+ export declare const shouldDisableSpinner: () => boolean;
5
+ export declare function isJsonMode(): boolean;
6
+ /**
7
+ * Pre-subcommand `ol --user <ref>` selector. cli-core's `parseGlobalArgs`
8
+ * already extracts it from argv; `applyUserSelector` strips the flag before
9
+ * Commander parses, so this reads the value off the warmed cache.
10
+ */
11
+ export declare function getRequestedUserRef(): string | undefined;
12
+ /**
13
+ * Guard a root `--user` against the two common footguns before it's stripped:
14
+ * a value-less flag (`--user`, `--user=`) and a forgotten value where the next
15
+ * token is actually a command (`ol --user document list`). Pure — pass the
16
+ * pre-strip argv and the set of registered command names. Silent when `--user`
17
+ * is absent, or when it appears *after* a command (a late flag is left for
18
+ * Commander to reject as an unknown option, matching what `stripUserFlag`
19
+ * leaves in argv).
20
+ */
21
+ export declare function validateRootUserFlag(argv: string[], knownCommands: ReadonlySet<string>): void;
22
+ /**
23
+ * Entrypoint wiring for the global `--user` selector, kept here so the
24
+ * validate → warm-cache → strip order is exercised by tests rather than living
25
+ * untested in `src/index.ts`. Validates the root flag, warms the global-args
26
+ * cache off the *original* argv (so the ref survives), then rewrites
27
+ * `process.argv` with the flag stripped for Commander. Throws `INVALID_USER_FLAG`
28
+ * on a malformed root flag.
29
+ */
30
+ export declare function applyUserSelector(knownCommands: ReadonlySet<string>): void;
@@ -0,0 +1,66 @@
1
+ import { createAccessibleGate, createGlobalArgsStore, createSpinnerGate, parseGlobalArgs, stripUserFlag, } from '@todoist/cli-core';
2
+ import { CliError } from './errors.js';
3
+ const store = createGlobalArgsStore();
4
+ export const getGlobalArgs = store.get;
5
+ export const resetGlobalArgs = store.reset;
6
+ export const isAccessible = createAccessibleGate({
7
+ envVar: 'OL_ACCESSIBLE',
8
+ getArgs: store.get,
9
+ });
10
+ export const shouldDisableSpinner = createSpinnerGate({
11
+ envVar: 'OL_SPINNER',
12
+ getArgs: store.get,
13
+ });
14
+ export function isJsonMode() {
15
+ const args = store.get();
16
+ return args.json || args.ndjson;
17
+ }
18
+ /**
19
+ * Pre-subcommand `ol --user <ref>` selector. cli-core's `parseGlobalArgs`
20
+ * already extracts it from argv; `applyUserSelector` strips the flag before
21
+ * Commander parses, so this reads the value off the warmed cache.
22
+ */
23
+ export function getRequestedUserRef() {
24
+ return store.get().user;
25
+ }
26
+ /**
27
+ * Guard a root `--user` against the two common footguns before it's stripped:
28
+ * a value-less flag (`--user`, `--user=`) and a forgotten value where the next
29
+ * token is actually a command (`ol --user document list`). Pure — pass the
30
+ * pre-strip argv and the set of registered command names. Silent when `--user`
31
+ * is absent, or when it appears *after* a command (a late flag is left for
32
+ * Commander to reject as an unknown option, matching what `stripUserFlag`
33
+ * leaves in argv).
34
+ */
35
+ export function validateRootUserFlag(argv, knownCommands) {
36
+ const userIdx = argv.findIndex((a) => a === '--user' || a.startsWith('--user='));
37
+ if (userIdx === -1)
38
+ return;
39
+ const firstCmdIdx = argv.findIndex((a) => knownCommands.has(a));
40
+ if (firstCmdIdx !== -1 && userIdx > firstCmdIdx)
41
+ return;
42
+ const ref = parseGlobalArgs(argv).user;
43
+ if (!ref) {
44
+ throw new CliError('INVALID_USER_FLAG', '--user requires a value: <id|name>.', [
45
+ 'Example: ol --user scott@example.com document list',
46
+ ]);
47
+ }
48
+ if (knownCommands.has(ref)) {
49
+ throw new CliError('INVALID_USER_FLAG', `--user requires a value: got "${ref}", which looks like a command — did you forget the value?`, [`Example: ol --user scott@example.com ${ref}`]);
50
+ }
51
+ }
52
+ /**
53
+ * Entrypoint wiring for the global `--user` selector, kept here so the
54
+ * validate → warm-cache → strip order is exercised by tests rather than living
55
+ * untested in `src/index.ts`. Validates the root flag, warms the global-args
56
+ * cache off the *original* argv (so the ref survives), then rewrites
57
+ * `process.argv` with the flag stripped for Commander. Throws `INVALID_USER_FLAG`
58
+ * on a malformed root flag.
59
+ */
60
+ export function applyUserSelector(knownCommands) {
61
+ const original = process.argv.slice(2);
62
+ validateRootUserFlag(original, knownCommands);
63
+ getRequestedUserRef();
64
+ process.argv = [process.argv[0], process.argv[1], ...stripUserFlag(original)];
65
+ }
66
+ //# sourceMappingURL=global-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-args.js","sourceRoot":"","sources":["../../src/lib/global-args.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,aAAa,GAChB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,MAAM,KAAK,GAAG,qBAAqB,EAAE,CAAA;AAErC,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,GAAG,CAAA;AACtC,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC,KAAK,CAAA;AAE1C,MAAM,CAAC,MAAM,YAAY,GAAG,oBAAoB,CAAC;IAC7C,MAAM,EAAE,eAAe;IACvB,OAAO,EAAE,KAAK,CAAC,GAAG;CACrB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;IAClD,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,KAAK,CAAC,GAAG;CACrB,CAAC,CAAA;AAEF,MAAM,UAAU,UAAU;IACtB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAA;IACxB,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAA;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IAC/B,OAAO,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAA;AAC3B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAc,EAAE,aAAkC;IACnF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAA;IAChF,IAAI,OAAO,KAAK,CAAC,CAAC;QAAE,OAAM;IAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IAC/D,IAAI,WAAW,KAAK,CAAC,CAAC,IAAI,OAAO,GAAG,WAAW;QAAE,OAAM;IAEvD,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAA;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,qCAAqC,EAAE;YAC3E,oDAAoD;SACvD,CAAC,CAAA;IACN,CAAC;IACD,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,QAAQ,CACd,mBAAmB,EACnB,iCAAiC,GAAG,2DAA2D,EAC/F,CAAC,wCAAwC,GAAG,EAAE,CAAC,CAClD,CAAA;IACL,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,aAAkC;IAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACtC,oBAAoB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;IAC7C,mBAAmB,EAAE,CAAA;IACrB,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;AACjF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function preloadMarkdown(): Promise<void>;
2
+ export declare function renderMarkdown(text: string): Promise<string>;
@@ -0,0 +1,12 @@
1
+ import { preloadMarkdown as corePreloadMarkdown, renderMarkdown as coreRenderMarkdown, } from '@todoist/cli-core/markdown';
2
+ let preloadPromise = null;
3
+ export async function preloadMarkdown() {
4
+ if (!preloadPromise)
5
+ preloadPromise = corePreloadMarkdown();
6
+ return preloadPromise;
7
+ }
8
+ export async function renderMarkdown(text) {
9
+ await preloadMarkdown();
10
+ return coreRenderMarkdown(text);
11
+ }
12
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/lib/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,eAAe,IAAI,mBAAmB,EACtC,cAAc,IAAI,kBAAkB,GACvC,MAAM,4BAA4B,CAAA;AAEnC,IAAI,cAAc,GAAyB,IAAI,CAAA;AAE/C,MAAM,CAAC,KAAK,UAAU,eAAe;IACjC,IAAI,CAAC,cAAc;QAAE,cAAc,GAAG,mBAAmB,EAAE,CAAA;IAC3D,OAAO,cAAc,CAAA;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC7C,MAAM,eAAe,EAAE,CAAA;IACvB,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAA;AACnC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type MigrateAuthResult } from '@todoist/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 '@todoist/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,32 @@
1
+ import type { AccountRef, AuthAccount } from '@todoist/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;
27
+ /**
28
+ * Accepts the Outline user UUID or display name. Id matches are
29
+ * case-sensitive (UUIDs are canonical); label matches are case-insensitive
30
+ * so users can pass the name they see in `auth status`.
31
+ */
32
+ export declare function matchOutlineAccount(account: OutlineAccount, ref: AccountRef): boolean;
@@ -0,0 +1,22 @@
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
+ /**
13
+ * Accepts the Outline user UUID or display name. Id matches are
14
+ * case-sensitive (UUIDs are canonical); label matches are case-insensitive
15
+ * so users can pass the name they see in `auth status`.
16
+ */
17
+ export function matchOutlineAccount(account, ref) {
18
+ if (account.id === ref)
19
+ return true;
20
+ return account.label.toLowerCase() === ref.toLowerCase();
21
+ }
22
+ //# 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;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAuB,EAAE,GAAe;IACxE,IAAI,OAAO,CAAC,EAAE,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACnC,OAAO,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE,CAAA;AAC5D,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type ViewOptions } from '@todoist/cli-core';
2
+ import type { Pagination } from './api.js';
3
+ import { BaseCliError } from './errors.js';
4
+ type AnyCliError = BaseCliError<string>;
5
+ export type OutputOptions = ViewOptions & {
6
+ full?: boolean;
7
+ };
8
+ export declare function getOutputOptions(opts: Record<string, unknown>): OutputOptions;
9
+ export declare function outputItem<T extends object>(item: T, humanFormatter: (item: T) => string, essentialKeys?: (keyof T)[], opts?: OutputOptions): void;
10
+ export declare function outputList<T extends object>(items: T[], humanFormatter: (item: T) => string, essentialKeys?: (keyof T)[], opts?: OutputOptions, pagination?: Pagination, emptyMessage?: string): void;
11
+ export declare function formatError(error: AnyCliError): string;
12
+ export declare function formatError(code: string, message: string, hints?: string[]): string;
13
+ export declare function formatErrorJson(error: AnyCliError): string;
14
+ export declare function formatErrorJson(code: string, message: string, hints?: string[]): string;
15
+ export {};