wikibase-cli 20.0.0 → 20.1.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/README.md +1 -1
- package/bin/wb-graph-path.js +40 -30
- package/metadata/graph-path.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ See [CHANGELOG.md](CHANGELOG.md) for version info
|
|
|
55
55
|
## Dependencies
|
|
56
56
|
|
|
57
57
|
### General
|
|
58
|
-
* [
|
|
58
|
+
* [NodeJS](https://nodejs.org) **>= v20.12.0** (Older NodeJS versions can be used for older wikibase-cli version, see [changelogs](./CHANGELOG.md). Recommendable way to install NodeJS: you may use [NVM](https://github.com/creationix/nvm) to install the latest LTS version `nvm install --lts`)
|
|
59
59
|
* [Git](https://git-scm.com/)
|
|
60
60
|
|
|
61
61
|
### Per feature
|
package/bin/wb-graph-path.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { map, partition, uniq, without } from 'lodash-es'
|
|
2
|
+
import { map, partition, uniq, values, without } from 'lodash-es'
|
|
3
3
|
import { grey } from 'tiny-chalk'
|
|
4
4
|
import { isEntityId, isPropertyId } from 'wikibase-sdk'
|
|
5
5
|
import errors_ from '#lib/errors'
|
|
@@ -8,9 +8,10 @@ import { makeSparqlQuery } from '#lib/make_sparql_query'
|
|
|
8
8
|
import program from '#lib/program'
|
|
9
9
|
|
|
10
10
|
await program
|
|
11
|
+
.option('-f, --format <format>', 'Available alternative formats: mermaid')
|
|
11
12
|
.process('graph-path')
|
|
12
13
|
|
|
13
|
-
const { args } = program
|
|
14
|
+
const { args, format } = program
|
|
14
15
|
const [ subject, property, joinedObjects ] = args
|
|
15
16
|
|
|
16
17
|
if (!(subject && property && joinedObjects)) {
|
|
@@ -41,35 +42,44 @@ if (rows.length === 0) {
|
|
|
41
42
|
const intermediaries = uniq(map(rows, 'intermediary'))
|
|
42
43
|
const relevantRows = rows.filter(row => intermediaries.includes(row.next))
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
let paths = [ subject ]
|
|
47
|
-
const replacedPaths = []
|
|
45
|
+
const allEntityIds = uniq(relevantRows.flatMap(row => values(row)))
|
|
46
|
+
const labels = await getEntitiesLabels(allEntityIds, program.lang)
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const updatedPaths = relevantPaths.map(path => `${path}.${next}`)
|
|
62
|
-
// Leave the relevantPaths in paths, to let other rows fork them if needed
|
|
63
|
-
replacedPaths.push(...relevantPaths)
|
|
64
|
-
newPaths.push(...updatedPaths)
|
|
65
|
-
})
|
|
66
|
-
nextSubjects = uniq(map(nextRows, 'next'))
|
|
67
|
-
paths = [ ...without(paths, ...replacedPaths), ...newPaths ]
|
|
68
|
-
}
|
|
48
|
+
if (format === 'mermaid') {
|
|
49
|
+
let output = 'graph LR\n'
|
|
50
|
+
const getNodeLabel = id => `${labels[id]} (${id})`
|
|
51
|
+
for (const { intermediary, next } of relevantRows) {
|
|
52
|
+
output += `${getNodeLabel(intermediary)} --> ${getNodeLabel(next)}\n`
|
|
53
|
+
}
|
|
54
|
+
console.log(output.trim())
|
|
55
|
+
} else {
|
|
56
|
+
let remainingRows = relevantRows
|
|
57
|
+
let nextSubjects = [ subject ]
|
|
58
|
+
let paths = [ subject ]
|
|
59
|
+
const replacedPaths = []
|
|
69
60
|
|
|
70
|
-
|
|
71
|
-
const
|
|
61
|
+
while (remainingRows.length > 0) {
|
|
62
|
+
const newPaths = []
|
|
63
|
+
const [ nextRows, rest ] = partition(remainingRows, ({ intermediary }) => {
|
|
64
|
+
return nextSubjects.includes(intermediary)
|
|
65
|
+
})
|
|
66
|
+
if (rest.length === remainingRows.length) throw new Error('stuck')
|
|
67
|
+
remainingRows = rest
|
|
68
|
+
nextRows.forEach(({ intermediary, next }) => {
|
|
69
|
+
const relevantPaths = paths.filter(path => {
|
|
70
|
+
const pathParts = path.split('.')
|
|
71
|
+
return pathParts.at(-1) === intermediary
|
|
72
|
+
})
|
|
73
|
+
const updatedPaths = relevantPaths.map(path => `${path}.${next}`)
|
|
74
|
+
// Leave the relevantPaths in paths, to let other rows fork them if needed
|
|
75
|
+
replacedPaths.push(...relevantPaths)
|
|
76
|
+
newPaths.push(...updatedPaths)
|
|
77
|
+
})
|
|
78
|
+
nextSubjects = uniq(map(nextRows, 'next'))
|
|
79
|
+
paths = [ ...without(paths, ...replacedPaths), ...newPaths ]
|
|
80
|
+
}
|
|
72
81
|
|
|
73
|
-
for (const path of paths) {
|
|
74
|
-
|
|
82
|
+
for (const path of paths) {
|
|
83
|
+
console.log(path.split('.').map(part => `${labels[part]} ${grey(`(${part})`)}`).join(' → '))
|
|
84
|
+
}
|
|
75
85
|
}
|
package/metadata/graph-path.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
alias: 'gp',
|
|
3
3
|
args: '<subject> <property> <object>',
|
|
4
|
-
description: 'Find the path between a subject and an object on the
|
|
4
|
+
description: 'Find the path between a subject and an object via a given property, on the entities relations graph',
|
|
5
5
|
options: {
|
|
6
6
|
lang: true,
|
|
7
7
|
verbose: true,
|
|
@@ -13,5 +13,6 @@ export default {
|
|
|
13
13
|
examples: [
|
|
14
14
|
{ args: 'Q336 P279 Q5891', comment: 'Find by which path science (Q336) is a subclass of (P279) philosophy (Q5891)' },
|
|
15
15
|
{ args: 'Q336 P279 Q5891,Q2198855,Q3326717,Q968159', comment: 'Find by which path science (Q336) is a subclass of (P279) either philosophy (Q5891), literary movement (Q3326717), or art movement (Q968159)' },
|
|
16
|
+
{ args: 'wd gp Q506259 P279 Q2509280 --format mermaid | mermaid-ascii -f -', comment: 'Output graph in the [mermaid format](https://mermaid.js.org/) and pipe it to [mermaid-ascii](https://github.com/AlexanderGrooff/mermaid-ascii) to visualize the graph in the terminal' },
|
|
16
17
|
],
|
|
17
18
|
}
|