UNPKG

strapi-plugin-import-export-entries

Version:

Import/Export data from and to your database in just few clicks.

218 lines (217 loc) 8.65 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const { isArraySafe, toArray } = require('../../../libs/arrays'); const { ObjectBuilder, isObjectSafe } = require('../../../libs/objects'); const { CustomSlugs } = require('../../config/constants'); const { getModelAttributes, getModel } = require('../../utils/models'); const { findOrImportFile } = require('./utils/file'); const { parseInputData } = require('./parsers'); /** * @typedef {Object} ImportDataRes * @property {Array<ImportDataFailures>} failures */ /** * Represents failed imports. * @typedef {Object} ImportDataFailures * @property {Error} error - Error raised. * @property {Object} data - Data for which import failed. */ /** * Import data. * @param {Array<Object>} dataRaw - Data to import. * @param {Object} options * @param {string} options.slug - Slug of the model to import. * @param {("csv" | "json")} options.format - Format of the imported data. * @param {Object} options.user - User importing the data. * @param {Object} options.idField - Field used as unique identifier. * @returns {Promise<ImportDataRes>} */ const importData = (dataRaw, { slug, format, user, idField }) => __awaiter(void 0, void 0, void 0, function* () { let data = yield parseInputData(format, dataRaw, { slug }); data = toArray(data); let res; if (slug === CustomSlugs.MEDIA) { res = yield importMedia(data, { user }); } else { res = yield importOtherSlug(data, { slug, user, idField }); } return res; }); const importMedia = (fileData, { user }) => __awaiter(void 0, void 0, void 0, function* () { const processed = []; for (let fileDatum of fileData) { let res; try { yield findOrImportFile(fileDatum, user, { allowedFileTypes: ['any'] }); res = { success: true }; } catch (err) { strapi.log.error(err); res = { success: false, error: err.message, args: [fileDatum] }; } processed.push(res); } const failures = processed.filter((p) => !p.success).map((f) => ({ error: f.error, data: f.args[0] })); return { failures, }; }); const importOtherSlug = (data, { slug, user, idField }) => __awaiter(void 0, void 0, void 0, function* () { const processed = []; for (let datum of data) { let res; try { yield updateOrCreate(user, slug, datum, idField); res = { success: true }; } catch (err) { strapi.log.error(err); res = { success: false, error: err.message, args: [datum] }; } processed.push(res); } const failures = processed.filter((p) => !p.success).map((f) => ({ error: f.error, data: f.args[0] })); return { failures, }; }); /** * Update or create entries for a given model. * @param {Object} user - User importing the data. * @param {string} slug - Slug of the model. * @param {Object} data - Data to update/create entries from. * @param {string} idField - Field used as unique identifier. * @returns Updated/created entry. */ const updateOrCreate = (user, slug, data, idField = 'id') => __awaiter(void 0, void 0, void 0, function* () { const relationAttributes = getModelAttributes(slug, { filterType: ['component', 'dynamiczone', 'media', 'relation'] }); for (let attribute of relationAttributes) { data[attribute.name] = yield updateOrCreateRelation(user, attribute, data[attribute.name]); } let entry; const model = getModel(slug); if (model.kind === 'singleType') { entry = yield updateOrCreateSingleType(user, slug, data, idField); } else { entry = yield updateOrCreateCollectionType(user, slug, data, idField); } return entry; }); const updateOrCreateCollectionType = (user, slug, data, idField) => __awaiter(void 0, void 0, void 0, function* () { const whereBuilder = new ObjectBuilder(); if (data[idField]) { whereBuilder.extend({ [idField]: data[idField] }); } const where = whereBuilder.get(); // Prevent strapi from throwing a unique constraint error on id field. if (idField !== 'id') { delete data.id; } let entry; if (!where[idField]) { entry = yield strapi.db.query(slug).create({ data }); } else { entry = yield strapi.db.query(slug).update({ where, data }); if (!entry) { entry = yield strapi.db.query(slug).create({ data }); } } return entry; }); const updateOrCreateSingleType = (user, slug, data, idField) => __awaiter(void 0, void 0, void 0, function* () { delete data.id; let [entry] = yield strapi.db.query(slug).findMany(); if (!entry) { entry = yield strapi.db.query(slug).create({ data }); } else { entry = yield strapi.db.query(slug).update({ where: { id: entry.id }, data }); } return entry; }); /** * Update or create a relation. * @param {Object} user * @param {Attribute} rel * @param {number | Object | Array<Object>} relData */ const updateOrCreateRelation = (user, rel, relData) => __awaiter(void 0, void 0, void 0, function* () { var _a; if (relData == null) { return null; } if (['createdBy', 'updatedBy'].includes(rel.name)) { return user.id; } else if (rel.type === 'dynamiczone') { const components = []; for (const componentDatum of relData || []) { let component = yield updateOrCreate(user, componentDatum.__component, componentDatum); component = Object.assign(Object.assign({}, component), { __component: componentDatum.__component }); components.push(component); } return components; } else if (rel.type === 'component') { relData = toArray(relData); relData = rel.repeatable ? relData : relData.slice(0, 1); const entryIds = []; for (const relDatum of relData) { if (typeof relDatum === 'number') { entryIds.push(relDatum); } else if (isObjectSafe(relDatum)) { const entry = yield updateOrCreate(user, rel.component, relDatum); if (entry === null || entry === void 0 ? void 0 : entry.id) { entryIds.push(entry.id); } } } return rel.repeatable ? entryIds : (entryIds === null || entryIds === void 0 ? void 0 : entryIds[0]) || null; } else if (rel.type === 'media') { relData = toArray(relData); relData = rel.multiple ? relData : relData.slice(0, 1); const entryIds = []; for (const relDatum of relData) { const media = yield findOrImportFile(relDatum, user, { allowedFileTypes: (_a = rel.allowedTypes) !== null && _a !== void 0 ? _a : ['any'] }); if (media === null || media === void 0 ? void 0 : media.id) { entryIds.push(media.id); } } return rel.multiple ? entryIds : (entryIds === null || entryIds === void 0 ? void 0 : entryIds[0]) || null; } else if (rel.type === 'relation') { const isMultiple = isArraySafe(relData); relData = toArray(relData); const entryIds = []; for (const relDatum of relData) { if (typeof relDatum === 'number') { entryIds.push(relDatum); } else if (isObjectSafe(relDatum)) { const entry = yield updateOrCreate(user, rel.target, relDatum); if (entry === null || entry === void 0 ? void 0 : entry.id) { entryIds.push(entry.id); } } } return isMultiple ? entryIds : (entryIds === null || entryIds === void 0 ? void 0 : entryIds[0]) || null; } throw new Error(`Could not update or create relation of type ${rel.type}.`); }); module.exports = { importData, };