@doist/outline-cli 0.0.1 → 1.0.1

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 (67) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +130 -29
  3. package/dist/commands/auth.d.ts +2 -0
  4. package/dist/commands/auth.js +176 -0
  5. package/dist/commands/auth.js.map +1 -0
  6. package/dist/commands/collection.d.ts +2 -0
  7. package/dist/commands/collection.js +106 -0
  8. package/dist/commands/collection.js.map +1 -0
  9. package/dist/commands/document.d.ts +2 -0
  10. package/dist/commands/document.js +191 -0
  11. package/dist/commands/document.js.map +1 -0
  12. package/dist/commands/search.d.ts +2 -0
  13. package/dist/commands/search.js +42 -0
  14. package/dist/commands/search.js.map +1 -0
  15. package/dist/commands/skill.d.ts +2 -0
  16. package/dist/commands/skill.js +80 -0
  17. package/dist/commands/skill.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +27 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/lib/api.d.ts +14 -0
  22. package/dist/lib/api.js +62 -0
  23. package/dist/lib/api.js.map +1 -0
  24. package/dist/lib/auth.d.ts +6 -0
  25. package/dist/lib/auth.js +70 -0
  26. package/dist/lib/auth.js.map +1 -0
  27. package/dist/lib/markdown.d.ts +1 -0
  28. package/dist/lib/markdown.js +7 -0
  29. package/dist/lib/markdown.js.map +1 -0
  30. package/dist/lib/oauth-server.d.ts +14 -0
  31. package/dist/lib/oauth-server.js +203 -0
  32. package/dist/lib/oauth-server.js.map +1 -0
  33. package/dist/lib/oauth.d.ts +17 -0
  34. package/dist/lib/oauth.js +38 -0
  35. package/dist/lib/oauth.js.map +1 -0
  36. package/dist/lib/output.d.ts +11 -0
  37. package/dist/lib/output.js +60 -0
  38. package/dist/lib/output.js.map +1 -0
  39. package/dist/lib/pkce.d.ts +3 -0
  40. package/dist/lib/pkce.js +16 -0
  41. package/dist/lib/pkce.js.map +1 -0
  42. package/dist/lib/refs.d.ts +33 -0
  43. package/dist/lib/refs.js +178 -0
  44. package/dist/lib/refs.js.map +1 -0
  45. package/dist/lib/skills/content.d.ts +3 -0
  46. package/dist/lib/skills/content.js +100 -0
  47. package/dist/lib/skills/content.js.map +1 -0
  48. package/dist/lib/skills/create-installer.d.ts +8 -0
  49. package/dist/lib/skills/create-installer.js +77 -0
  50. package/dist/lib/skills/create-installer.js.map +1 -0
  51. package/dist/lib/skills/index.d.ts +5 -0
  52. package/dist/lib/skills/index.js +40 -0
  53. package/dist/lib/skills/index.js.map +1 -0
  54. package/dist/lib/skills/types.d.ts +10 -0
  55. package/dist/lib/skills/types.js +2 -0
  56. package/dist/lib/skills/types.js.map +1 -0
  57. package/dist/lib/skills/update-installed.d.ts +6 -0
  58. package/dist/lib/skills/update-installed.js +23 -0
  59. package/dist/lib/skills/update-installed.js.map +1 -0
  60. package/dist/lib/spinner.d.ts +13 -0
  61. package/dist/lib/spinner.js +56 -0
  62. package/dist/lib/spinner.js.map +1 -0
  63. package/dist/postinstall.d.ts +1 -0
  64. package/dist/postinstall.js +16 -0
  65. package/dist/postinstall.js.map +1 -0
  66. package/package.json +65 -8
  67. package/scripts/postinstall.js +12 -0
