wikibase-cli 18.1.0 → 18.2.0
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/bin/wb-badges.js +2 -0
- package/bin/wb-config.js +2 -0
- package/bin/wb-convert.js +2 -0
- package/bin/wb-data.js +2 -0
- package/bin/wb-generate-template.js +2 -0
- package/bin/wb-props.js +2 -0
- package/bin/wb-query.js +3 -0
- package/bin/wb-revisions.js +62 -38
- package/lib/edit/edit_command.js +3 -3
- package/lib/log_ndjson.js +1 -1
- package/lib/program.js +2 -19
- package/lib/read_ids_from_stdin.js +14 -6
- package/metadata/data.js +2 -2
- package/metadata/query.js +1 -1
- package/metadata/revisions.js +1 -0
- package/package.json +3 -3
package/bin/wb-badges.js
CHANGED
package/bin/wb-config.js
CHANGED
|
@@ -5,6 +5,8 @@ import { configurateCredentials } from '#lib/config/credentials_config'
|
|
|
5
5
|
import fileOps from '#lib/config/file_operations'
|
|
6
6
|
import program from '#lib/program'
|
|
7
7
|
|
|
8
|
+
program.canHaveZeroArguments = true
|
|
9
|
+
|
|
8
10
|
await program.process('config')
|
|
9
11
|
|
|
10
12
|
const { args, json } = program
|
package/bin/wb-convert.js
CHANGED
|
@@ -5,6 +5,8 @@ import errors_ from '#lib/errors'
|
|
|
5
5
|
import { getStdinInput } from '#lib/get_stdin_input'
|
|
6
6
|
import program from '#lib/program'
|
|
7
7
|
|
|
8
|
+
program.canHaveZeroArguments = true
|
|
9
|
+
|
|
8
10
|
await program
|
|
9
11
|
.option('-s, --subjects [subjects...]', 'set a subject')
|
|
10
12
|
.option('-p, --property <property>', 'set a property')
|
package/bin/wb-data.js
CHANGED
|
@@ -4,6 +4,8 @@ import { parseGuid } from '#lib/parse_command_utils'
|
|
|
4
4
|
import program from '#lib/program'
|
|
5
5
|
import { tolerantIdParserFactory } from '#lib/tolerant_id_parser'
|
|
6
6
|
|
|
7
|
+
program.acceptsArgsOnStdin = true
|
|
8
|
+
|
|
7
9
|
await program
|
|
8
10
|
.option('-s, --simplify', 'get simplified entities data')
|
|
9
11
|
.option('-k, --keep <props>', 'data to keep when simplifying claims (ids,richvalues,types,references,qualifiers,hashes,nontruthy,nondeprecated,ranks)')
|
|
@@ -9,6 +9,8 @@ import { readIdsFromStdin } from '#lib/read_ids_from_stdin'
|
|
|
9
9
|
import { tolerantIdParserFactory } from '#lib/tolerant_id_parser'
|
|
10
10
|
import { getWbk } from '#lib/wbk'
|
|
11
11
|
|
|
12
|
+
program.acceptsArgsOnStdin = true
|
|
13
|
+
|
|
12
14
|
await program
|
|
13
15
|
.option('-p, --props <props>', 'request only certain properties (info, sitelinks, aliases, labels, descriptions, claims, datatype)')
|
|
14
16
|
.option('-r, --revision <id>', 'request a specific revision')
|
package/bin/wb-props.js
CHANGED
|
@@ -7,6 +7,8 @@ import getPatternFilter from '#lib/get_pattern_filter'
|
|
|
7
7
|
import program from '#lib/program'
|
|
8
8
|
import resetProperties from '#lib/reset_properties'
|
|
9
9
|
|
|
10
|
+
program.canHaveZeroArguments = true
|
|
11
|
+
|
|
10
12
|
await program
|
|
11
13
|
.option('-d, --details', 'include properties labels, types, descriptions, and aliases')
|
|
12
14
|
.option('-t, --type [type]', 'include properties types, or if a type is specified, keep only properties with that type')
|
package/bin/wb-query.js
CHANGED
|
@@ -7,6 +7,9 @@ import { outputFactory } from '#lib/output'
|
|
|
7
7
|
import program from '#lib/program'
|
|
8
8
|
import { sparqlQueryCommand } from '#lib/sparql_query_command'
|
|
9
9
|
|
|
10
|
+
// All arguments are passed as options values making program.args.length === 0 likely
|
|
11
|
+
program.canHaveZeroArguments = true
|
|
12
|
+
|
|
10
13
|
await program
|
|
11
14
|
.option('-s, --subject <subject>', 'set a subject')
|
|
12
15
|
.option('-p, --property <property>', 'set a property')
|
package/bin/wb-revisions.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { values } from 'lodash-es'
|
|
2
|
+
import { chunk, values } from 'lodash-es'
|
|
3
3
|
import { isEntityId } from 'wikibase-sdk'
|
|
4
4
|
import errors_ from '#lib/errors'
|
|
5
5
|
import { exitOnMissingInstance } from '#lib/exit_on_missing'
|
|
@@ -9,58 +9,82 @@ import { get } from '#lib/request'
|
|
|
9
9
|
import { isPositiveIntegerString } from '#lib/types'
|
|
10
10
|
import { getWbk } from '#lib/wbk'
|
|
11
11
|
|
|
12
|
+
program.acceptsArgsOnStdin = true
|
|
13
|
+
|
|
12
14
|
await program
|
|
13
15
|
.option('-s, --start <date>', 'start date')
|
|
14
16
|
.option('-e, --end <date>', 'end date')
|
|
15
17
|
.option('-n, --limit <num>', 'maximum number of revisions')
|
|
18
|
+
.option('-p, --props <props>', 'requested props, separated by a comma. Available props: https://www.mediawiki.org/wiki/API:Revisions#query+revisions:rvprop')
|
|
16
19
|
.process('revisions')
|
|
17
20
|
|
|
18
21
|
exitOnMissingInstance(program.instance)
|
|
19
22
|
|
|
20
23
|
const { getRevisions } = getWbk(program)
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (prefix !== 'Property' && prefix !== 'Item') {
|
|
32
|
-
throw new Error(`invalid entity prefix: ${prefix}`)
|
|
25
|
+
async function fetchAndLogRevisions (ids) {
|
|
26
|
+
ids.forEach(id => {
|
|
27
|
+
let [ prefix, entityId ] = id.split(':')
|
|
28
|
+
if (entityId) {
|
|
29
|
+
if (prefix !== 'Property' && prefix !== 'Item') {
|
|
30
|
+
throw new Error(`invalid entity prefix: ${prefix}`)
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
entityId = prefix
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
35
|
+
if (!isEntityId(entityId)) throw new Error(`invalid entity id: ${id}`)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const query = {}
|
|
39
|
+
let { start, end, limit, props, verbose } = program
|
|
40
|
+
if (isPositiveIntegerString(start)) start = parseInt(start)
|
|
41
|
+
if (isPositiveIntegerString(end)) end = parseInt(end)
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
if (
|
|
43
|
+
if (start != null) query.start = start
|
|
44
|
+
if (end != null) query.end = end
|
|
45
|
+
if (limit != null) query.limit = limit
|
|
46
|
+
if (props != null) query.prop = props?.split(/[,|]/)
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
query.limit = limit
|
|
48
|
+
// Prevent error "titles, pageids or a generator was used to supply multiple pages, but the rvlimit, rvstartid, rvendid, rvdir=newer, rvuser, rvexcludeuser, rvstart, and rvend parameters may only be used on a single page. "
|
|
49
|
+
const usesSinglePageParam = limit != null || start != null || end != null
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
async function getAndLogRevisions (ids) {
|
|
52
|
+
const url = getRevisions({ ids, ...query })
|
|
53
|
+
if (verbose) console.log(`revision query: ${ids}`, url)
|
|
54
|
+
const body = await get(url)
|
|
55
|
+
return values(body.query.pages)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (usesSinglePageParam) {
|
|
59
|
+
const idsBatches = chunk(ids, 10)
|
|
60
|
+
for (const batch of idsBatches) {
|
|
61
|
+
// Getting revisisions data individually to be able to pass parameters
|
|
62
|
+
// cf https://github.com/maxlath/wikibase-sdk/blob/master/docs/get_revisions.md
|
|
63
|
+
await Promise.all(batch.map(getAndLogRevisions))
|
|
64
|
+
.then(logNdjson)
|
|
65
|
+
.catch(errors_.exit)
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
const idsBatches = chunk(ids, 50)
|
|
69
|
+
for (const batch of idsBatches) {
|
|
70
|
+
await getAndLogRevisions(batch)
|
|
71
|
+
.then(logNdjson)
|
|
72
|
+
.catch(errors_.exit)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
54
75
|
}
|
|
55
76
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
.
|
|
77
|
+
// process.stdin.isTTY will be undefined if the process is receiving
|
|
78
|
+
// its stdin from another process
|
|
79
|
+
if (program.args.length === 0 && process.stdin.isTTY) {
|
|
80
|
+
program.helpAndExit(0)
|
|
81
|
+
} else if (program.args.length > 0) {
|
|
82
|
+
// Not parsing the ids with ../lib/tolerant_id_parser as that would
|
|
83
|
+
// remove prefixes which are required for entities out of the main namespace
|
|
84
|
+
// Ex: Property:P570
|
|
85
|
+
const ids = program.args
|
|
86
|
+
fetchAndLogRevisions(ids)
|
|
60
87
|
} else {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
Promise.all(ids.map(getAndLogRevisions))
|
|
64
|
-
.then(logNdjson)
|
|
65
|
-
.catch(errors_.exit)
|
|
88
|
+
const { readIdsFromStdin } = await import('#lib/read_ids_from_stdin')
|
|
89
|
+
readIdsFromStdin(fetchAndLogRevisions)
|
|
66
90
|
}
|
package/lib/edit/edit_command.js
CHANGED
|
@@ -106,11 +106,10 @@ function getWbEditConfig () {
|
|
|
106
106
|
const { editGroup } = program
|
|
107
107
|
let { summary, baserevid, maxlag } = program
|
|
108
108
|
|
|
109
|
+
let summarySuffix
|
|
109
110
|
if (editGroup) {
|
|
110
111
|
const compactEditGroupUrl = getEditGroupUrl(':toollabs:', editGroup)
|
|
111
|
-
|
|
112
|
-
summary += ` ([[${compactEditGroupUrl}|details]])`
|
|
113
|
-
summary = summary.trim()
|
|
112
|
+
summarySuffix = `([[${compactEditGroupUrl}|details]])`
|
|
114
113
|
}
|
|
115
114
|
|
|
116
115
|
const { instance, credentials } = config
|
|
@@ -132,6 +131,7 @@ function getWbEditConfig () {
|
|
|
132
131
|
instance,
|
|
133
132
|
credentials: { oauth, username, password },
|
|
134
133
|
summary,
|
|
134
|
+
summarySuffix,
|
|
135
135
|
baserevid,
|
|
136
136
|
tags,
|
|
137
137
|
bot: config.bot,
|
package/lib/log_ndjson.js
CHANGED
package/lib/program.js
CHANGED
|
@@ -27,9 +27,9 @@ program.process = async command => {
|
|
|
27
27
|
} else if (showHelp) {
|
|
28
28
|
program.helpAndExit(0)
|
|
29
29
|
} else if (program.args.length === 0 && !program.batch) {
|
|
30
|
-
if (
|
|
30
|
+
if (program.acceptsArgsOnStdin) {
|
|
31
31
|
if (process.stdin.isTTY) program.helpAndExit(0)
|
|
32
|
-
} else if (!
|
|
32
|
+
} else if (!program.canHaveZeroArguments) {
|
|
33
33
|
program.helpAndExit(0)
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -48,23 +48,6 @@ function getOptionsKeyValues (options) {
|
|
|
48
48
|
return Object.fromEntries(optionsEntries)
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
const commandsAcceptingZeroArguments = [
|
|
52
|
-
// Can be called without argument
|
|
53
|
-
'props',
|
|
54
|
-
'badges',
|
|
55
|
-
// All arguments are passed as options values
|
|
56
|
-
// making program.args.length === 0 likely
|
|
57
|
-
'query',
|
|
58
|
-
'convert',
|
|
59
|
-
// Needs to also log the current config
|
|
60
|
-
'config',
|
|
61
|
-
]
|
|
62
|
-
|
|
63
|
-
const commandsTakingArgsOnStdin = [
|
|
64
|
-
'data',
|
|
65
|
-
'generate-template',
|
|
66
|
-
]
|
|
67
|
-
|
|
68
51
|
const parseArgv = (argv, isCommandsWithCustomHelpMenu) => {
|
|
69
52
|
// Make a copy to be able to mutate the array without affecting other operations
|
|
70
53
|
// that might rely on that array being intact
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import split from 'split'
|
|
2
2
|
import through from 'through'
|
|
3
|
+
import program from '#lib/program'
|
|
3
4
|
|
|
4
5
|
let ids = []
|
|
5
6
|
|
|
6
7
|
export function readIdsFromStdin (handleIdsBatch) {
|
|
7
|
-
|
|
8
|
+
let count = 0
|
|
9
|
+
async function write (id) {
|
|
8
10
|
id = id.trim()
|
|
9
11
|
if (id === '') return
|
|
12
|
+
count++
|
|
10
13
|
ids.push(id)
|
|
11
14
|
if (ids.length < 50) return
|
|
12
15
|
|
|
@@ -15,18 +18,23 @@ export function readIdsFromStdin (handleIdsBatch) {
|
|
|
15
18
|
const batch = ids
|
|
16
19
|
ids = []
|
|
17
20
|
|
|
18
|
-
handleIdsBatch(batch)
|
|
19
|
-
|
|
21
|
+
await handleIdsBatch(batch)
|
|
22
|
+
this.resume()
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
async function end () {
|
|
26
|
+
if (count === 0) program.helpAndExit(0)
|
|
23
27
|
if (ids.length === 0) return this.emit('end')
|
|
24
|
-
handleIdsBatch(ids)
|
|
25
|
-
|
|
28
|
+
await handleIdsBatch(ids)
|
|
29
|
+
this.emit('end')
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
process.stdin
|
|
29
33
|
.pipe(split(/\s/))
|
|
30
34
|
.pipe(through(write, end))
|
|
31
35
|
.on('error', console.error)
|
|
36
|
+
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
if (count === 0) program.helpAndExit(0)
|
|
39
|
+
}, 500)
|
|
32
40
|
}
|
package/metadata/data.js
CHANGED
|
@@ -16,7 +16,7 @@ export default {
|
|
|
16
16
|
{ args: '--simplify Q123', comment: 'fetch Q123 simplified data' },
|
|
17
17
|
{ args: '--simplify --keep ids,references,qualifiers,hashes,nontruthy Q123', comment: 'simplified Q123 data, but keep some attributes' },
|
|
18
18
|
{ args: '--simplify --keep all Q123', comment: 'same as above' },
|
|
19
|
-
{ args: 'Q1496 |
|
|
20
|
-
{ args: '--simplify --keep ids Q123 |
|
|
19
|
+
{ args: 'Q1496 | jq .labels.pt', comment: "take advantage of the raw data being output as JSON\n # to pass it to jq (a JSON parsers https://jqlang.github.io/jq/)\n # and get only the piece of data you're looking for" },
|
|
20
|
+
{ args: '--simplify --keep ids Q123 | jq .claims.P138 -j', comment: 'get Q123 P138 claims ids' },
|
|
21
21
|
],
|
|
22
22
|
}
|
package/metadata/query.js
CHANGED
|
@@ -15,7 +15,7 @@ export default {
|
|
|
15
15
|
{ args: '--property P921 --object Q44559 --labels', comment: 'find out which works have exoplanets (Q44559) for main subject (P921)\n # and include labels' },
|
|
16
16
|
{ args: '--property P7476 --count', comment: 'get a list of all the claims using the property (P7476)' },
|
|
17
17
|
{ args: '-p P921 -o Q44559 -a', comment: 'as always, you can also use the short options syntax' },
|
|
18
|
-
{ args:
|
|
18
|
+
{ args: "-p P921 -o Q44559 -a | jq '.[]' -cr", comment: 'the output is valid JSON, so you can pipe it to any JSON parser you like\n # (here jq https://jqlang.github.io/jq/)' },
|
|
19
19
|
{ args: '-s Q15228 -p P674 -a', comment: 'find out which are the characters (P674) in The Lord of The Ring (Q15228)' },
|
|
20
20
|
{ args: '-s Q15228 -o Q177499 -a', comment: 'find out which property link The Lord of The Ring (Q15228) and Gandalf (Q177499)' },
|
|
21
21
|
{ args: '-s Q177499 -a', comment: 'get the properties and objects for all the triples (subject, property, object) having Gandalf (Q177499) as subject' },
|
package/metadata/revisions.js
CHANGED
|
@@ -12,6 +12,7 @@ export default {
|
|
|
12
12
|
},
|
|
13
13
|
examples: [
|
|
14
14
|
{ args: 'Q3548931', comment: "fetch Q3548931's revisions data" },
|
|
15
|
+
{ args: 'Q3548931 -p content,user,ids', comment: "fetch only certain attributes from Q3548931's revisions data" },
|
|
15
16
|
{ args: 'Property:P31', comment: "fetch P31's revisions data" },
|
|
16
17
|
],
|
|
17
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikibase-cli",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.2.0",
|
|
4
4
|
"description": "A command-line interface to Wikibase",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"lint-staged": "./scripts/lint_staged",
|
|
17
17
|
"prepublishOnly": "export MOCHA_OPTIONS='--bail'; npm run lint && npm test",
|
|
18
18
|
"postpublish": "npm run docker:publish && git push --tags",
|
|
19
|
-
"test": "mocha --exit --timeout 20000 $MOCHA_OPTIONS",
|
|
19
|
+
"test": "export FORCE_COLOR=false; mocha --exit --timeout 20000 $MOCHA_OPTIONS",
|
|
20
20
|
"update-toc": "./scripts/update_toc"
|
|
21
21
|
},
|
|
22
22
|
"repository": {
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"shell-quote": "^1.8.1",
|
|
58
58
|
"split": "^1.0.1",
|
|
59
59
|
"through": "^2.3.8",
|
|
60
|
-
"wikibase-edit": "^7.1.
|
|
60
|
+
"wikibase-edit": "^7.1.2",
|
|
61
61
|
"wikibase-sdk": "^10.1.0",
|
|
62
62
|
"wikidata-lang": "^2.0.11"
|
|
63
63
|
},
|