@verbatims/cli 0.1.18 → 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.
- package/README.md +5 -3
- package/package.json +2 -2
- package/src/commands/quotes.ts +33 -31
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
CLI for the [Verbatims](https://verbatims.cc) quotes API.
|
|
4
4
|
|
|
5
|
+
Version 1 uses normalized provenance options for quote creation and updates.
|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -27,12 +29,12 @@ verbatims quotes get 123 --format json
|
|
|
27
29
|
verbatims quotes attributions list 123
|
|
28
30
|
verbatims quotes attributions create 123 --author-id 1 --reference-id 2 --status manually_verified --primary
|
|
29
31
|
verbatims quotes sources list 123
|
|
30
|
-
verbatims quotes sources create 123 --source-type book --source-url https://example.com/edition --status externally_verified
|
|
32
|
+
verbatims quotes sources create 123 --attribution-id 7 --source-type book --source-url https://example.com/edition --status externally_verified
|
|
31
33
|
|
|
32
34
|
# Create a quote with a source
|
|
33
|
-
verbatims quotes create --source-type book --source-url https://example.com/edition
|
|
35
|
+
verbatims quotes create --name "Alea jacta est" --author-id 1 --source-type book --source-url https://example.com/edition
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
Use `--author-id` or `--reference-id` to create the required primary attribution. Sources always require `--attribution-id`; use the dedicated `quotes attributions` and `quotes sources` commands for additional or edited provenance.
|
|
36
38
|
|
|
37
39
|
# Browse interactively
|
|
38
40
|
verbatims quotes browse
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verbatims/cli",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "CLI for the Verbatims quotes API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"typecheck": "tsc --noEmit"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@verbatims/sdk": "^
|
|
19
|
+
"@verbatims/sdk": "^2.0.1",
|
|
20
20
|
"@clack/prompts": "^0.10.1",
|
|
21
21
|
"chalk": "^5.4.1",
|
|
22
22
|
"commander": "^13.1.0",
|
package/src/commands/quotes.ts
CHANGED
|
@@ -10,13 +10,6 @@ function getFormat(program: Command): Format {
|
|
|
10
10
|
return (program.opts().format ?? 'table') as Format
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function warnLegacyQuoteOptions(options: Record<string, unknown>): void {
|
|
14
|
-
const fields = ['authorId', 'referenceId', 'sourceType', 'sourceUrl']
|
|
15
|
-
if (fields.some(field => options[field] !== undefined)) {
|
|
16
|
-
console.error(chalk.yellow('Warning: quote provenance options are deprecated; use the provenance API fields instead.'))
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
13
|
export function registerQuotesCommand(program: Command) {
|
|
21
14
|
const quotes = program.command('quotes').description('Manage quotes')
|
|
22
15
|
|
|
@@ -73,14 +66,13 @@ export function registerQuotesCommand(program: Command) {
|
|
|
73
66
|
.description('Create a quote')
|
|
74
67
|
.option('--name <text>', 'Quote text')
|
|
75
68
|
.option('--language <lang>', 'Language')
|
|
76
|
-
.option('--author-id <id>', '
|
|
77
|
-
.option('--reference-id <id>', '
|
|
78
|
-
.option('--source-type <type>', 'Source type
|
|
79
|
-
.option('--source-url <url>', 'Source URL
|
|
69
|
+
.option('--author-id <id>', 'Primary attribution author ID')
|
|
70
|
+
.option('--reference-id <id>', 'Primary attribution reference ID')
|
|
71
|
+
.option('--source-type <type>', 'Source type for the primary attribution')
|
|
72
|
+
.option('--source-url <url>', 'Source URL for the primary attribution')
|
|
80
73
|
.action(async (options: Record<string, string>) => {
|
|
81
74
|
const client = await getClient()
|
|
82
75
|
const format = getFormat(program)
|
|
83
|
-
warnLegacyQuoteOptions(options)
|
|
84
76
|
|
|
85
77
|
const name = options.name ?? await text({ message: 'Quote text', validate: (v) => !v ? 'Required' : undefined })
|
|
86
78
|
if (isCancel(name)) cancel('Cancelled')
|
|
@@ -90,20 +82,29 @@ export function registerQuotesCommand(program: Command) {
|
|
|
90
82
|
|
|
91
83
|
const authorId = options.authorId ? Number(options.authorId) : undefined
|
|
92
84
|
const referenceId = options.referenceId ? Number(options.referenceId) : undefined
|
|
85
|
+
if (authorId === undefined && referenceId === undefined) {
|
|
86
|
+
throw new Error('A quote requires --author-id or --reference-id')
|
|
87
|
+
}
|
|
93
88
|
|
|
94
89
|
const { data } = await withSpinner('Creating quote', () =>
|
|
95
90
|
client.quotes.create({
|
|
96
91
|
content: name as string,
|
|
97
92
|
name: name as string,
|
|
98
93
|
language: language as string,
|
|
99
|
-
|
|
100
|
-
author_id: authorId,
|
|
101
|
-
reference_id: referenceId,
|
|
102
|
-
source: options.sourceType ? { source_type: options.sourceType, source_url: options.sourceUrl } : undefined,
|
|
103
|
-
},
|
|
94
|
+
attributions: [{ author_id: authorId, reference_id: referenceId, is_primary: true }],
|
|
104
95
|
}),
|
|
105
96
|
format,
|
|
106
97
|
)
|
|
98
|
+
if (options.sourceType && data) {
|
|
99
|
+
const primary = data.attributions?.find(attribution => attribution.is_primary)
|
|
100
|
+
if (!primary) throw new Error('The created quote has no primary attribution')
|
|
101
|
+
await withSpinner('Creating source', () => client.quotes.createSource(data.id, {
|
|
102
|
+
attribution_id: primary.id,
|
|
103
|
+
source_type: options.sourceType,
|
|
104
|
+
source_url: options.sourceUrl,
|
|
105
|
+
is_primary: true,
|
|
106
|
+
}), format)
|
|
107
|
+
}
|
|
107
108
|
console.log(chalk.green(' Quote created'))
|
|
108
109
|
output(data, format)
|
|
109
110
|
})
|
|
@@ -113,28 +114,28 @@ export function registerQuotesCommand(program: Command) {
|
|
|
113
114
|
.description('Update a quote')
|
|
114
115
|
.option('--name <text>', 'Quote text')
|
|
115
116
|
.option('--language <lang>', 'Language')
|
|
116
|
-
.option('--author-id <id>', '
|
|
117
|
-
.option('--reference-id <id>', '
|
|
118
|
-
.option('--source-type <type>', 'Source type (deprecated)')
|
|
119
|
-
.option('--source-url <url>', 'Source URL (deprecated)')
|
|
117
|
+
.option('--author-id <id>', 'Primary attribution author ID')
|
|
118
|
+
.option('--reference-id <id>', 'Primary attribution reference ID')
|
|
120
119
|
.action(async (id: string, options: Record<string, string>) => {
|
|
121
120
|
const client = await getClient()
|
|
122
121
|
const format = getFormat(program)
|
|
123
|
-
warnLegacyQuoteOptions(options)
|
|
124
122
|
|
|
125
123
|
const data_: Record<string, unknown> = {}
|
|
126
124
|
if (options.name) { data_.name = options.name; data_.content = options.name }
|
|
127
125
|
if (options.language) data_.language = options.language
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (options.sourceType !== undefined || options.sourceUrl !== undefined) {
|
|
131
|
-
data_.provenance = {
|
|
132
|
-
...(data_.provenance as object),
|
|
133
|
-
source: { source_type: options.sourceType ?? 'manual', source_url: options.sourceUrl },
|
|
134
|
-
}
|
|
135
|
-
}
|
|
126
|
+
const authorId = options.authorId === undefined ? undefined : options.authorId === 'null' ? null : Number(options.authorId)
|
|
127
|
+
const referenceId = options.referenceId === undefined ? undefined : options.referenceId === 'null' ? null : Number(options.referenceId)
|
|
136
128
|
|
|
137
129
|
const { data } = await withSpinner('Updating quote', () => client.quotes.update(Number(id), data_ as any), format)
|
|
130
|
+
if (authorId !== undefined || referenceId !== undefined) {
|
|
131
|
+
const attributions = await client.quotes.listAttributions(Number(id))
|
|
132
|
+
const primary = attributions.data?.find(attribution => attribution.is_primary)
|
|
133
|
+
if (!primary) throw new Error('The quote has no primary attribution')
|
|
134
|
+
await withSpinner('Updating primary attribution', () => client.quotes.updateAttribution(Number(id), primary.id, {
|
|
135
|
+
author_id: authorId === undefined ? primary.author_id : authorId,
|
|
136
|
+
reference_id: referenceId === undefined ? primary.reference_id : referenceId,
|
|
137
|
+
}), format)
|
|
138
|
+
}
|
|
138
139
|
console.log(chalk.green(' Quote updated'))
|
|
139
140
|
output(data, format)
|
|
140
141
|
})
|
|
@@ -306,8 +307,9 @@ export function registerQuotesCommand(program: Command) {
|
|
|
306
307
|
}
|
|
307
308
|
if (action === 'create') {
|
|
308
309
|
if (!options.sourceType) throw new Error('--source-type is required')
|
|
310
|
+
if (!options.attributionId) throw new Error('--attribution-id is required')
|
|
309
311
|
const { data } = await withSpinner('Creating source', () => client.quotes.createSource(id, {
|
|
310
|
-
attribution_id:
|
|
312
|
+
attribution_id: Number(options.attributionId),
|
|
311
313
|
source_type: options.sourceType,
|
|
312
314
|
source_url: options.sourceUrl,
|
|
313
315
|
label: options.label,
|