@@ -0,0 +1,191 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import chalk from 'chalk';
3
+ import open from 'open';
4
+ import { apiRequest } from '../lib/api.js';
5
+ import { getBaseUrl } from '../lib/auth.js';
6
+ import { renderMarkdown } from '../lib/markdown.js';
7
+ import { formatError, getOutputOptions, outputItem, outputList } from '../lib/output.js';
8
+ import { resolveCollectionId, resolveDocumentId, resolveDocumentRef } from '../lib/refs.js';
9
+ const essentialKeys = ['id', 'title', 'urlId', 'collectionId', 'updatedAt'];
10
+ function formatDoc(doc) {
11
+ const title = chalk.bold(doc.title);
12
+ const id = chalk.dim(doc.urlId);
13
+ const date = chalk.dim(new Date(doc.updatedAt).toLocaleDateString());
14
+ return `${title} ${id} ${date}`;
15
+ }
16
+ function formatDocFull(doc) {
17
+ return `# ${doc.title}\n\n${doc.text}`;
18
+ }
19
+ function readTextInput(opts) {
20
+ if (opts.file)
21
+ return readFileSync(opts.file, 'utf-8');
22
+ return opts.text;
23
+ }
24
+ function extractTitleFromText(text) {
25
+ const lines = text.split('\n');
26
+ const firstLine = lines[0]?.trim();
27
+ if (firstLine?.startsWith('# ')) {
28
+ return {
29
+ title: firstLine.slice(2).trim(),
30
+ body: lines.slice(1).join('\n').replace(/^\n+/, ''),
31
+ };
32
+ }
33
+ return { body: text };
34
+ }
35
+ export function registerDocumentCommand(program) {
36
+ const doc = program.command('document').alias('doc').description('Manage documents');
37
+ doc.command('list')
38
+ .description('List documents')
39
+ .option('--collection <ref>', 'Filter by collection ID or name')
40
+ .option('--limit <n>', 'Max results', '25')
41
+ .option('--offset <n>', 'Pagination offset', '0')
42
+ .option('--sort <field>', 'Sort by field (title|updatedAt|createdAt)', 'updatedAt')
43
+ .option('--direction <dir>', 'Sort direction (ASC|DESC)', 'DESC')
44
+ .option('--json', 'Output JSON')
45
+ .option('--ndjson', 'Output NDJSON')
46
+ .option('--full', 'Include all fields in JSON output')
47
+ .action(async (opts) => {
48
+ const body = {
49
+ limit: Number(opts.limit),
50
+ offset: Number(opts.offset),
51
+ sort: opts.sort,
52
+ direction: opts.direction,
53
+ };
54
+ if (opts.collection) {
55
+ body.collectionId = await resolveCollectionId(opts.collection);
56
+ }
57
+ const { data, pagination } = await apiRequest('documents.list', body);
58
+ outputList(data, formatDoc, essentialKeys, getOutputOptions(opts), pagination);
59
+ });
60
+ doc.command('get <id>')
61
+ .description('Get a document by ID, URL, or name')
62
+ .option('--raw', 'Output raw markdown without terminal formatting')
63
+ .option('--json', 'Output JSON')
64
+ .option('--full', 'Include all fields in JSON output')
65
+ .action(async (id, opts) => {
66
+ const resolved = await resolveDocumentRef(id);
67
+ // If resolved from name search (documents.list), text may be missing
68
+ let data;
69
+ if (resolved.text !== undefined) {
70
+ data = resolved;
71
+ }
72
+ else {
73
+ const response = await apiRequest('documents.info', {
74
+ id: resolved.id,
75
+ });
76
+ data = response.data;
77
+ }
78
+ const outputOpts = getOutputOptions(opts);
79
+ if (outputOpts.json) {
80
+ outputItem(data, formatDocFull, essentialKeys, outputOpts);
81
+ }
82
+ else {
83
+ const content = formatDocFull(data);
84
+ console.log(opts.raw ? content : renderMarkdown(content));
85
+ }
86
+ });
87
+ doc.command('open <id>')
88
+ .description('Open a document in the browser')
89
+ .action(async (id) => {
90
+ const resolved = await resolveDocumentRef(id);
91
+ const fullUrl = `${getBaseUrl()}${resolved.url}`;
92
+ await open(fullUrl);
93
+ console.log(chalk.dim(`Opened: ${fullUrl}`));
94
+ });
95
+ doc.command('create')
96
+ .description('Create a document')
97
+ .requiredOption('--title <title>', 'Document title')
98
+ .requiredOption('--collection <ref>', 'Collection ID or name')
99
+ .option('--text <text>', 'Document body (markdown)')
100
+ .option('--file <path>', 'Read markdown from file')
101
+ .option('--publish', 'Publish immediately')
102
+ .option('--json', 'Output JSON')
103
+ .action(async (opts) => {
104
+ const collectionId = await resolveCollectionId(opts.collection);
105
+ const body = {
106
+ title: opts.title,
107
+ collectionId,
108
+ };
109
+ const text = readTextInput(opts);
110
+ if (text)
111
+ body.text = text;
112
+ if (opts.publish)
113
+ body.publish = true;
114
+ const { data } = await apiRequest('documents.create', body);
115
+ if (opts.json) {
116
+ outputItem(data, formatDoc, essentialKeys, { json: true });
117
+ }
118
+ else {
119
+ console.log(chalk.green(`Created: ${data.title}`), chalk.dim(data.urlId));
120
+ }
121
+ });
122
+ doc.command('update <id>')
123
+ .description('Update a document')
124
+ .option('--title <title>', 'New title')
125
+ .option('--text <text>', 'New body (markdown)')
126
+ .option('--file <path>', 'Read markdown from file')
127
+ .option('--json', 'Output JSON')
128
+ .action(async (id, opts) => {
129
+ const resolvedId = await resolveDocumentId(id);
130
+ const body = { id: resolvedId };
131
+ const rawText = readTextInput(opts);
132
+ if (rawText && !opts.title) {
133
+ const { title, body: textBody } = extractTitleFromText(rawText);
134
+ if (title)
135
+ body.title = title;
136
+ body.text = textBody;
137
+ }
138
+ else {
139
+ if (rawText)
140
+ body.text = rawText;
141
+ if (opts.title)
142
+ body.title = opts.title;
143
+ }
144
+ const { data } = await apiRequest('documents.update', body);
145
+ if (opts.json) {
146
+ outputItem(data, formatDoc, essentialKeys, { json: true });
147
+ }
148
+ else {
149
+ console.log(chalk.green(`Updated: ${data.title}`), chalk.dim(data.urlId));
150
+ }
151
+ });
152
+ doc.command('delete <id>')
153
+ .description('Delete a document')
154
+ .option('--confirm', 'Skip confirmation')
155
+ .action(async (id, opts) => {
156
+ if (!opts.confirm) {
157
+ console.error(formatError('CONFIRMATION_REQUIRED', 'Delete operation requires confirmation.', ['Use --confirm flag to proceed with deletion']));
158
+ process.exit(1);
159
+ }
160
+ const resolvedId = await resolveDocumentId(id);
161
+ await apiRequest('documents.delete', { id: resolvedId });
162
+ console.log('Deleted.');
163
+ });
164
+ doc.command('move <id>')
165
+ .description('Move a document to another collection')
166
+ .requiredOption('--collection <ref>', 'Target collection ID or name')
167
+ .action(async (id, opts) => {
168
+ const resolvedId = await resolveDocumentId(id);
169
+ const collectionId = await resolveCollectionId(opts.collection);
170
+ await apiRequest('documents.move', {
171
+ id: resolvedId,
172
+ collectionId,
173
+ });
174
+ console.log('Moved.');
175
+ });
176
+ doc.command('archive <id>')
177
+ .description('Archive a document')
178
+ .action(async (id) => {
179
+ const resolvedId = await resolveDocumentId(id);
180
+ await apiRequest('documents.archive', { id: resolvedId });
181
+ console.log('Archived.');
182
+ });
183
+ doc.command('unarchive <id>')
184
+ .description('Unarchive a document')
185
+ .action(async (id) => {
186
+ const resolvedId = await resolveDocumentId(id);
187
+ await apiRequest('documents.unarchive', { id: resolvedId });
188
+ console.log('Unarchived.');
189
+ });
190
+ }
191
+ //# 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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"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerSearchCommand(program: Command): void;
@@ -0,0 +1,42 @@
1
+ import chalk from 'chalk';
2
+ import { apiRequest } from '../lib/api.js';
3
+ import { getBaseUrl } from '../lib/auth.js';
4
+ import { getOutputOptions, outputList } from '../lib/output.js';
5
+ const essentialKeys = ['document', 'context'];
6
+ function formatResult(result) {
7
+ const { document, context } = result;
8
+ const title = chalk.bold(document.title);
9
+ const id = chalk.dim(document.urlId);
10
+ const link = chalk.dim(`${getBaseUrl()}${document.url}`);
11
+ const snippet = context
12
+ .replace(/<b>(.*?)<\/b>/g, (_, m) => chalk.bold(m))
13
+ .replace(/<\/?b>/g, '')
14
+ .trim()
15
+ .slice(0, 120);
16
+ return `${title} ${id}\n ${link}\n ${chalk.dim(snippet)}\n`;
17
+ }
18
+ export function registerSearchCommand(program) {
19
+ program
20
+ .command('search <query>')
21
+ .description('Search documents')
22
+ .option('--limit <n>', 'Max results', '25')
23
+ .option('--collection <id>', 'Filter by collection ID')
24
+ .option('--status <status>', 'Filter by status (published|draft|archived)')
25
+ .option('--json', 'Output JSON')
26
+ .option('--ndjson', 'Output NDJSON')
27
+ .option('--full', 'Include all fields in JSON output')
28
+ .action(async (query, opts) => {
29
+ const body = {
30
+ query,
31
+ limit: Number(opts.limit),
32
+ };
33
+ if (opts.collection)
34
+ body.collectionId = opts.collection;
35
+ if (opts.status)
36
+ body.statusFilter = [opts.status];
37
+ const { data, pagination } = await apiRequest('documents.search', body);
38
+ const outputOpts = getOutputOptions(opts);
39
+ outputList(data, formatResult, essentialKeys, outputOpts, pagination);
40
+ });
41
+ }
42
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAc/D,MAAM,aAAa,GAA2B,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;AAErE,SAAS,YAAY,CAAC,MAAoB;IACtC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAAA;IACpC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACxC,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAA;IACxD,MAAM,OAAO,GAAG,OAAO;SAClB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAClD,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,IAAI,EAAE;SACN,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAClB,OAAO,GAAG,KAAK,IAAI,EAAE,OAAO,IAAI,OAAO,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAA;AACjE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IAClD,OAAO;SACF,OAAO,CAAC,gBAAgB,CAAC;SACzB,WAAW,CAAC,kBAAkB,CAAC;SAC/B,MAAM,CAAC,aAAa,EAAE,aAAa,EAAE,IAAI,CAAC;SAC1C,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;SACtD,MAAM,CAAC,mBAAmB,EAAE,6CAA6C,CAAC;SAC1E,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC;SAC/B,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;SACnC,MAAM,CAAC,QAAQ,EAAE,mCAAmC,CAAC;SACrD,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,IAAI,EAAE,EAAE;QAClC,MAAM,IAAI,GAA4B;YAClC,KAAK;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;SAC5B,CAAA;QACD,IAAI,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,UAAU,CAAA;QACxD,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAElD,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,MAAM,UAAU,CAAiB,kBAAkB,EAAE,IAAI,CAAC,CAAA;QAEvF,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAA;QACzC,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;AACV,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerSkillCommand(program: Command): void;
@@ -0,0 +1,80 @@
1
+ import chalk from 'chalk';
2
+ import { formatError } from '../lib/output.js';
3
+ import { getInstaller, listAgents, skillInstallers } from '../lib/skills/index.js';
4
+ export function registerSkillCommand(program) {
5
+ const skill = program.command('skill').description('Manage coding agent skills/integrations');
6
+ const installCmd = skill
7
+ .command('install [agent]')
8
+ .description('Install skill for a coding agent')
9
+ .option('--local', 'Install in current project instead of global')
10
+ .option('--force', 'Overwrite existing skill file')
11
+ .action(async (agent, opts) => {
12
+ if (!agent) {
13
+ installCmd.help();
14
+ return;
15
+ }
16
+ const installer = getInstaller(agent);
17
+ if (!installer) {
18
+ const available = listAgents().join(', ');
19
+ console.error(formatError('UNKNOWN_AGENT', `Unknown agent: ${agent}`, [
20
+ `Available agents: ${available}`,
21
+ "Run 'ol skill list' to see all agents",
22
+ ]));
23
+ process.exit(1);
24
+ }
25
+ const local = opts.local ?? false;
26
+ const force = opts.force ?? false;
27
+ await installer.install(local, force);
28
+ const filepath = installer.getInstallPath(local);
29
+ console.log(chalk.green('✓'), `Installed ${installer.name} skill`);
30
+ console.log(chalk.dim(filepath));
31
+ });
32
+ const uninstallCmd = skill
33
+ .command('uninstall [agent]')
34
+ .description('Uninstall skill for a coding agent')
35
+ .option('--local', 'Remove from current project instead of global')
36
+ .action(async (agent, opts) => {
37
+ if (!agent) {
38
+ uninstallCmd.help();
39
+ return;
40
+ }
41
+ const installer = getInstaller(agent);
42
+ if (!installer) {
43
+ const available = listAgents().join(', ');
44
+ console.error(formatError('UNKNOWN_AGENT', `Unknown agent: ${agent}`, [
45
+ `Available agents: ${available}`,
46
+ "Run 'ol skill list' to see all agents",
47
+ ]));
48
+ process.exit(1);
49
+ }
50
+ const local = opts.local ?? false;
51
+ await installer.uninstall(local);
52
+ console.log(chalk.green('✓'), `Uninstalled ${installer.name} skill`);
53
+ });
54
+ skill
55
+ .command('list')
56
+ .description('List supported agents and install status')
57
+ .action(async () => {
58
+ const agents = listAgents();
59
+ console.log(chalk.bold('Available agents:'));
60
+ console.log('');
61
+ for (const agentName of agents) {
62
+ const installer = skillInstallers[agentName];
63
+ const globalInstalled = await installer.isInstalled(false);
64
+ const localInstalled = await installer.isInstalled(true);
65
+ const status = [];
66
+ if (globalInstalled)
67
+ status.push('global');
68
+ if (localInstalled)
69
+ status.push('local');
70
+ const statusStr = status.length > 0
71
+ ? chalk.green(`[${status.join(', ')}]`)
72
+ : chalk.dim('[not installed]');
73
+ console.log(` ${agentName}`);
74
+ console.log(` ${chalk.dim(installer.description)}`);
75
+ console.log(` ${statusStr}`);
76
+ console.log('');
77
+ }
78
+ });
79
+ }
80
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { registerAuthCommand } from './commands/auth.js';
4
+ import { registerCollectionCommand } from './commands/collection.js';
5
+ import { registerDocumentCommand } from './commands/document.js';
6
+ import { registerSearchCommand } from './commands/search.js';
7
+ import { registerSkillCommand } from './commands/skill.js';
8
+ const program = new Command();
9
+ program
10
+ .name('ol')
11
+ .version('0.1.0')
12
+ .description('CLI for the Outline wiki/knowledge base API')
13
+ .option('--no-spinner', 'Disable loading animations')
14
+ .addHelpText('after', `
15
+ Note for AI/LLM agents:
16
+ Use --json or --ndjson flags for unambiguous, parseable output.
17
+ Default JSON shows essential fields; use --full for all fields.`);
18
+ registerAuthCommand(program);
19
+ registerSearchCommand(program);
20
+ registerDocumentCommand(program);
21
+ registerCollectionCommand(program);
22
+ registerSkillCommand(program);
23
+ program.parseAsync().catch((err) => {
24
+ console.error(err.message);
25
+ process.exit(1);
26
+ });
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAA;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAE1D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACF,IAAI,CAAC,IAAI,CAAC;KACV,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,cAAc,EAAE,4BAA4B,CAAC;KACpD,WAAW,CACR,OAAO,EACP;;;kEAG0D,CAC7D,CAAA;AAEL,mBAAmB,CAAC,OAAO,CAAC,CAAA;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,uBAAuB,CAAC,OAAO,CAAC,CAAA;AAChC,yBAAyB,CAAC,OAAO,CAAC,CAAA;AAClC,oBAAoB,CAAC,OAAO,CAAC,CAAA;AAE7B,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IACtC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACnB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,14 @@
1
+ export interface Pagination {
2
+ offset: number;
3
+ limit: number;
4
+ nextPath?: string;
5
+ }
6
+ export interface PaginatedResult<T> {
7
+ data: T;
8
+ pagination?: Pagination;
9
+ }
10
+ /**
11
+ * Public API request function that wraps rawApiRequest with automatic spinners.
12
+ * Spinner messages are configured per API path in API_SPINNER_CONFIG.
13
+ */
14
+ export declare function apiRequest<T>(path: string, body?: object): Promise<PaginatedResult<T>>;
@@ -0,0 +1,62 @@
1
+ import { getApiToken, getBaseUrl } from './auth.js';
2
+ import { withSpinner } from './spinner.js';
3
+ /**
4
+ * Spinner configuration mapping API paths to spinner options.
5
+ * Blue for read operations, green for creates, yellow for updates/deletes.
6
+ */
7
+ const API_SPINNER_CONFIG = {
8
+ 'auth.info': { text: 'Checking authentication...', color: 'blue' },
9
+ 'documents.search': { text: 'Searching documents...', color: 'blue' },
10
+ 'documents.list': { text: 'Loading documents...', color: 'blue' },
11
+ 'documents.info': { text: 'Loading document...', color: 'blue' },
12
+ 'documents.create': { text: 'Creating document...', color: 'green' },
13
+ 'documents.update': { text: 'Updating document...', color: 'yellow' },
14
+ 'documents.delete': { text: 'Deleting document...', color: 'yellow' },
15
+ 'documents.move': { text: 'Moving document...', color: 'yellow' },
16
+ 'documents.archive': { text: 'Archiving document...', color: 'yellow' },
17
+ 'documents.unarchive': { text: 'Unarchiving document...', color: 'yellow' },
18
+ 'collections.list': { text: 'Loading collections...', color: 'blue' },
19
+ 'collections.info': { text: 'Loading collection...', color: 'blue' },
20
+ 'collections.create': { text: 'Creating collection...', color: 'green' },
21
+ 'collections.update': { text: 'Updating collection...', color: 'yellow' },
22
+ 'collections.delete': { text: 'Deleting collection...', color: 'yellow' },
23
+ };
24
+ /**
25
+ * Core API request function without spinner wrapping.
26
+ */
27
+ async function rawApiRequest(path, body = {}) {
28
+ const baseUrl = getBaseUrl();
29
+ const token = getApiToken();
30
+ const res = await fetch(`${baseUrl}/api/${path}`, {
31
+ method: 'POST',
32
+ headers: {
33
+ 'Content-Type': 'application/json',
34
+ Authorization: `Bearer ${token}`,
35
+ },
36
+ body: JSON.stringify(body),
37
+ });
38
+ if (!res.ok) {
39
+ let message = `API error: ${res.status} ${res.statusText}`;
40
+ try {
41
+ const err = (await res.json());
42
+ if (err.message)
43
+ message = `API error: ${err.message}`;
44
+ }
45
+ catch { }
46
+ throw new Error(message);
47
+ }
48
+ const json = (await res.json());
49
+ return { data: json.data, pagination: json.pagination };
50
+ }
51
+ /**
52
+ * Public API request function that wraps rawApiRequest with automatic spinners.
53
+ * Spinner messages are configured per API path in API_SPINNER_CONFIG.
54
+ */
55
+ export async function apiRequest(path, body = {}) {
56
+ const spinnerConfig = API_SPINNER_CONFIG[path] ?? {
57
+ text: 'Loading...',
58
+ color: 'blue',
59
+ };
60
+ return withSpinner(spinnerConfig, () => rawApiRequest(path, body));
61
+ }
62
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function getApiToken(): string;
2
+ export declare function getBaseUrl(): string;
3
+ export declare function getOAuthClientId(): string | undefined;
4
+ export declare function getTokenSource(): 'env' | 'config' | null;
5
+ export declare function saveConfig(token: string, baseUrl?: string, oauthClientId?: string): void;
6
+ export declare function clearConfig(): void;
@@ -0,0 +1,70 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ const CONFIG_DIR = join(homedir(), '.config', 'outline-cli');
5
+ const CONFIG_PATH = join(CONFIG_DIR, 'config.json');
6
+ const DEFAULT_BASE_URL = 'https://app.getoutline.com';
7
+ function readConfig() {
8
+ if (!existsSync(CONFIG_PATH))
9
+ return {};
10
+ try {
11
+ return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
12
+ }
13
+ catch {
14
+ return {};
15
+ }
16
+ }
17
+ export function getApiToken() {
18
+ const envToken = process.env.OUTLINE_API_TOKEN;
19
+ if (envToken)
20
+ return envToken;
21
+ const config = readConfig();
22
+ if (config.api_token)
23
+ return config.api_token;
24
+ throw new Error('No API token found. Set OUTLINE_API_TOKEN env var or run: ol auth login');
25
+ }
26
+ export function getBaseUrl() {
27
+ const envUrl = process.env.OUTLINE_URL;
28
+ if (envUrl)
29
+ return envUrl.replace(/\/$/, '');
30
+ const config = readConfig();
31
+ if (config.base_url)
32
+ return config.base_url.replace(/\/$/, '');
33
+ return DEFAULT_BASE_URL;
34
+ }
35
+ export function getOAuthClientId() {
36
+ const envClientId = process.env.OUTLINE_OAUTH_CLIENT_ID;
37
+ if (envClientId)
38
+ return envClientId;
39
+ const config = readConfig();
40
+ return config.oauth_client_id;
41
+ }
42
+ export function getTokenSource() {
43
+ if (process.env.OUTLINE_API_TOKEN)
44
+ return 'env';
45
+ const config = readConfig();
46
+ if (config.api_token)
47
+ return 'config';
48
+ return null;
49
+ }
50
+ export function saveConfig(token, baseUrl, oauthClientId) {
51
+ mkdirSync(CONFIG_DIR, { recursive: true });
52
+ const existing = readConfig();
53
+ const config = {
54
+ ...existing,
55
+ api_token: token,
56
+ };
57
+ if (baseUrl) {
58
+ config.base_url = baseUrl.replace(/\/$/, '');
59
+ }
60
+ if (oauthClientId) {
61
+ config.oauth_client_id = oauthClientId;
62
+ }
63
+ writeFileSync(CONFIG_PATH, `${JSON.stringify(config, null, 2)}\n`);
64
+ }
65
+ export function clearConfig() {
66
+ if (existsSync(CONFIG_PATH)) {
67
+ rmSync(CONFIG_PATH);
68
+ }
69
+ }
70
+ //# 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 @@
1
+ export declare function renderMarkdown(text: string): string;
@@ -0,0 +1,7 @@
1
+ import { marked } from 'marked';
2
+ import { markedTerminal } from 'marked-terminal';
3
+ marked.use(markedTerminal());
4
+ export function renderMarkdown(text) {
5
+ return marked.parse(text);
6
+ }
7
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/lib/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAA;AAE5B,MAAM,UAAU,cAAc,CAAC,IAAY;IACvC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAW,CAAA;AACvC,CAAC"}
@@ -0,0 +1,14 @@
1
+ interface OAuthServerOptions {
2
+ state: string;
3
+ timeoutMs?: number;
4
+ port?: number;
5
+ }
6
+ export interface OAuthCallbackServer {
7
+ port: number;
8
+ redirectUri: string;
9
+ waitForCode: Promise<string>;
10
+ close: () => void;
11
+ }
12
+ export declare const DEFAULT_OAUTH_CALLBACK_PORT = 54969;
13
+ export declare function startOAuthCallbackServer(options: OAuthServerOptions): Promise<OAuthCallbackServer>;
14
+ export {};