wikibase-edit
Version:
Edit Wikibase from NodeJS
140 lines • 5.24 kB
JavaScript
import { omit } from 'lodash-es';
import { isEntityId, datatypes } from 'wikibase-sdk';
import { newError } from '../error.js';
import { getEntityClaims } from '../get_entity.js';
import { arrayIncludes, forceArray, objectEntries } from '../utils.js';
import { formatClaims, formatSitelinks, formatTermsObject } from './format.js';
import { isIdAliasPattern, resolveIdAlias } from './id_alias.js';
const editableTypes = [
// 'form',
'item',
'lexeme',
'mediainfo',
'property',
// 'sense',
];
export async function editEntity(inputParams, properties, instance, config) {
return _editEntity(inputParams, properties, instance, config);
}
export async function _rawEditEntity(inputParams, properties, instance, config) {
return _editEntity(inputParams, properties, instance, config);
}
async function _editEntity(inputParams, properties, instance, config) {
validateParameters(inputParams);
let { id } = inputParams;
const { create, type = 'item', clear, reconciliation } = inputParams;
const datatype = 'datatype' in inputParams ? inputParams.datatype : undefined;
const rawMode = 'rawMode' in inputParams ? inputParams.rawMode : false;
if (!arrayIncludes(editableTypes, type)) {
throw newError('invalid entity type', { type });
}
let params = { type, data: {} };
let existingClaims;
if (create) {
if (type === 'property') {
if (!datatype)
throw newError('missing property datatype', { datatype });
if (!datatypesSet.has(datatype)) {
throw newError('invalid property datatype', { datatype, knownDatatypes: datatypes });
}
params = {
...params,
new: 'property',
data: {
datatype,
},
};
}
else {
if (datatype) {
throw newError("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;
// @ts-expect-error
if (hasReconciliationSettings(reconciliation, inputParams.claims || inputParams.statements)) {
existingClaims = await getEntityClaims(id, config);
}
}
else {
throw newError('invalid entity id', { id });
}
for (const [attribute, types] of objectEntries(attributesPerEntityType)) {
if (arrayIncludes(types, params.type)) {
if (attribute in inputParams && inputParams[attribute] != null) {
const inputParam = inputParams[attribute];
if (rawMode) {
params.data[attribute] = inputParam;
}
else {
if (attribute === 'claims' || attribute === 'statements') {
params.data[attribute] = formatClaims(inputParam, properties, instance, reconciliation, existingClaims);
}
else {
params.data[attribute] = simplifiedInputFormatters[attribute](inputParam);
}
}
}
}
}
if (clear === true)
params.clear = true;
if (!clear && Object.keys(params.data).length === 0) {
throw newError('no data was passed', { id });
}
return {
action: 'wbeditentity',
data: {
...omit(params, 'type', 'data'),
// Stringify as it will be passed as form data
data: JSON.stringify(params.data),
},
};
}
// TODO: add support for lemmas, forms and senses
const attributesPerEntityType = {
aliases: ['item', 'property'],
claims: ['item', 'property', 'lexeme'],
descriptions: ['item', 'property', 'mediainfo'],
labels: ['item', 'property', 'mediainfo'],
statements: ['mediainfo'],
sitelinks: ['item'],
};
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
const simplifiedInputFormatters = {
aliases: formatTermsObject.bind(null, 'alias'),
descriptions: formatTermsObject.bind(null, 'description'),
labels: formatTermsObject.bind(null, 'label'),
sitelinks: formatSitelinks,
};
const datatypesSet = new Set(datatypes);
const allowedParameters = new Set([
'id', 'create', 'type', 'datatype', 'clear', 'rawMode', 'summary', 'baserevid',
'labels', 'aliases', 'descriptions', 'claims', 'statements', 'sitelinks', 'reconciliation',
'origin',
]);
function validateParameters(params) {
for (const parameter in params) {
if (!allowedParameters.has(parameter)) {
throw newError(`invalid parameter: ${parameter}`, 400, { parameter, allowedParameters, params });
}
}
}
function 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;
}
//# sourceMappingURL=edit.js.map