@verbatims/cli 0.1.6 → 0.1.8
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/package.json +1 -1
- package/src/commands/quotes.ts +50 -1
- package/src/commands/themes.ts +45 -4
package/package.json
CHANGED
package/src/commands/quotes.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Command } from 'commander'
|
|
2
|
-
import { text, isCancel, cancel, confirm } from '@clack/prompts'
|
|
2
|
+
import { text, isCancel, cancel, confirm, select } from '@clack/prompts'
|
|
3
3
|
import chalk from 'chalk'
|
|
4
4
|
import { getClient } from '../utils/client.js'
|
|
5
5
|
import { output, type Format } from '../utils/format.js'
|
|
@@ -21,6 +21,7 @@ export function registerQuotesCommand(program: Command) {
|
|
|
21
21
|
.option('--author <id>', 'Filter by author ID')
|
|
22
22
|
.option('--tag <name>', 'Filter by tag')
|
|
23
23
|
.option('--search <q>', 'Search in quote text')
|
|
24
|
+
.option('--status <status>', 'Filter by status (draft|pending|approved|rejected)')
|
|
24
25
|
.option('--sort-by <field>', 'Sort field')
|
|
25
26
|
.option('--sort-order <order>', 'Sort order (asc|desc)')
|
|
26
27
|
.action(async (options: Record<string, string>) => {
|
|
@@ -34,6 +35,8 @@ export function registerQuotesCommand(program: Command) {
|
|
|
34
35
|
author_id: options.author ? Number(options.author) : undefined,
|
|
35
36
|
tag: options.tag,
|
|
36
37
|
search: options.search,
|
|
38
|
+
q: options.search,
|
|
39
|
+
status: options.status as any,
|
|
37
40
|
sort_by: options.sortBy,
|
|
38
41
|
sort_order: options.sortOrder as 'asc' | 'desc',
|
|
39
42
|
}),
|
|
@@ -121,6 +124,49 @@ export function registerQuotesCommand(program: Command) {
|
|
|
121
124
|
console.log(chalk.green(` Quote #${id} deleted`))
|
|
122
125
|
})
|
|
123
126
|
|
|
127
|
+
quotes
|
|
128
|
+
.command('submit <id>')
|
|
129
|
+
.description('Submit a draft quote for review (draft → pending)')
|
|
130
|
+
.action(async (id: string) => {
|
|
131
|
+
const client = await getClient()
|
|
132
|
+
const format = getFormat(program)
|
|
133
|
+
const { data } = await withSpinner('Submitting quote', () => client.quotes.submit(Number(id)), format)
|
|
134
|
+
console.log(chalk.green(' Quote submitted for review'))
|
|
135
|
+
output(data, format)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
quotes
|
|
139
|
+
.command('moderate <id>')
|
|
140
|
+
.description('Moderate a pending quote (pending → approved|rejected)')
|
|
141
|
+
.option('--action <action>', 'Action to take: approve or reject')
|
|
142
|
+
.option('--reason <reason>', 'Rejection reason (required when rejecting)')
|
|
143
|
+
.action(async (id: string, options: Record<string, string>) => {
|
|
144
|
+
const client = await getClient()
|
|
145
|
+
const format = getFormat(program)
|
|
146
|
+
|
|
147
|
+
const action = options.action ?? await select({
|
|
148
|
+
message: 'Action',
|
|
149
|
+
options: [
|
|
150
|
+
{ value: 'approve', label: 'Approve' },
|
|
151
|
+
{ value: 'reject', label: 'Reject' },
|
|
152
|
+
],
|
|
153
|
+
})
|
|
154
|
+
if (isCancel(action)) cancel('Cancelled')
|
|
155
|
+
|
|
156
|
+
let rejection_reason: string | undefined | null
|
|
157
|
+
if (action === 'reject') {
|
|
158
|
+
rejection_reason = options.reason ?? await text({ message: 'Rejection reason' }) as string
|
|
159
|
+
if (isCancel(rejection_reason)) cancel('Cancelled')
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const { data } = await withSpinner('Moderating quote', () =>
|
|
163
|
+
client.quotes.moderate(Number(id), { action: action as 'approve' | 'reject', rejection_reason }),
|
|
164
|
+
format,
|
|
165
|
+
)
|
|
166
|
+
console.log(chalk.green(` Quote ${action === 'approve' ? 'approved' : 'rejected'}`))
|
|
167
|
+
output(data, format)
|
|
168
|
+
})
|
|
169
|
+
|
|
124
170
|
quotes
|
|
125
171
|
.command('browse')
|
|
126
172
|
.description('Browse quotes interactively')
|
|
@@ -128,6 +174,7 @@ export function registerQuotesCommand(program: Command) {
|
|
|
128
174
|
.option('--author <id>', 'Filter by author ID')
|
|
129
175
|
.option('--tag <name>', 'Filter by tag')
|
|
130
176
|
.option('--search <q>', 'Search in quote text')
|
|
177
|
+
.option('--status <status>', 'Filter by status (draft|pending|approved|rejected)')
|
|
131
178
|
.option('--sort-by <field>', 'Sort field')
|
|
132
179
|
.option('--sort-order <order>', 'Sort order (asc|desc)')
|
|
133
180
|
.action(async (options: Record<string, string>) => {
|
|
@@ -140,6 +187,8 @@ export function registerQuotesCommand(program: Command) {
|
|
|
140
187
|
author_id: options.author ? Number(options.author) : undefined,
|
|
141
188
|
tag: options.tag,
|
|
142
189
|
search: options.search,
|
|
190
|
+
q: options.search,
|
|
191
|
+
status: options.status as any,
|
|
143
192
|
sort_by: options.sortBy,
|
|
144
193
|
sort_order: options.sortOrder as 'asc' | 'desc',
|
|
145
194
|
}),
|
package/src/commands/themes.ts
CHANGED
|
@@ -57,7 +57,11 @@ export function registerThemesCommand(program: Command) {
|
|
|
57
57
|
.option('--active', 'Set as active')
|
|
58
58
|
.option('--default', 'Set as default')
|
|
59
59
|
.option('--priority <n>', 'Priority', '0')
|
|
60
|
-
.
|
|
60
|
+
.option('--scheduled-start <date>', 'Scheduled start date (ISO 8601)')
|
|
61
|
+
.option('--scheduled-end <date>', 'Scheduled end date (ISO 8601)')
|
|
62
|
+
.option('--config <json>', 'Theme configuration as JSON')
|
|
63
|
+
.option('--translation <lang:name:desc>', 'Add a translation (can be repeated)', (val: string, prev: string[]) => { prev.push(val); return prev }, [])
|
|
64
|
+
.action(async (options: Record<string, string | string[]>) => {
|
|
61
65
|
const client = await getClient()
|
|
62
66
|
const format = getFormat(program)
|
|
63
67
|
|
|
@@ -70,15 +74,33 @@ export function registerThemesCommand(program: Command) {
|
|
|
70
74
|
const description = options.description ?? await text({ message: 'Description (optional)', initialValue: '' })
|
|
71
75
|
if (isCancel(description)) cancel('Cancelled')
|
|
72
76
|
|
|
77
|
+
const translations = Array.isArray(options.translation) ? options.translation.map((t: string) => {
|
|
78
|
+
const [lang, tName, tDesc] = t.split(':')
|
|
79
|
+
return { language: lang!, name: tName!, description: tDesc || null }
|
|
80
|
+
}) : undefined
|
|
81
|
+
|
|
82
|
+
let config: Record<string, unknown> | string | null | undefined
|
|
83
|
+
if (options.config) {
|
|
84
|
+
try {
|
|
85
|
+
config = JSON.parse(options.config as string)
|
|
86
|
+
} catch {
|
|
87
|
+
config = options.config as string
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
73
91
|
const { data } = await withSpinner('Creating theme', () =>
|
|
74
92
|
client.themes.create({
|
|
75
93
|
slug: slug as string,
|
|
76
94
|
name: name as string,
|
|
77
95
|
description: (description as string) || null,
|
|
78
|
-
language: options.language || null,
|
|
96
|
+
language: (options.language as string) || null,
|
|
79
97
|
is_active: options.active !== undefined ? true : undefined,
|
|
80
98
|
is_default: options.default !== undefined ? true : undefined,
|
|
81
99
|
priority: options.priority ? Number(options.priority) : undefined,
|
|
100
|
+
scheduled_start: (options.scheduledStart as string) || null,
|
|
101
|
+
scheduled_end: (options.scheduledEnd as string) || null,
|
|
102
|
+
config,
|
|
103
|
+
translations,
|
|
82
104
|
}),
|
|
83
105
|
format,
|
|
84
106
|
)
|
|
@@ -94,7 +116,11 @@ export function registerThemesCommand(program: Command) {
|
|
|
94
116
|
.option('--description <text>', 'Description')
|
|
95
117
|
.option('--language <lang>', 'Language')
|
|
96
118
|
.option('--priority <n>', 'Priority')
|
|
97
|
-
.
|
|
119
|
+
.option('--scheduled-start <date>', 'Scheduled start date (ISO 8601)')
|
|
120
|
+
.option('--scheduled-end <date>', 'Scheduled end date (ISO 8601)')
|
|
121
|
+
.option('--config <json>', 'Theme configuration as JSON')
|
|
122
|
+
.option('--translation <lang:name:desc>', 'Add a translation (can be repeated)', (val: string, prev: string[]) => { prev.push(val); return prev }, [])
|
|
123
|
+
.action(async (id: string, options: Record<string, string | string[]>) => {
|
|
98
124
|
const client = await getClient()
|
|
99
125
|
const format = getFormat(program)
|
|
100
126
|
|
|
@@ -102,8 +128,23 @@ export function registerThemesCommand(program: Command) {
|
|
|
102
128
|
if (options.slug) data_.slug = options.slug
|
|
103
129
|
if (options.name) data_.name = options.name
|
|
104
130
|
if (options.description !== undefined) data_.description = options.description || null
|
|
105
|
-
if (options.language !== undefined) data_.language = options.language || null
|
|
131
|
+
if (options.language !== undefined) data_.language = (options.language as string) || null
|
|
106
132
|
if (options.priority !== undefined) data_.priority = Number(options.priority)
|
|
133
|
+
if (options.scheduledStart !== undefined) data_.scheduled_start = (options.scheduledStart as string) || null
|
|
134
|
+
if (options.scheduledEnd !== undefined) data_.scheduled_end = (options.scheduledEnd as string) || null
|
|
135
|
+
if (options.config !== undefined) {
|
|
136
|
+
try {
|
|
137
|
+
data_.config = JSON.parse(options.config as string)
|
|
138
|
+
} catch {
|
|
139
|
+
data_.config = options.config as string
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (Array.isArray(options.translation) && options.translation.length > 0) {
|
|
143
|
+
data_.translations = options.translation.map((t: string) => {
|
|
144
|
+
const [lang, tName, tDesc] = t.split(':')
|
|
145
|
+
return { language: lang!, name: tName!, description: tDesc || null }
|
|
146
|
+
})
|
|
147
|
+
}
|
|
107
148
|
|
|
108
149
|
const { data } = await withSpinner('Updating theme', () => client.themes.update(Number(id), data_ as any), format)
|
|
109
150
|
console.log(chalk.green(' Theme updated'))
|