Skip to content
This repository has been archived by the owner on Nov 25, 2022. It is now read-only.

Commit

Permalink
Merge branch 'refactor' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
EdisonPeM committed Jun 17, 2021
2 parents 7ea6829 + 818305c commit b4f0fb0
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 140 deletions.
10 changes: 5 additions & 5 deletions services/analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ function analyze(items) {
fieldNames.forEach((fieldName) => {
const fieldData = item[fieldName];

// Missig data
if ([null, undefined, ""].includes(fieldData)) return;

const fieldFormat = getFormatFromField(fieldData);
fieldsFormats[fieldName].push(fieldFormat);
// Get format from valid data
if (fieldData !== null && fieldData !== undefined) {
const fieldFormat = getFormatFromField(fieldData);
fieldsFormats[fieldName].push(fieldFormat);
}
});
});

Expand Down
21 changes: 11 additions & 10 deletions services/utils/csvParser.js → services/contentParser/csvParser.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const {
isNumber,
isBoolean,
isString,
isObject,
} = require("./formatsValidator");
textIsNumber,
textToNumber,
textIsBoolean,
textToBoolean,
textIsObject,
textToObject,
} = require("./textFormats");
const CsvParser = require("csv-parse/lib/sync");
const CSV = require("csv-string");

Expand All @@ -15,11 +17,10 @@ function csvToJson(text) {

// Try to convert the format of the values
cast: (value) => {
if (isNumber(value)) return parseFloat(value);
else if (isBoolean(value))
if (isString(value)) return value === "true";
else return value;
else if (isObject(value)) return JSON.parse(value);
if (value === "") return null;
else if (textIsNumber(value)) return textToNumber(value);
else if (textIsBoolean(value)) return textToBoolean(value);
else if (textIsObject(value)) return textToObject(value);
else return value;
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { csvToJson, jsonToCsv } = require("./csvParser");
const { getFieldsFromItems } = require("./fieldUtils");
const { getFieldsFromItems } = require("../utils/fieldUtils");

const toArray = (arr) => (Array.isArray(arr) ? arr : [arr]);

Expand Down
61 changes: 61 additions & 0 deletions services/contentParser/textFormats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// ------------------------------------- //
// Number Validation //
// ------------------------------------- //
function textIsNumber(value) {
if (typeof value === "string" && value.trim() !== "") {
return !isNaN(value);
}

return false;
}

function textToNumber(value) {
return parseFloat(value);
}

// -------------------------------------- //
// Boolean Validation //
// -------------------------------------- //
const booleanStringPossibleValues = {
trueValues: ["true", "t"],
falseValues: ["false", "f"],
};

function textIsBoolean(value) {
return (
booleanStringPossibleValues.trueValues.includes(value.toLowerCase()) ||
booleanStringPossibleValues.falseValues.includes(value.toLowerCase())
);
}

function textToBoolean(value) {
return booleanStringPossibleValues.trueValues.includes(value);
}

// ------------------------------------- //
// Object Validation //
// ------------------------------------- //
function textIsObject(value) {
try {
JSON.parse(value);
return true;
} catch {
return false;
}
}

function textToObject(value) {
return JSON.parse(value);
}

// --------------------------- //
// Exports //
// --------------------------- //
module.exports = {
textIsNumber,
textToNumber,
textIsBoolean,
textToBoolean,
textIsObject,
textToObject,
};
20 changes: 15 additions & 5 deletions services/import-export-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
* @description: A set of functions similar to controller's actions to avoid code duplication.
*/

const { getItemsFromContent } = require("./utils/contentParser");
const { getItemsFromContent, getContentFromItems } = require("./contentParser");
const { analyze } = require("./analyzer");

const { mapFieldsToTargetFields } = require("./utils/fieldUtils");
const { importContent } = require("./importer");
const { PUBLISHED_AT_ATTRIBUTE } = require("../constants/contentTypes");
const {
CREATED_BY_ATTRIBUTE,
UPDATED_BY_ATTRIBUTE,
PUBLISHED_AT_ATTRIBUTE,
} = require("../constants/contentTypes");

const { getContentFromItems } = require("./utils/contentParser");
const { getAll } = require("./exporter");

module.exports = {
Expand All @@ -27,15 +30,22 @@ module.exports = {
importItems: async (ctx) => {
const { user } = ctx.state;
const { target, fields, items, asDraft } = ctx.request.body;
const { attributes } = target;

const {
attributes,
options: { draftAndPublish },
} = target;

const mappedItems = await mapFieldsToTargetFields({
items,
fields,
attributes,
user,
});
return importContent(target, mappedItems, {
[PUBLISHED_AT_ATTRIBUTE]: asDraft ? null : Date.now(),
[CREATED_BY_ATTRIBUTE]: user,
[UPDATED_BY_ATTRIBUTE]: user,
[PUBLISHED_AT_ATTRIBUTE]: draftAndPublish && asDraft ? null : Date.now(),
});
},

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { urlIsMedia } = require("./formatsValidator");
const { urlIsMedia } = require("../utils/formatsValidator");
const request = require("request");

const fetchFiles = (url) =>
Expand Down Expand Up @@ -49,7 +49,8 @@ async function importMediaFromUrl(url, user) {
user,
});

return uploadedFile?.id || null;
if (uploadedFile && uploadedFile.id) return uploadedFile.id;
return null;
} catch (err) {
console.error(err);
return null;
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions services/importer.js → services/importer/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const { COLLECTION_TYPE, SINGLE_TYPE } = require("../constants/contentTypes");
const {
importToCollectionType,
importToSingleType,
} = require("./utils/importUtils");
COLLECTION_TYPE,
SINGLE_TYPE,
} = require("../../constants/contentTypes");
const { importToCollectionType, importToSingleType } = require("./importUtils");

function importContent(target, items, options) {
const { uid, kind } = target;
Expand Down
96 changes: 43 additions & 53 deletions services/utils/contentChecker.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,56 @@
const { isNumber, isString, urlIsMedia } = require("./formatsValidator");
const { MANY_RELATIONS } = require("../../constants/relations");
const { importMediaFromUrl } = require("./importMediaFiles");
const { urlIsMedia } = require("./formatsValidator");
const { importMediaFromUrl } = require("../importer/importMediaFiles");

function getId(value) {
if (isNumber(value)) return parseInt(value);
return value?.id || null;
if (typeof value === "number") return value;
if (typeof value === "object" && value.id) return value.id;
return null;
}

async function getValidContent({ value, attribute, user }) {
const { type } = attribute;

if (type === "media") {
const { multiple } = attribute;
if (multiple) {
if (!Array.isArray(value)) return [];
const urls = value.filter((v) => isString(v) && urlIsMedia(v));
const uploadedFiles = await Promise.all(
urls.map((url) => importMediaFromUrl(url, user))
);

const ids = value.map(getId).filter((v) => v !== null);
const entities = await strapi
.query("file", "upload")
.find({ id_in: ids });

return [...uploadedFiles, ...entities.map(({ id }) => id)];
} else {
if (Array.isArray(value)) return null;

// Upload url to plugin upload
if (isString(value) && urlIsMedia(value)) {
return importMediaFromUrl(value, user);
}

const id = getId(value);
const entity = await strapi.query("file", "upload").findOne({ id });
return entity?.id || null;
}
async function getValidRelations(value, attribute) {
const { relationType, targetModel } = attribute;
if (MANY_RELATIONS.includes(relationType)) {
const relations = Array.isArray(value) ? value : [value];
const ids = relations.map(getId);
const entities = await strapi.query(targetModel).find({ id_in: ids });
return entities.map(({ id }) => id);
} else {
const relation = Array.isArray(value) ? value[0] : value;
const id = getId(relation);
const entity = await strapi.query(targetModel).findOne({ id });
return entity ? entity.id : null;
}
}

if (type === "relation") {
const { relationType, targetModel } = attribute;

if (MANY_RELATIONS.includes(relationType)) {
if (!Array.isArray(value)) return [];
const ids = value.map(getId);

const entities = await strapi.query(targetModel).find({ id_in: ids });
return entities.map(({ id }) => id);
} else {
if (Array.isArray(value)) return null;

const id = getId(value);
const entity = await strapi.query(targetModel).findOne({ id });
return entity?.id || null;
async function getValidMedia(value, attribute, user) {
const { multiple } = attribute;
if (multiple) {
const medias = Array.isArray(value) ? value : [value];
const urls = medias.filter((v) => urlIsMedia(v));
const uploadedFiles = await Promise.all(
urls.map((url) => importMediaFromUrl(url, user))
);

const ids = medias.map(getId).filter((v) => v !== null);
const entities = await strapi.query("file", "upload").find({ id_in: ids });

return [...uploadedFiles, ...entities.map(({ id }) => id)];
} else {
const media = Array.isArray(value) ? value[0] : value;

// Upload url to plugin upload
if (urlIsMedia(media)) {
return importMediaFromUrl(media, user);
}
}

// Other types are not validated
return value;
const id = getId(media);
const entity = await strapi.query("file", "upload").findOne({ id });
return entity ? entity.id : null;
}
}

module.exports = {
getValidContent,
getValidRelations,
getValidMedia,
};
24 changes: 8 additions & 16 deletions services/utils/fieldUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ const {
stringIsUrl,
urlIsMedia,
} = require("./formatsValidator");
const { getValidContent } = require("./contentChecker");
const {
CREATED_BY_ATTRIBUTE,
UPDATED_BY_ATTRIBUTE,
} = require("../../constants/contentTypes");
const { getValidRelations, getValidMedia } = require("./contentChecker");

function getFormatFromField(field) {
switch (typeof field) {
Expand Down Expand Up @@ -50,23 +46,19 @@ function mapFieldsToTargetFields({ items, fields, attributes, user }) {
const fieldNames = getFieldsFromItems(items);
return Promise.all(
items.map(async (item) => {
const mappedItem = {
[CREATED_BY_ATTRIBUTE]: user,
[UPDATED_BY_ATTRIBUTE]: user,
};
const mappedItem = {};

for (const fieldname of fieldNames) {
const { targetField } = fields[fieldname];
if (targetField && targetField !== "none") {
const { type } = attributes[targetField];
const attribute = attributes[targetField];
let targetItem = item[fieldname];

if (["media", "relation"].includes(type)) {
targetItem = await getValidContent({
user,
value: targetItem,
attribute: attributes[targetField],
});
// Validate ids and import medias
if (attribute.type === "relation") {
targetItem = await getValidRelations(targetItem, attribute);
} else if (attribute.type === "media") {
targetItem = await getValidMedia(targetItem, attribute, user);
}

mappedItem[targetField] = targetItem;
Expand Down
Loading

0 comments on commit b4f0fb0

Please sign in to comment.