wikibase-edit
Version:
Edit Wikibase from NodeJS
121 lines (103 loc) • 3.63 kB
text/typescript
import { entityEditBuilders as builders } from '../claim/builders.js'
import { buildReferenceFactory, buildPropSnaksFactory } from '../claim/snak.js'
import { hasSpecialSnaktype } from '../claim/special_snaktype.js'
import { newError } from '../error.js'
import { normalizeDatatype } from '../properties/datatypes_to_builder_datatypes.js'
import { isString, isNumber, isPlainObject, mapValues, forceArray } from '../utils.js'
import { validateGuid, validateRank, validateSnakValue } from '../validate.js'
import type { PropertiesDatatypes } from '../properties/fetch_properties_datatypes.js'
import type { AbsoluteUrl } from '../types/common.js'
import type { PropertyId, SimplifiedClaim } from 'wikibase-sdk'
export function buildClaim (property: PropertyId, properties: PropertiesDatatypes, claimData: SimplifiedClaim, instance: AbsoluteUrl) {
const datatype = properties[property]
const builderDatatype = normalizeDatatype(datatype)
const builder = builders[builderDatatype]
const params = { properties, datatype, property, claimData, builder, instance }
if (isString(claimData) || isNumber(claimData)) {
return simpleClaimBuilder(params)
} else {
if (!isPlainObject(claimData)) throw newError('invalid claim data', { property, claimData })
return fullClaimBuilder(params)
}
}
function simpleClaimBuilder (params) {
const { property, datatype, claimData: value, builder, instance } = params
validateSnakValue(property, datatype, value)
return builder(property, value, instance)
}
function fullClaimBuilder (params) {
const { properties, datatype, property, claimData, builder, instance } = params
validateClaimParameters(claimData)
let { id, value, snaktype, rank, qualifiers, references, remove, reconciliation } = claimData
if (remove === true) {
if (!(id || reconciliation)) throw newError("can't remove a claim without an id or reconciliation settings", claimData)
if (id) return { id, remove: true }
}
let claim
if (value?.snaktype) {
claimData.snaktype = snaktype = value.snaktype
}
if (hasSpecialSnaktype(claimData)) {
claim = builders.specialSnaktype(property, snaktype)
} else {
// In case of a rich value (monolingual text, quantity, globe coordinate, or time)
if (value == null && (claimData.text || claimData.amount || claimData.latitude || claimData.time)) {
value = claimData
}
validateSnakValue(property, datatype, value)
claim = builder(property, value, instance)
}
if (id) {
validateGuid(id)
claim.id = id
}
if (rank) {
validateRank(rank)
claim.rank = rank
}
if (qualifiers) {
claim.qualifiers = mapValues(qualifiers, buildPropSnaksFactory(properties, instance))
}
if (references) {
claim.references = forceArray(references).map(buildReferenceFactory(properties, instance))
}
if (reconciliation) claim.reconciliation = reconciliation
if (remove) claim.remove = remove
return claim
}
const validClaimParameters = [
'id',
'type',
'value',
'snaktype',
'rank',
'qualifiers',
'references',
'remove',
'reconciliation',
'text',
'language',
'amount',
'lowerBound',
'upperBound',
'unit',
'latitude',
'longitude',
'precision',
'globe',
'altitude',
'time',
'timezone',
'before',
'after',
'precision',
'calendarmodel',
]
const validClaimParametersSet = new Set(validClaimParameters)
function validateClaimParameters (claimData) {
for (const key in claimData) {
if (!validClaimParametersSet.has(key)) {
throw newError(`invalid claim parameter: ${key}`, { claimData, validClaimParameters })
}
}
}