wikibase-edit
Version:
Edit Wikibase from NodeJS
124 lines (108 loc) • 3.74 kB
JavaScript
import { isEntityId } from 'wikibase-sdk'
import error_ from '../error.js'
import { getEntityClaims } from '../get_entity.js'
import { forceArray } from '../utils.js'
import * as format from './format.js'
import { isIdAliasPattern, resolveIdAlias } from './id_alias.js'
export default async (data, properties, instance, config) => {
validateParameters(data)
let { id } = data
const { create, type, datatype, clear, rawMode, reconciliation } = data
const params = { data: {} }
let existingClaims
if (type && type !== 'property' && type !== 'item') {
throw error_.new('invalid entity type', { type })
}
const statements = data.claims || data.statements
if (create) {
if (type === 'property') {
if (!datatype) throw error_.new('missing property datatype', { datatype })
if (!datatypes.has(datatype)) {
throw error_.new('invalid property datatype', { datatype, knownDatatypes: datatypes })
}
params.new = 'property'
params.data.datatype = datatype
} else {
if (datatype) {
throw error_.new("an item can't have a datatype", { datatype })
}
params.new = 'item'
}
} else if (isEntityId(id) || isIdAliasPattern(id)) {
if (isIdAliasPattern(id)) {
id = await resolveIdAlias(id, instance)
}
params.id = id
if (hasReconciliationSettings(reconciliation, statements)) {
existingClaims = await getEntityClaims(id, config)
}
} else {
throw error_.new('invalid entity id', { id })
}
const { labels, aliases, descriptions, sitelinks } = data
if (rawMode) {
if (labels) params.data.labels = labels
if (aliases) params.data.aliases = aliases
if (descriptions) params.data.descriptions = descriptions
if (statements) params.data.claims = statements
if (sitelinks) params.data.sitelinks = sitelinks
} else {
if (labels) params.data.labels = format.values('label', labels)
if (aliases) params.data.aliases = format.values('alias', aliases)
if (descriptions) params.data.descriptions = format.values('description', descriptions)
if (statements) params.data.claims = format.claims(statements, properties, instance, reconciliation, existingClaims)
if (sitelinks) params.data.sitelinks = format.sitelinks(sitelinks)
}
if (clear === true) params.clear = true
if (!clear && Object.keys(params.data).length === 0) {
throw error_.new('no data was passed', { id })
}
// stringify as it will be passed as form data
params.data = JSON.stringify(params.data)
return {
action: 'wbeditentity',
data: params,
}
}
const datatypes = new Set([
'commonsMedia',
'edtf',
'external-id',
'geo-shape',
'globe-coordinate',
// datatype from https://github.com/ProfessionalWiki/WikibaseLocalMedia
'localMedia',
'math',
'monolingualtext',
'musical-notation',
'quantity',
'string',
'tabular-data',
'time',
'url',
'wikibase-form',
'wikibase-item',
'wikibase-property',
'wikibase-lexeme',
])
const allowedParameters = new Set([
'id', 'create', 'type', 'datatype', 'clear', 'rawMode', 'summary', 'baserevid',
'labels', 'aliases', 'descriptions', 'claims', 'statements', 'sitelinks', 'reconciliation',
'origin',
])
const validateParameters = data => {
for (const parameter in data) {
if (!allowedParameters.has(parameter)) {
throw error_.new(`invalid parameter: ${parameter}`, 400, { parameter, allowedParameters, data })
}
}
}
const hasReconciliationSettings = (reconciliation, claims) => {
if (reconciliation != null) return true
for (const property in claims) {
for (const claim of forceArray(claims[property])) {
if (claim.reconciliation != null) return true
}
}
return false
}