@verbatims/cli 0.1.8 → 0.1.10

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verbatims/cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "CLI for the Verbatims quotes API",
5
5
  "type": "module",
6
6
  "bin": {
@@ -195,4 +195,53 @@ export function registerQuotesCommand(program: Command) {
195
195
  format,
196
196
  )
197
197
  })
198
+
199
+ const tags = quotes.command('tags').description('Manage quote tags')
200
+
201
+ tags
202
+ .command('list <id>')
203
+ .description('List tags for a quote')
204
+ .action(async (id: string) => {
205
+ const client = await getClient()
206
+ const format = getFormat(program)
207
+ const { data } = await withSpinner('Fetching tags', () => client.quotes.listTags(Number(id)), format)
208
+ output(data, format)
209
+ })
210
+
211
+ tags
212
+ .command('add <id>')
213
+ .description('Add a tag to a quote (by tag ID or name)')
214
+ .option('--tag-id <n>', 'Existing tag ID')
215
+ .option('--name <name>', 'Tag name (creates new tag if admin)')
216
+ .action(async (id: string, options: Record<string, string>) => {
217
+ const client = await getClient()
218
+ const format = getFormat(program)
219
+
220
+ const tagId = options.tagId ? Number(options.tagId) : undefined
221
+ const name = options.name || undefined
222
+
223
+ if (!tagId && !name) {
224
+ console.log(chalk.red(' Provide --tag-id or --name'))
225
+ process.exit(1)
226
+ }
227
+
228
+ const { data } = await withSpinner('Adding tag', () =>
229
+ client.quotes.addTag(Number(id), { tagId, name }),
230
+ format,
231
+ )
232
+ console.log(chalk.green(' Tag added'))
233
+ output(data, format)
234
+ })
235
+
236
+ tags
237
+ .command('remove <id> <tagId>')
238
+ .description('Remove a tag from a quote')
239
+ .action(async (id: string, tagId: string) => {
240
+ const confirmed = await confirm({ message: `Remove tag #${tagId} from quote #${id}?` })
241
+ if (isCancel(confirmed) || !confirmed) cancel('Cancelled')
242
+
243
+ const client = await getClient()
244
+ await withSpinner('Removing tag', () => client.quotes.removeTag(Number(id), Number(tagId)))
245
+ console.log(chalk.green(` Tag #${tagId} removed`))
246
+ })
198
247
  }
@@ -213,14 +213,14 @@ export function registerThemesCommand(program: Command) {
213
213
  })
214
214
 
215
215
  themes
216
- .command('feed <slug>')
216
+ .command('feed <id>')
217
217
  .description('Get the curated feed for a theme')
218
218
  .option('--language <lang>', 'Language')
219
- .action(async (slug: string, options: Record<string, string>) => {
219
+ .action(async (id: string, options: Record<string, string>) => {
220
220
  const client = await getClient()
221
221
  const format = getFormat(program)
222
222
  const { data } = await withSpinner('Fetching theme feed', () =>
223
- client.themes.getFeed(slug, { language: options.language }),
223
+ client.themes.getFeed(Number(id), { language: options.language }),
224
224
  format,
225
225
  )
226
226
  if (!data) {
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  import { Command } from 'commander'
4
4
  import { registerCommands } from './commands/index.js'
5
5
  import { setSilent } from './utils/spinner.js'
6
+ import pkg from '../package.json' with { type: 'json' }
6
7
 
7
8
  process.on('unhandledRejection', (err) => {
8
9
  console.error(err instanceof Error ? err.message : String(err))
@@ -14,6 +15,7 @@ const program = new Command()
14
15
  program
15
16
  .name('verbatims')
16
17
  .description('CLI for the Verbatims quotes API')
18
+ .version(pkg.version)
17
19
  .option('--api-key <key>', 'API key (overrides config and env)')
18
20
  .option('--format <type>', 'Output format: table|json|plain', 'table')
19
21
  .showHelpAfterError()
@@ -3,6 +3,14 @@ import { loadConfig } from './config.js'
3
3
 
4
4
  const DEFAULT_BASE_URL = 'https://verbatims.cc/api/v1'
5
5
 
6
+ function withCliSource(fetchFn: typeof globalThis.fetch): typeof globalThis.fetch {
7
+ return (input, init) => {
8
+ const headers = new Headers(init?.headers)
9
+ headers.set('x-client-source', 'cli')
10
+ return fetchFn(input, { ...init, headers })
11
+ }
12
+ }
13
+
6
14
  export async function getClient(): Promise<VerbatimsClient> {
7
15
  const config = await loadConfig()
8
16
  const apiKey = process.env.VERBATIMS_API_KEY ?? config.apiKey
@@ -14,5 +22,6 @@ export async function getClient(): Promise<VerbatimsClient> {
14
22
 
15
23
  return new VerbatimsClient(apiKey, {
16
24
  baseUrl: process.env.VERBATIMS_BASE_URL ?? config.baseUrl ?? DEFAULT_BASE_URL,
25
+ fetch: withCliSource(globalThis.fetch),
17
26
  })
18
27
  }