@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.
- package/CHANGELOG.md +359 -0
- package/README.md +160 -2
- package/dist/commands/account.d.ts +2 -0
- package/dist/commands/account.js +107 -0
- package/dist/commands/account.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +169 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/changelog.d.ts +2 -0
- package/dist/commands/changelog.js +15 -0
- package/dist/commands/changelog.js.map +1 -0
- package/dist/commands/collection.d.ts +2 -0
- package/dist/commands/collection.js +106 -0
- package/dist/commands/collection.js.map +1 -0
- package/dist/commands/document.d.ts +2 -0
- package/dist/commands/document.js +291 -0
- package/dist/commands/document.js.map +1 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +49 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/skill.d.ts +2 -0
- package/dist/commands/skill.js +80 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/update/index.d.ts +2 -0
- package/dist/commands/update/index.js +14 -0
- package/dist/commands/update/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +18 -0
- package/dist/lib/api.js +107 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/auth-constants.d.ts +18 -0
- package/dist/lib/auth-constants.js +25 -0
- package/dist/lib/auth-constants.js.map +1 -0
- package/dist/lib/auth-output.d.ts +21 -0
- package/dist/lib/auth-output.js +38 -0
- package/dist/lib/auth-output.js.map +1 -0
- package/dist/lib/auth-pages.d.ts +2 -0
- package/dist/lib/auth-pages.js +101 -0
- package/dist/lib/auth-pages.js.map +1 -0
- package/dist/lib/auth-provider.d.ts +85 -0
- package/dist/lib/auth-provider.js +363 -0
- package/dist/lib/auth-provider.js.map +1 -0
- package/dist/lib/auth.d.ts +73 -0
- package/dist/lib/auth.js +188 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/config.d.ts +45 -0
- package/dist/lib/config.js +20 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/errors.d.ts +8 -0
- package/dist/lib/errors.js +9 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/global-args.d.ts +30 -0
- package/dist/lib/global-args.js +66 -0
- package/dist/lib/global-args.js.map +1 -0
- package/dist/lib/markdown.d.ts +2 -0
- package/dist/lib/markdown.js +12 -0
- package/dist/lib/markdown.js.map +1 -0
- package/dist/lib/migrate-auth.d.ts +11 -0
- package/dist/lib/migrate-auth.js +92 -0
- package/dist/lib/migrate-auth.js.map +1 -0
- package/dist/lib/outline-account.d.ts +32 -0
- package/dist/lib/outline-account.js +22 -0
- package/dist/lib/outline-account.js.map +1 -0
- package/dist/lib/output.d.ts +15 -0
- package/dist/lib/output.js +85 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/refs.d.ts +33 -0
- package/dist/lib/refs.js +182 -0
- package/dist/lib/refs.js.map +1 -0
- package/dist/lib/skills/content.d.ts +3 -0
- package/dist/lib/skills/content.js +160 -0
- package/dist/lib/skills/content.js.map +1 -0
- package/dist/lib/skills/create-installer.d.ts +9 -0
- package/dist/lib/skills/create-installer.js +77 -0
- package/dist/lib/skills/create-installer.js.map +1 -0
- package/dist/lib/skills/index.d.ts +5 -0
- package/dist/lib/skills/index.js +40 -0
- package/dist/lib/skills/index.js.map +1 -0
- package/dist/lib/skills/types.d.ts +10 -0
- package/dist/lib/skills/types.js +2 -0
- package/dist/lib/skills/types.js.map +1 -0
- package/dist/lib/skills/update-installed.d.ts +6 -0
- package/dist/lib/skills/update-installed.js +23 -0
- package/dist/lib/skills/update-installed.js.map +1 -0
- package/dist/lib/spinner.d.ts +2 -0
- package/dist/lib/spinner.js +5 -0
- package/dist/lib/spinner.js.map +1 -0
- package/dist/lib/user-records.d.ts +21 -0
- package/dist/lib/user-records.js +126 -0
- package/dist/lib/user-records.js.map +1 -0
- package/dist/lib/user-ref-store.d.ts +16 -0
- package/dist/lib/user-ref-store.js +37 -0
- package/dist/lib/user-ref-store.js.map +1 -0
- package/dist/postinstall.d.ts +1 -0
- package/dist/postinstall.js +16 -0
- package/dist/postinstall.js.map +1 -0
- package/dist/transport/fetch-with-retry.d.ts +15 -0
- package/dist/transport/fetch-with-retry.js +144 -0
- package/dist/transport/fetch-with-retry.js.map +1 -0
- package/dist/transport/http-dispatcher.d.ts +37 -0
- package/dist/transport/http-dispatcher.js +95 -0
- package/dist/transport/http-dispatcher.js.map +1 -0
- package/package.json +72 -5
- package/scripts/check-skill-sync.js +40 -0
- package/scripts/postinstall.js +12 -0
- package/scripts/sync-skill.js +30 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { attachLoginCommand, attachLogoutCommand, attachStatusCommand, attachTokenViewCommand, } from '@todoist/cli-core/auth';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { apiRequest } from '../lib/api.js';
|
|
4
|
+
import { TOKEN_ENV_VAR } from '../lib/auth-constants.js';
|
|
5
|
+
import { logClearResult, logSaveResult } from '../lib/auth-output.js';
|
|
6
|
+
import { renderError, renderSuccess } from '../lib/auth-pages.js';
|
|
7
|
+
import { createOutlineAuthProvider, createOutlineTokenStore, getActiveTokenSource, identifyAccount, prompt, resolveBaseUrl, } from '../lib/auth-provider.js';
|
|
8
|
+
import { getTokenRefreshOptions } from '../lib/auth.js';
|
|
9
|
+
import { CliError } from '../lib/errors.js';
|
|
10
|
+
import { isJsonMode } from '../lib/global-args.js';
|
|
11
|
+
import { withUserRefAware } from '../lib/user-ref-store.js';
|
|
12
|
+
const DEFAULT_OAUTH_CALLBACK_PORT = 54969;
|
|
13
|
+
function resolvePreferredCallbackPort() {
|
|
14
|
+
const raw = process.env.OUTLINE_OAUTH_CALLBACK_PORT?.trim();
|
|
15
|
+
if (!raw)
|
|
16
|
+
return DEFAULT_OAUTH_CALLBACK_PORT;
|
|
17
|
+
const parsed = Number(raw);
|
|
18
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 65_535) {
|
|
19
|
+
return DEFAULT_OAUTH_CALLBACK_PORT;
|
|
20
|
+
}
|
|
21
|
+
return parsed;
|
|
22
|
+
}
|
|
23
|
+
async function saveToken(store, token, options) {
|
|
24
|
+
if (!token) {
|
|
25
|
+
if (!process.stdin.isTTY) {
|
|
26
|
+
throw new CliError('NO_TOKEN', 'No token provided', [
|
|
27
|
+
'Pass it as an argument: ol auth token <token>',
|
|
28
|
+
'Run in an interactive terminal to be prompted for it',
|
|
29
|
+
'Set OUTLINE_API_TOKEN to authenticate without storing a token',
|
|
30
|
+
'Or use OAuth: ol auth login',
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
token = await prompt('API token: ', { hidden: true });
|
|
34
|
+
}
|
|
35
|
+
const trimmed = token.trim();
|
|
36
|
+
if (!trimmed)
|
|
37
|
+
throw new CliError('NO_TOKEN', 'No token provided');
|
|
38
|
+
const baseUrl = await resolveBaseUrl({ baseUrl: options.baseUrl });
|
|
39
|
+
// A freshly pasted token is verified by probing `auth.info`. Any failure
|
|
40
|
+
// (bad token, wrong instance, unreachable host) collapses to one stable
|
|
41
|
+
// error — never surface the raw API/network string.
|
|
42
|
+
let account;
|
|
43
|
+
try {
|
|
44
|
+
account = await identifyAccount(trimmed, baseUrl);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
throw new CliError('AUTH_VERIFICATION_FAILED', 'Could not verify the token with Outline', [
|
|
48
|
+
'Check the token value',
|
|
49
|
+
`Check --base-url matches the instance the token came from (used: ${baseUrl})`,
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
await store.set(account, trimmed);
|
|
53
|
+
const machine = isJsonMode();
|
|
54
|
+
if (!machine) {
|
|
55
|
+
console.log(chalk.green('✓'), `Saved token for ${account.label} (${account.teamName})`);
|
|
56
|
+
}
|
|
57
|
+
logSaveResult(store, machine);
|
|
58
|
+
}
|
|
59
|
+
export function registerAuthCommand(program) {
|
|
60
|
+
const auth = program.command('auth').description('Manage authentication');
|
|
61
|
+
const provider = createOutlineAuthProvider();
|
|
62
|
+
const store = createOutlineTokenStore();
|
|
63
|
+
// Honours a global `ol --user <ref>` placed before `auth status` / `auth
|
|
64
|
+
// logout`; login always targets the freshly authenticated account, so it
|
|
65
|
+
// keeps the raw store.
|
|
66
|
+
const refAware = withUserRefAware(store);
|
|
67
|
+
attachLoginCommand(auth, {
|
|
68
|
+
provider,
|
|
69
|
+
store,
|
|
70
|
+
preferredPort: resolvePreferredCallbackPort(),
|
|
71
|
+
resolveScopes: () => [],
|
|
72
|
+
renderSuccess,
|
|
73
|
+
renderError,
|
|
74
|
+
onSuccess({ view, account }) {
|
|
75
|
+
const isMachineOutput = view.json || view.ndjson;
|
|
76
|
+
if (!isMachineOutput) {
|
|
77
|
+
console.log(chalk.green(`Authenticated to ${account.teamName} as ${account.label}`));
|
|
78
|
+
}
|
|
79
|
+
logSaveResult(store, isMachineOutput);
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
.description('Authenticate with an Outline instance via OAuth')
|
|
83
|
+
.option('--base-url <url>', 'Outline base URL to use for this login (saved for future logins)')
|
|
84
|
+
.option('--client-id <clientId>', 'OAuth client ID to use for this login (saved for future logins)');
|
|
85
|
+
// `attachStatusCommand` guarantees `fetchLive` runs before `renderText` /
|
|
86
|
+
// `renderJson` within a single invocation, so the stash is always
|
|
87
|
+
// populated by the time the render hooks read it.
|
|
88
|
+
let statusData = null;
|
|
89
|
+
attachStatusCommand(auth, {
|
|
90
|
+
store: refAware,
|
|
91
|
+
description: 'Show current authentication state',
|
|
92
|
+
// Outline access tokens last ~an hour; without a refresh `auth status`
|
|
93
|
+
// can't self-heal even though normal commands do. cli-core rotates the
|
|
94
|
+
// selected account's token first and hands `fetchLive` the live one.
|
|
95
|
+
refresh: getTokenRefreshOptions(),
|
|
96
|
+
async fetchLive({ account, token }) {
|
|
97
|
+
try {
|
|
98
|
+
const [{ data: info }, source] = await Promise.all([
|
|
99
|
+
apiRequest('auth.info', {}, { token, baseUrl: account.baseUrl }),
|
|
100
|
+
// Scope the source to the selected account so `auth status
|
|
101
|
+
// --user <ref>` reports where *that* account's token lives,
|
|
102
|
+
// not the default/env source. Empty id (env/legacy snapshot)
|
|
103
|
+
// falls back to the default cascade.
|
|
104
|
+
getActiveTokenSource(account.id || undefined),
|
|
105
|
+
]);
|
|
106
|
+
statusData = { email: info.user.email, source };
|
|
107
|
+
return {
|
|
108
|
+
...account,
|
|
109
|
+
id: info.user.id,
|
|
110
|
+
label: info.user.name,
|
|
111
|
+
teamName: info.team.name,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
const message = err instanceof Error ? err.message : '';
|
|
116
|
+
if (/\b401\b/.test(message) || /Authentication required/i.test(message)) {
|
|
117
|
+
throw new CliError('NO_TOKEN', 'Not authenticated (token expired or invalid)', [
|
|
118
|
+
'Run `ol auth login` to re-authenticate',
|
|
119
|
+
]);
|
|
120
|
+
}
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
renderText({ account }) {
|
|
125
|
+
if (!statusData)
|
|
126
|
+
throw new Error('status renderText called before fetchLive');
|
|
127
|
+
return [
|
|
128
|
+
`${chalk.green('✓')} Authenticated`,
|
|
129
|
+
` Team: ${chalk.bold(account.teamName ?? '')}`,
|
|
130
|
+
` User: ${account.label} (${statusData.email})`,
|
|
131
|
+
` Base URL: ${account.baseUrl}`,
|
|
132
|
+
` Token source: ${statusData.source}`,
|
|
133
|
+
];
|
|
134
|
+
},
|
|
135
|
+
renderJson({ account }) {
|
|
136
|
+
if (!statusData)
|
|
137
|
+
throw new Error('status renderJson called before fetchLive');
|
|
138
|
+
return {
|
|
139
|
+
id: account.id,
|
|
140
|
+
team: account.teamName,
|
|
141
|
+
baseUrl: account.baseUrl,
|
|
142
|
+
source: statusData.source,
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
onNotAuthenticated() {
|
|
146
|
+
throw new CliError('NOT_AUTHENTICATED', 'Not authenticated. Run: ol auth login');
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
attachLogoutCommand(auth, {
|
|
150
|
+
store: refAware,
|
|
151
|
+
description: 'Clear saved authentication',
|
|
152
|
+
onCleared({ view }) {
|
|
153
|
+
logClearResult(store, view.json || view.ndjson);
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
const tokenCmd = auth
|
|
157
|
+
.command('token [token]')
|
|
158
|
+
.description('Save an Outline API token for CLI auth (or use the `view` subcommand)')
|
|
159
|
+
.option('--base-url <url>', 'Outline base URL the token belongs to')
|
|
160
|
+
.action((token, options) => saveToken(store, token, options));
|
|
161
|
+
attachTokenViewCommand(tokenCmd, {
|
|
162
|
+
name: 'view',
|
|
163
|
+
store: refAware,
|
|
164
|
+
envVarName: TOKEN_ENV_VAR,
|
|
165
|
+
refresh: getTokenRefreshOptions(),
|
|
166
|
+
description: 'Print the stored token for the active user (or --user <ref>) to stdout for scripts',
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,GACzB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACjE,OAAO,EAEH,yBAAyB,EACzB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EAGf,MAAM,EACN,cAAc,GACjB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE3D,MAAM,2BAA2B,GAAG,KAAK,CAAA;AAOzC,SAAS,4BAA4B;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,IAAI,EAAE,CAAA;IAC3D,IAAI,CAAC,GAAG;QAAE,OAAO,2BAA2B,CAAA;IAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;IAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,MAAM,EAAE,CAAC;QAC7D,OAAO,2BAA2B,CAAA;IACtC,CAAC;IACD,OAAO,MAAM,CAAA;AACjB,CAAC;AAED,KAAK,UAAU,SAAS,CACpB,KAAwB,EACxB,KAAyB,EACzB,OAA6B;IAE7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACvB,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,mBAAmB,EAAE;gBAChD,+CAA+C;gBAC/C,sDAAsD;gBACtD,+DAA+D;gBAC/D,6BAA6B;aAChC,CAAC,CAAA;QACN,CAAC;QACD,KAAK,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC5B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAA;IAEjE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IAElE,yEAAyE;IACzE,wEAAwE;IACxE,oDAAoD;IACpD,IAAI,OAAuB,CAAA;IAC3B,IAAI,CAAC;QACD,OAAO,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACrD,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,IAAI,QAAQ,CAAC,0BAA0B,EAAE,yCAAyC,EAAE;YACtF,uBAAuB;YACvB,oEAAoE,OAAO,GAAG;SACjF,CAAC,CAAA;IACN,CAAC;IACD,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAEjC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,mBAAmB,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;IAC3F,CAAC;IACD,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;AACjC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAA;IAEzE,MAAM,QAAQ,GAAG,yBAAyB,EAAE,CAAA;IAC5C,MAAM,KAAK,GAAsB,uBAAuB,EAAE,CAAA;IAC1D,yEAAyE;IACzE,yEAAyE;IACzE,uBAAuB;IACvB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IAExC,kBAAkB,CAAC,IAAI,EAAE;QACrB,QAAQ;QACR,KAAK;QACL,aAAa,EAAE,4BAA4B,EAAE;QAC7C,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;QACvB,aAAa;QACb,WAAW;QACX,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE;YACvB,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAA;YAChD,IAAI,CAAC,eAAe,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,OAAO,CAAC,QAAQ,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YACxF,CAAC;YACD,aAAa,CAAC,KAAK,EAAE,eAAe,CAAC,CAAA;QACzC,CAAC;KACJ,CAAC;SACG,WAAW,CAAC,iDAAiD,CAAC;SAC9D,MAAM,CACH,kBAAkB,EAClB,kEAAkE,CACrE;SACA,MAAM,CACH,wBAAwB,EACxB,iEAAiE,CACpE,CAAA;IAEL,0EAA0E;IAC1E,kEAAkE;IAClE,kDAAkD;IAClD,IAAI,UAAU,GAAsB,IAAI,CAAA;IAExC,mBAAmB,CAAiB,IAAI,EAAE;QACtC,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,mCAAmC;QAChD,uEAAuE;QACvE,uEAAuE;QACvE,qEAAqE;QACrE,OAAO,EAAE,sBAAsB,EAAE;QACjC,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;YAC9B,IAAI,CAAC;gBACD,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;oBAC/C,UAAU,CACN,WAAW,EACX,EAAE,EACF,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CACtC;oBACD,2DAA2D;oBAC3D,4DAA4D;oBAC5D,6DAA6D;oBAC7D,qCAAqC;oBACrC,oBAAoB,CAAC,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC;iBAChD,CAAC,CAAA;gBACF,UAAU,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;gBAC/C,OAAO;oBACH,GAAG,OAAO;oBACV,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE;oBAChB,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;oBACrB,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;iBAC3B,CAAA;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;gBACvD,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBACtE,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,8CAA8C,EAAE;wBAC3E,wCAAwC;qBAC3C,CAAC,CAAA;gBACN,CAAC;gBACD,MAAM,GAAG,CAAA;YACb,CAAC;QACL,CAAC;QACD,UAAU,CAAC,EAAE,OAAO,EAAE;YAClB,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;YAC7E,OAAO;gBACH,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB;gBACnC,WAAW,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE;gBAC/C,WAAW,OAAO,CAAC,KAAK,KAAK,UAAU,CAAC,KAAK,GAAG;gBAChD,eAAe,OAAO,CAAC,OAAO,EAAE;gBAChC,mBAAmB,UAAU,CAAC,MAAM,EAAE;aACzC,CAAA;QACL,CAAC;QACD,UAAU,CAAC,EAAE,OAAO,EAAE;YAClB,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;YAC7E,OAAO;gBACH,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,IAAI,EAAE,OAAO,CAAC,QAAQ;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,MAAM,EAAE,UAAU,CAAC,MAAM;aAC5B,CAAA;QACL,CAAC;QACD,kBAAkB;YACd,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,uCAAuC,CAAC,CAAA;QACpF,CAAC;KACJ,CAAC,CAAA;IAEF,mBAAmB,CAAiB,IAAI,EAAE;QACtC,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,4BAA4B;QACzC,SAAS,CAAC,EAAE,IAAI,EAAE;YACd,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,CAAA;QACnD,CAAC;KACJ,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAG,IAAI;SAChB,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,uEAAuE,CAAC;SACpF,MAAM,CAAC,kBAAkB,EAAE,uCAAuC,CAAC;SACnE,MAAM,CAAC,CAAC,KAAyB,EAAE,OAA6B,EAAE,EAAE,CACjE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CACnC,CAAA;IAEL,sBAAsB,CAAiB,QAAQ,EAAE;QAC7C,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,QAAQ;QACf,UAAU,EAAE,aAAa;QACzB,OAAO,EAAE,sBAAsB,EAAE;QACjC,WAAW,EACP,oFAAoF;KAC3F,CAAC,CAAA;AACN,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { dirname, join } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { registerChangelogCommand as registerCoreChangelogCommand } from '@todoist/cli-core/commands';
|
|
4
|
+
import packageJson from '../../package.json' with { type: 'json' };
|
|
5
|
+
const CHANGELOG_PATH = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'CHANGELOG.md');
|
|
6
|
+
const REPO_URL = packageJson.repository.url.replace(/^git\+/, '').replace(/\.git$/, '');
|
|
7
|
+
export function registerChangelogCommand(program) {
|
|
8
|
+
registerCoreChangelogCommand(program, {
|
|
9
|
+
path: CHANGELOG_PATH,
|
|
10
|
+
repoUrl: REPO_URL,
|
|
11
|
+
version: packageJson.version,
|
|
12
|
+
bulletMarkers: ['*', '-'],
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=changelog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/commands/changelog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,wBAAwB,IAAI,4BAA4B,EAAE,MAAM,4BAA4B,CAAA;AAErG,OAAO,WAAW,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AAElE,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAA;AAChG,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;AAEvF,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACrD,4BAA4B,CAAC,OAAO,EAAE;QAClC,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,QAAQ;QACjB,OAAO,EAAE,WAAW,CAAC,OAAO;QAC5B,aAAa,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;KAC5B,CAAC,CAAA;AACN,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { apiRequest } from '../lib/api.js';
|
|
3
|
+
import { formatError, getOutputOptions, outputItem, outputList } from '../lib/output.js';
|
|
4
|
+
import { resolveCollectionId, resolveCollectionRef } from '../lib/refs.js';
|
|
5
|
+
const essentialKeys = ['id', 'name', 'description', 'color', 'documentCount'];
|
|
6
|
+
function formatCollection(col) {
|
|
7
|
+
const name = chalk.bold(col.name);
|
|
8
|
+
const id = chalk.dim(col.id);
|
|
9
|
+
const count = chalk.dim(`${col.documentCount} docs`);
|
|
10
|
+
return `${name} ${id} ${count}`;
|
|
11
|
+
}
|
|
12
|
+
export function registerCollectionCommand(program) {
|
|
13
|
+
const col = program.command('collection').alias('col').description('Manage collections');
|
|
14
|
+
col.command('list')
|
|
15
|
+
.description('List collections')
|
|
16
|
+
.option('--limit <n>', 'Max results', '25')
|
|
17
|
+
.option('--offset <n>', 'Pagination offset', '0')
|
|
18
|
+
.option('--json', 'Output JSON')
|
|
19
|
+
.option('--ndjson', 'Output NDJSON')
|
|
20
|
+
.option('--full', 'Include all fields in JSON output')
|
|
21
|
+
.action(async (opts) => {
|
|
22
|
+
const { data, pagination } = await apiRequest('collections.list', {
|
|
23
|
+
limit: Number(opts.limit),
|
|
24
|
+
offset: Number(opts.offset),
|
|
25
|
+
});
|
|
26
|
+
outputList(data, formatCollection, essentialKeys, getOutputOptions(opts), pagination);
|
|
27
|
+
});
|
|
28
|
+
col.command('get <id>')
|
|
29
|
+
.description('Get collection details by ID or name')
|
|
30
|
+
.option('--json', 'Output JSON')
|
|
31
|
+
.option('--full', 'Include all fields in JSON output')
|
|
32
|
+
.action(async (id, opts) => {
|
|
33
|
+
const resolved = await resolveCollectionRef(id);
|
|
34
|
+
// If resolved from name search (collections.list), some fields may be missing
|
|
35
|
+
let data;
|
|
36
|
+
if (resolved.documentCount !== undefined) {
|
|
37
|
+
data = resolved;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const response = await apiRequest('collections.info', {
|
|
41
|
+
id: resolved.id,
|
|
42
|
+
});
|
|
43
|
+
data = response.data;
|
|
44
|
+
}
|
|
45
|
+
outputItem(data, formatCollection, essentialKeys, getOutputOptions(opts));
|
|
46
|
+
});
|
|
47
|
+
col.command('create')
|
|
48
|
+
.description('Create a collection')
|
|
49
|
+
.requiredOption('--name <name>', 'Collection name')
|
|
50
|
+
.option('--description <text>', 'Description')
|
|
51
|
+
.option('--color <hex>', 'Color hex code')
|
|
52
|
+
.option('--private', 'Make private')
|
|
53
|
+
.option('--json', 'Output JSON')
|
|
54
|
+
.action(async (opts) => {
|
|
55
|
+
const body = { name: opts.name };
|
|
56
|
+
if (opts.description)
|
|
57
|
+
body.description = opts.description;
|
|
58
|
+
if (opts.color)
|
|
59
|
+
body.color = opts.color;
|
|
60
|
+
if (opts.private)
|
|
61
|
+
body.permission = '';
|
|
62
|
+
const { data } = await apiRequest('collections.create', body);
|
|
63
|
+
if (opts.json) {
|
|
64
|
+
outputItem(data, formatCollection, essentialKeys, { json: true });
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.log(chalk.green(`Created: ${data.name}`), chalk.dim(data.id));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
col.command('update <id>')
|
|
71
|
+
.description('Update a collection')
|
|
72
|
+
.option('--name <name>', 'New name')
|
|
73
|
+
.option('--description <text>', 'New description')
|
|
74
|
+
.option('--color <hex>', 'New color')
|
|
75
|
+
.option('--json', 'Output JSON')
|
|
76
|
+
.action(async (id, opts) => {
|
|
77
|
+
const resolvedId = await resolveCollectionId(id);
|
|
78
|
+
const body = { id: resolvedId };
|
|
79
|
+
if (opts.name)
|
|
80
|
+
body.name = opts.name;
|
|
81
|
+
if (opts.description)
|
|
82
|
+
body.description = opts.description;
|
|
83
|
+
if (opts.color)
|
|
84
|
+
body.color = opts.color;
|
|
85
|
+
const { data } = await apiRequest('collections.update', body);
|
|
86
|
+
if (opts.json) {
|
|
87
|
+
outputItem(data, formatCollection, essentialKeys, { json: true });
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.log(chalk.green(`Updated: ${data.name}`), chalk.dim(data.id));
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
col.command('delete <id>')
|
|
94
|
+
.description('Delete a collection')
|
|
95
|
+
.option('--confirm', 'Skip confirmation')
|
|
96
|
+
.action(async (id, opts) => {
|
|
97
|
+
if (!opts.confirm) {
|
|
98
|
+
console.error(formatError('CONFIRMATION_REQUIRED', 'Delete operation requires confirmation.', ['Use --confirm flag to proceed with deletion']));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
const resolvedId = await resolveCollectionId(id);
|
|
102
|
+
await apiRequest('collections.delete', { id: resolvedId });
|
|
103
|
+
console.log('Deleted.');
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=collection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection.js","sourceRoot":"","sources":["../../src/commands/collection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { readStdin } from '@todoist/cli-core';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import open from 'open';
|
|
5
|
+
import { apiRequest } from '../lib/api.js';
|
|
6
|
+
import { getBaseUrl } from '../lib/auth.js';
|
|
7
|
+
import { renderMarkdown } from '../lib/markdown.js';
|
|
8
|
+
import { formatError, getOutputOptions, outputItem, outputList } from '../lib/output.js';
|
|
9
|
+
import { resolveCollectionId, resolveDocumentId, resolveDocumentRef } from '../lib/refs.js';
|
|
10
|
+
const essentialKeys = ['id', 'title', 'urlId', 'collectionId', 'updatedAt'];
|
|
11
|
+
function formatDoc(doc) {
|
|
12
|
+
const title = chalk.bold(doc.title);
|
|
13
|
+
const id = chalk.dim(doc.urlId);
|
|
14
|
+
const date = chalk.dim(new Date(doc.updatedAt).toLocaleDateString());
|
|
15
|
+
return `${title} ${id} ${date}`;
|
|
16
|
+
}
|
|
17
|
+
function formatDocFull(doc) {
|
|
18
|
+
return `# ${doc.title}\n\n${doc.text}`;
|
|
19
|
+
}
|
|
20
|
+
function exitOnConflictingTextInputs(opts) {
|
|
21
|
+
const given = [opts.text !== undefined, opts.file !== undefined, opts.stdin === true];
|
|
22
|
+
if (given.filter(Boolean).length > 1) {
|
|
23
|
+
console.error(formatError('CONFLICTING_OPTIONS', '--text, --file and --stdin are mutually exclusive.', ['Pass the document body with only one of them']));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Read before any API call, so a bad --file path or a --stdin with nothing
|
|
28
|
+
// piped in fails without a network round-trip.
|
|
29
|
+
async function readTextInput(opts) {
|
|
30
|
+
exitOnConflictingTextInputs(opts);
|
|
31
|
+
if (opts.stdin)
|
|
32
|
+
return readStdin();
|
|
33
|
+
if (opts.file)
|
|
34
|
+
return readFileSync(opts.file, 'utf-8');
|
|
35
|
+
return opts.text;
|
|
36
|
+
}
|
|
37
|
+
function extractTitleFromText(text) {
|
|
38
|
+
const lines = text.split('\n');
|
|
39
|
+
const firstLine = lines[0]?.trim();
|
|
40
|
+
if (firstLine?.startsWith('# ')) {
|
|
41
|
+
return {
|
|
42
|
+
title: firstLine.slice(2).trim(),
|
|
43
|
+
body: lines.slice(1).join('\n').replace(/^\n+/, ''),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return { body: text };
|
|
47
|
+
}
|
|
48
|
+
export function registerDocumentCommand(program) {
|
|
49
|
+
const doc = program.command('document').alias('doc').description('Manage documents');
|
|
50
|
+
doc.command('list')
|
|
51
|
+
.description('List documents')
|
|
52
|
+
.option('--collection <ref>', 'Filter by collection ID or name')
|
|
53
|
+
.option('--limit <n>', 'Max results', '25')
|
|
54
|
+
.option('--offset <n>', 'Pagination offset', '0')
|
|
55
|
+
.option('--sort <field>', 'Sort by field (title|updatedAt|createdAt)', 'updatedAt')
|
|
56
|
+
.option('--direction <dir>', 'Sort direction (ASC|DESC)', 'DESC')
|
|
57
|
+
.option('--json', 'Output JSON')
|
|
58
|
+
.option('--ndjson', 'Output NDJSON')
|
|
59
|
+
.option('--full', 'Include all fields in JSON output')
|
|
60
|
+
.action(async (opts) => {
|
|
61
|
+
const body = {
|
|
62
|
+
limit: Number(opts.limit),
|
|
63
|
+
offset: Number(opts.offset),
|
|
64
|
+
sort: opts.sort,
|
|
65
|
+
direction: opts.direction,
|
|
66
|
+
};
|
|
67
|
+
if (opts.collection) {
|
|
68
|
+
body.collectionId = await resolveCollectionId(opts.collection);
|
|
69
|
+
}
|
|
70
|
+
const { data, pagination } = await apiRequest('documents.list', body);
|
|
71
|
+
outputList(data, formatDoc, essentialKeys, getOutputOptions(opts), pagination, 'No documents found.');
|
|
72
|
+
});
|
|
73
|
+
doc.command('get <id>')
|
|
74
|
+
.description('Get a document by ID, URL, or name')
|
|
75
|
+
.option('--raw', 'Output raw markdown without terminal formatting')
|
|
76
|
+
.option('--json', 'Output JSON')
|
|
77
|
+
.option('--full', 'Include all fields in JSON output')
|
|
78
|
+
.action(async (id, opts) => {
|
|
79
|
+
const resolved = await resolveDocumentRef(id);
|
|
80
|
+
// If resolved from name search (documents.list), text may be missing
|
|
81
|
+
let data;
|
|
82
|
+
if (resolved.text !== undefined) {
|
|
83
|
+
data = resolved;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const response = await apiRequest('documents.info', {
|
|
87
|
+
id: resolved.id,
|
|
88
|
+
});
|
|
89
|
+
data = response.data;
|
|
90
|
+
}
|
|
91
|
+
const outputOpts = getOutputOptions(opts);
|
|
92
|
+
if (outputOpts.json) {
|
|
93
|
+
outputItem(data, formatDocFull, essentialKeys, outputOpts);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
const content = formatDocFull(data);
|
|
97
|
+
console.log(opts.raw ? content : await renderMarkdown(content));
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
doc.command('open <id>')
|
|
101
|
+
.description('Open a document in the browser')
|
|
102
|
+
.action(async (id) => {
|
|
103
|
+
const resolved = await resolveDocumentRef(id);
|
|
104
|
+
const fullUrl = `${await getBaseUrl()}${resolved.url}`;
|
|
105
|
+
await open(fullUrl);
|
|
106
|
+
console.log(chalk.dim(`Opened: ${fullUrl}`));
|
|
107
|
+
});
|
|
108
|
+
doc.command('create')
|
|
109
|
+
.description('Create a document')
|
|
110
|
+
.requiredOption('--title <title>', 'Document title')
|
|
111
|
+
.option('--collection <ref>', 'Collection ID or name')
|
|
112
|
+
.option('--parent <ref>', 'Parent document ID, URL, or name')
|
|
113
|
+
.option('--text <text>', 'Document body (markdown)')
|
|
114
|
+
.option('--file <path>', 'Read markdown from file')
|
|
115
|
+
.option('--stdin', 'Read markdown from stdin')
|
|
116
|
+
.option('--publish', 'Publish immediately')
|
|
117
|
+
.option('--json', 'Output JSON')
|
|
118
|
+
.action(async (opts) => {
|
|
119
|
+
if (!opts.collection && !opts.parent) {
|
|
120
|
+
console.error(formatError('MISSING_OPTION', 'Either --collection or --parent must be provided.', [
|
|
121
|
+
'Use --collection to create at a collection root',
|
|
122
|
+
'Use --parent to nest under a parent document (collection is inferred)',
|
|
123
|
+
]));
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
if (opts.collection && opts.parent) {
|
|
127
|
+
console.error(formatError('CONFLICTING_OPTIONS', '--collection and --parent are mutually exclusive.', [
|
|
128
|
+
'Use --collection to create at a collection root',
|
|
129
|
+
'Use --parent to nest under a parent document (collection is inferred)',
|
|
130
|
+
]));
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
const inputText = await readTextInput(opts);
|
|
134
|
+
const body = {
|
|
135
|
+
title: opts.title,
|
|
136
|
+
};
|
|
137
|
+
if (opts.collection) {
|
|
138
|
+
body.collectionId = await resolveCollectionId(opts.collection);
|
|
139
|
+
}
|
|
140
|
+
if (opts.parent) {
|
|
141
|
+
const parent = await resolveDocumentRef(opts.parent);
|
|
142
|
+
body.parentDocumentId = parent.id;
|
|
143
|
+
body.collectionId = parent.collectionId;
|
|
144
|
+
}
|
|
145
|
+
if (inputText)
|
|
146
|
+
body.text = inputText;
|
|
147
|
+
if (opts.publish)
|
|
148
|
+
body.publish = true;
|
|
149
|
+
const { data } = await apiRequest('documents.create', body);
|
|
150
|
+
if (opts.json) {
|
|
151
|
+
outputItem(data, formatDoc, essentialKeys, { json: true });
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
console.log(chalk.green(`Created: ${data.title}`), chalk.dim(data.urlId));
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
doc.command('update <id>')
|
|
158
|
+
.description('Update a document')
|
|
159
|
+
.option('--title <title>', 'New title')
|
|
160
|
+
.option('--text <text>', 'New body (markdown)')
|
|
161
|
+
.option('--file <path>', 'Read markdown from file')
|
|
162
|
+
.option('--stdin', 'Read markdown from stdin')
|
|
163
|
+
.option('--publish', 'Publish a draft')
|
|
164
|
+
.option('--collection <ref>', 'Collection to publish into (drafts without one only)')
|
|
165
|
+
.option('--if-updated-at <timestamp>', 'Fail if updatedAt differs (from doc get --json)')
|
|
166
|
+
.option('--json', 'Output JSON')
|
|
167
|
+
.action(async (id, opts) => {
|
|
168
|
+
if (opts.collection && !opts.publish) {
|
|
169
|
+
console.error(formatError('MISSING_OPTION', '--collection requires --publish.', [
|
|
170
|
+
'Use doc move to move a document to another collection',
|
|
171
|
+
]));
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
if (opts.ifUpdatedAt !== undefined && Number.isNaN(Date.parse(opts.ifUpdatedAt))) {
|
|
175
|
+
console.error(formatError('INVALID_TIMESTAMP', `--if-updated-at needs a timestamp, got "${opts.ifUpdatedAt}".`, ['Pass the updatedAt value printed by ol doc get --json']));
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
const rawText = await readTextInput(opts);
|
|
179
|
+
const current = (await resolveDocumentRef(id));
|
|
180
|
+
if (opts.ifUpdatedAt !== undefined &&
|
|
181
|
+
Date.parse(current.updatedAt) !== Date.parse(opts.ifUpdatedAt)) {
|
|
182
|
+
console.error(formatError('DOCUMENT_CHANGED', `Document was updated at ${current.updatedAt}, not ${opts.ifUpdatedAt}.`, ['Run ol doc get again, reapply your changes, then retry']));
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
const body = { id: current.id };
|
|
186
|
+
// Outline rejects the write if the document was saved after this revision,
|
|
187
|
+
// which covers edits landing between the check above and this update
|
|
188
|
+
if (opts.ifUpdatedAt !== undefined)
|
|
189
|
+
body.lastRevision = current.revision;
|
|
190
|
+
if (rawText && !opts.title) {
|
|
191
|
+
const { title, body: textBody } = extractTitleFromText(rawText);
|
|
192
|
+
if (title)
|
|
193
|
+
body.title = title;
|
|
194
|
+
body.text = textBody;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
if (rawText)
|
|
198
|
+
body.text = rawText;
|
|
199
|
+
if (opts.title)
|
|
200
|
+
body.title = opts.title;
|
|
201
|
+
}
|
|
202
|
+
if (opts.publish)
|
|
203
|
+
body.publish = true;
|
|
204
|
+
if (opts.collection) {
|
|
205
|
+
body.collectionId = await resolveCollectionId(opts.collection);
|
|
206
|
+
}
|
|
207
|
+
const { data } = await apiRequest('documents.update', body);
|
|
208
|
+
if (opts.json) {
|
|
209
|
+
outputItem(data, formatDoc, essentialKeys, { json: true });
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
const verb = opts.publish ? 'Published' : 'Updated';
|
|
213
|
+
console.log(chalk.green(`${verb}: ${data.title}`), chalk.dim(data.urlId));
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
doc.command('delete <id>')
|
|
217
|
+
.description('Delete a document')
|
|
218
|
+
.option('--confirm', 'Skip confirmation')
|
|
219
|
+
.action(async (id, opts) => {
|
|
220
|
+
if (!opts.confirm) {
|
|
221
|
+
console.error(formatError('CONFIRMATION_REQUIRED', 'Delete operation requires confirmation.', ['Use --confirm flag to proceed with deletion']));
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
const resolvedId = await resolveDocumentId(id);
|
|
225
|
+
await apiRequest('documents.delete', { id: resolvedId });
|
|
226
|
+
console.log('Deleted.');
|
|
227
|
+
});
|
|
228
|
+
doc.command('move <id>')
|
|
229
|
+
.description('Move a document to another collection or under a parent')
|
|
230
|
+
.option('--collection <ref>', 'Target collection ID or name')
|
|
231
|
+
.option('--parent <ref>', 'Parent document ID, URL, or name')
|
|
232
|
+
.action(async (id, opts) => {
|
|
233
|
+
if (!opts.collection && !opts.parent) {
|
|
234
|
+
console.error(formatError('MISSING_OPTION', 'Either --collection or --parent must be provided.', [
|
|
235
|
+
'Use --collection to move to a collection root',
|
|
236
|
+
'Use --parent to nest under a parent document (collection is inferred)',
|
|
237
|
+
]));
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
if (opts.collection && opts.parent) {
|
|
241
|
+
console.error(formatError('CONFLICTING_OPTIONS', '--collection and --parent are mutually exclusive.', [
|
|
242
|
+
'Use --collection to move to a collection root',
|
|
243
|
+
'Use --parent to nest under a parent document (collection is inferred)',
|
|
244
|
+
]));
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
const resolvedId = await resolveDocumentId(id);
|
|
248
|
+
const body = { id: resolvedId };
|
|
249
|
+
if (opts.collection) {
|
|
250
|
+
body.collectionId = await resolveCollectionId(opts.collection);
|
|
251
|
+
}
|
|
252
|
+
if (opts.parent) {
|
|
253
|
+
const parent = await resolveDocumentRef(opts.parent);
|
|
254
|
+
if (parent.id === resolvedId) {
|
|
255
|
+
console.error(formatError('INVALID_PARENT', 'A document cannot be its own parent.', []));
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
body.parentDocumentId = parent.id;
|
|
259
|
+
body.collectionId = parent.collectionId;
|
|
260
|
+
}
|
|
261
|
+
await apiRequest('documents.move', body);
|
|
262
|
+
console.log('Moved.');
|
|
263
|
+
});
|
|
264
|
+
doc.command('archive <id>')
|
|
265
|
+
.description('Archive a document')
|
|
266
|
+
.action(async (id) => {
|
|
267
|
+
const resolvedId = await resolveDocumentId(id);
|
|
268
|
+
await apiRequest('documents.archive', { id: resolvedId });
|
|
269
|
+
console.log('Archived.');
|
|
270
|
+
});
|
|
271
|
+
doc.command('unarchive <id>')
|
|
272
|
+
.description('Unarchive a document')
|
|
273
|
+
.action(async (id) => {
|
|
274
|
+
const resolvedId = await resolveDocumentId(id);
|
|
275
|
+
await apiRequest('documents.unarchive', { id: resolvedId });
|
|
276
|
+
console.log('Unarchived.');
|
|
277
|
+
});
|
|
278
|
+
doc.command('restore <id>')
|
|
279
|
+
.description('Restore a deleted document from the trash')
|
|
280
|
+
.option('--collection <ref>', 'Collection ID or name to restore into instead of the original (required if it is gone)')
|
|
281
|
+
.action(async (id, opts) => {
|
|
282
|
+
const resolvedId = await resolveDocumentId(id);
|
|
283
|
+
const body = { id: resolvedId };
|
|
284
|
+
if (opts.collection) {
|
|
285
|
+
body.collectionId = await resolveCollectionId(opts.collection);
|
|
286
|
+
}
|
|
287
|
+
await apiRequest('documents.restore', body);
|
|
288
|
+
console.log('Restored.');
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/commands/document.ts"],"names":[],"mappings":"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"}
|