Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/__tests__/empty-output.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { describeEmptyMachineOutput } from '@doist/cli-core/testing'
import { Command } from 'commander'
import { vi } from 'vitest'

vi.mock('../lib/auth.js', () => ({
getApiToken: async () => 'test-token',
getBaseUrl: async () => 'https://test.outline.com',
getOAuthClientId: async () => undefined,
getTokenSource: async () => 'config' as const,
saveConfig: vi.fn(),
clearConfig: vi.fn(),
}))

vi.mock('../lib/api.js', () => ({
apiRequest: vi.fn().mockResolvedValue({ data: [], pagination: undefined }),
}))

describeEmptyMachineOutput('ol document list', {
Comment thread
scottlovegrove marked this conversation as resolved.
setup: () => {},
run: async (extraArgs) => {
const { registerDocumentCommand } = await import('../commands/document.js')
const program = new Command()
program.exitOverride()
registerDocumentCommand(program)
await program.parseAsync(['node', 'ol', 'document', 'list', ...extraArgs])
},
humanMessage: 'No documents found.',
})
20 changes: 20 additions & 0 deletions src/__tests__/spinner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,24 @@ describe('spinner wiring', () => {
process.argv = ['node', 'ol', 'auth', 'status', '--no-spinner']
expect((await loadIsDisabled())()).toBe(true)
})

it('disables when --progress-jsonl is in argv', async () => {
process.argv = ['node', 'ol', 'search', 'foo', '--progress-jsonl']
expect((await loadIsDisabled())()).toBe(true)
})

it('disables when --progress-jsonl=path is in argv', async () => {
process.argv = ['node', 'ol', 'search', 'foo', '--progress-jsonl=/tmp/p.jsonl']
expect((await loadIsDisabled())()).toBe(true)
})

it('disables when --verbose is in argv', async () => {
process.argv = ['node', 'ol', 'search', 'foo', '--verbose']
expect((await loadIsDisabled())()).toBe(true)
})

it('disables when -v short flag is in argv', async () => {
process.argv = ['node', 'ol', 'search', 'foo', '-v']
expect((await loadIsDisabled())()).toBe(true)
})
})
9 changes: 8 additions & 1 deletion src/commands/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,14 @@ export function registerDocumentCommand(program: Command): void {

const { data, pagination } = await apiRequest<Document[]>('documents.list', body)

outputList(data, formatDoc, essentialKeys, getOutputOptions(opts), pagination)
outputList(
data,
formatDoc,
essentialKeys,
getOutputOptions(opts),
pagination,
'No documents found.',
)
})

doc.command('get <id>')
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ program
.version('0.1.0')
.description('CLI for the Outline wiki/knowledge base API')
.option('--no-spinner', 'Disable loading animations')
.option('--accessible', 'Render output in screen-reader-friendly mode')
.addHelpText(
'after',
`
Expand Down
16 changes: 16 additions & 0 deletions src/lib/global-args.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createAccessibleGate, createGlobalArgsStore, createSpinnerGate } from '@doist/cli-core'

const store = createGlobalArgsStore()

export const getGlobalArgs = store.get
export const resetGlobalArgs = store.reset

export const isAccessible = createAccessibleGate({
Comment thread
scottlovegrove marked this conversation as resolved.
envVar: 'OL_ACCESSIBLE',
getArgs: store.get,
})

export const shouldDisableSpinner = createSpinnerGate({
envVar: 'OL_SPINNER',
getArgs: store.get,
})
12 changes: 8 additions & 4 deletions src/lib/output.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { formatJson, formatNdjson } from '@doist/cli-core'
import { formatJson, formatNdjson, printEmpty, type ViewOptions } from '@doist/cli-core'
import chalk from 'chalk'
import type { Pagination } from './api.js'

interface OutputOptions {
json?: boolean
ndjson?: boolean
export type OutputOptions = ViewOptions & {
Comment thread
scottlovegrove marked this conversation as resolved.
full?: boolean
}

Expand Down Expand Up @@ -41,7 +39,13 @@ export function outputList<T extends object>(
essentialKeys?: (keyof T)[],
opts: OutputOptions = {},
pagination?: Pagination,
emptyMessage?: string,
): void {
if (items.length === 0 && emptyMessage !== undefined) {
printEmpty({ options: opts, message: emptyMessage })
return
}

const project = (item: T) => (opts.full || !essentialKeys ? item : pick(item, essentialKeys))

if (opts.ndjson) {
Expand Down
13 changes: 1 addition & 12 deletions src/lib/spinner.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
import { createSpinner } from '@doist/cli-core'
import { shouldDisableSpinner } from './global-args.js'

export type { SpinnerColor, SpinnerOptions } from '@doist/cli-core'

function shouldDisableSpinner(): boolean {
if (process.env.OL_SPINNER === 'false') return true
if (process.env.CI && process.env.CI !== 'false') return true

const args = process.argv
if (args.includes('--json') || args.includes('--ndjson') || args.includes('--no-spinner')) {
return true
}

return false
}

const spinner = createSpinner({ isDisabled: shouldDisableSpinner })

export const { LoadingSpinner, withSpinner, startEarlySpinner, stopEarlySpinner } = spinner
Loading