Update ST localizations through core api update

This commit is contained in:
Alexandre Bodin 2021-03-18 18:47:47 +01:00
parent 9a49ab64f6
commit 6679c22bdc
8 changed files with 288 additions and 254 deletions

View File

@ -15,10 +15,6 @@ const SINGLE_ENTRY_ACTIONS = ['findOne', 'update', 'delete'];
const wrapParams = async (params = {}, ctx = {}) => {
const { action } = ctx;
if (has('id', params) && SINGLE_ENTRY_ACTIONS.includes(action)) {
return params;
}
if (has(LOCALE_QUERY_FILTER, params)) {
if (params[LOCALE_QUERY_FILTER] === 'all') {
return omit(LOCALE_QUERY_FILTER, params);
@ -30,6 +26,10 @@ const wrapParams = async (params = {}, ctx = {}) => {
};
}
if (has('id', params) && SINGLE_ENTRY_ACTIONS.includes(action)) {
return params;
}
const { getDefaultLocale } = getService('locales');
return {

View File

@ -1,7 +1,7 @@
'use strict';
const _ = require('lodash');
const createService = require('../service');
const { createService, getFetchParams } = require('../service');
const maxLimit = 50;
const defaultLimit = 20;
@ -69,6 +69,9 @@ describe('Default Service', () => {
find: jest.fn(() => Promise.resolve(null)),
create: jest.fn(() => Promise.resolve({ id: 1 })),
},
query() {
return { count() {} };
},
};
const model = {
@ -102,6 +105,9 @@ describe('Default Service', () => {
find: jest.fn(() => Promise.resolve({ id: 1 })),
update: jest.fn(() => Promise.resolve({ id: 1 })),
},
query() {
return { count() {} };
},
};
const model = {
@ -194,7 +200,7 @@ describe('getFetchParams', () => {
['1000 if _limit=1000 and no max allowed limit is set', { _limit: 1000 }, 1000],
])('Sets _limit parameter to %s', (description, input, expected) => {
strapi.config.api.rest.maxLimit = input.maxLimit;
expect(createService.getFetchParams({ _limit: input._limit })).toMatchObject({
expect(getFetchParams({ _limit: input._limit })).toMatchObject({
_limit: expected,
});
});

View File

@ -43,12 +43,14 @@ const createSingleTypeController = ({ model, service }) => {
* @return {Object}
*/
async update(ctx) {
const { body, query } = ctx.request;
let entity;
if (ctx.is('multipart')) {
const { data, files } = parseMultipartData(ctx);
entity = await service.createOrUpdate(data, { files });
entity = await service.createOrUpdate(data, { files, query });
} else {
entity = await service.createOrUpdate(ctx.request.body);
entity = await service.createOrUpdate(body, { query });
}
return sanitize(entity);

View File

@ -6,7 +6,7 @@
const _ = require('lodash');
const createController = require('./controller');
const createService = require('./service');
const { createService } = require('./service');
/**
* Returns a service and a controller built based on the content type passed

View File

@ -1,245 +0,0 @@
'use strict';
const _ = require('lodash');
const utils = require('strapi-utils');
const {
contentTypes: {
hasDraftAndPublish,
constants: { PUBLISHED_AT_ATTRIBUTE, DP_PUB_STATE_LIVE },
},
} = require('strapi-utils');
/**
* Default limit values from config
* @return {{maxLimit: number, defaultLimit: number}}
*/
const getLimitConfigDefaults = () => ({
defaultLimit: _.toNumber(strapi.config.get('api.rest.defaultLimit', 100)),
maxLimit: _.toNumber(strapi.config.get('api.rest.maxLimit')) || null,
});
const getLimitParam = params => {
const { defaultLimit, maxLimit } = getLimitConfigDefaults();
if (params._limit === undefined) {
return defaultLimit;
}
const limit = _.toNumber(params._limit);
// if there is max limit set and params._limit exceeds this number, return configured max limit
if (maxLimit && (limit === -1 || limit > maxLimit)) {
return maxLimit;
}
return limit;
};
const getFetchParams = (params = {}) => {
const defaultParams = {};
Object.assign(defaultParams, {
_publicationState: DP_PUB_STATE_LIVE,
});
return {
...defaultParams,
...params,
_limit: getLimitParam(params),
};
};
/**
* default service
*
*/
const createCoreService = ({ model, strapi }) => {
const serviceFactory =
model.kind === 'singleType' ? createSingleTypeService : createCollectionTypeService;
return serviceFactory({ model, strapi });
};
/**
* Mixins
*/
const createUtils = ({ model }) => {
const { getNonWritableAttributes } = utils.contentTypes;
return {
// make sure too keep the call to getNonWritableAttributes dynamic
sanitizeInput: data => _.omit(data, getNonWritableAttributes(model)),
};
};
/**
* Returns a single type service to handle default core-api actions
*/
const createSingleTypeService = ({ model, strapi }) => {
const { modelName } = model;
const { sanitizeInput } = createUtils({ model });
return {
/**
* Returns single type content
*
* @return {Promise}
*/
find(params, populate) {
return strapi.entityService.find(
{ params: getFetchParams(params), populate },
{ model: modelName }
);
},
/**
* Creates or update the single- type content
*
* @return {Promise}
*/
async createOrUpdate(data, { files } = {}) {
const entity = await this.find();
const sanitizedData = sanitizeInput(data);
if (!entity) {
return strapi.entityService.create({ data: sanitizedData, files }, { model: modelName });
} else {
return strapi.entityService.update(
{
params: {
id: entity.id,
},
data: sanitizedData,
files,
},
{ model: modelName }
);
}
},
/**
* Deletes the single type content
*
* @return {Promise}
*/
async delete() {
const entity = await this.find();
if (!entity) return;
return strapi.entityService.delete({ params: { id: entity.id } }, { model: modelName });
},
};
};
/**
*
* Returns a collection type service to handle default core-api actions
*/
const createCollectionTypeService = ({ model, strapi }) => {
const { modelName } = model;
const { sanitizeInput } = createUtils({ model });
return {
/**
* Promise to fetch all records
*
* @return {Promise}
*/
find(params, populate) {
return strapi.entityService.find(
{ params: getFetchParams(params), populate },
{ model: modelName }
);
},
/**
* Promise to fetch record
*
* @return {Promise}
*/
findOne(params, populate) {
return strapi.entityService.findOne(
{ params: getFetchParams(params), populate },
{ model: modelName }
);
},
/**
* Promise to count record
*
* @return {Promise}
*/
count(params) {
return strapi.entityService.count({ params: getFetchParams(params) }, { model: modelName });
},
/**
* Promise to add record
*
* @return {Promise}
*/
create(data, { files } = {}) {
const sanitizedData = sanitizeInput(data);
if (hasDraftAndPublish(model)) {
sanitizedData[PUBLISHED_AT_ATTRIBUTE] = _.get(
sanitizedData,
PUBLISHED_AT_ATTRIBUTE,
new Date()
);
}
return strapi.entityService.create({ data: sanitizedData, files }, { model: modelName });
},
/**
* Promise to edit record
*
* @return {Promise}
*/
update(params, data, { files } = {}) {
const sanitizedData = sanitizeInput(data);
return strapi.entityService.update(
{ params, data: sanitizedData, files },
{ model: modelName }
);
},
/**
* Promise to delete a record
*
* @return {Promise}
*/
delete(params) {
return strapi.entityService.delete({ params }, { model: modelName });
},
/**
* Promise to search records
*
* @return {Promise}
*/
search(params) {
return strapi.entityService.search({ params }, { model: modelName });
},
/**
* Promise to count searched records
*
* @return {Promise}
*/
countSearch(params) {
return strapi.entityService.countSearch(
{ params: getFetchParams(params) },
{ model: modelName }
);
},
};
};
module.exports = createCoreService;
module.exports.getFetchParams = getFetchParams;

View File

@ -0,0 +1,122 @@
'use strict';
const { propOr } = require('lodash/fp');
const {
hasDraftAndPublish,
constants: { PUBLISHED_AT_ATTRIBUTE },
} = require('strapi-utils').contentTypes;
const setPublishedAt = data => {
data[PUBLISHED_AT_ATTRIBUTE] = propOr(new Date(), PUBLISHED_AT_ATTRIBUTE, data);
};
/**
*
* Returns a collection type service to handle default core-api actions
*/
const createCollectionTypeService = ({ model, strapi, utils }) => {
const { modelName } = model;
const { sanitizeInput, getFetchParams } = utils;
return {
/**
* Promise to fetch all records
*
* @return {Promise}
*/
find(params, populate) {
return strapi.entityService.find(
{ params: getFetchParams(params), populate },
{ model: modelName }
);
},
/**
* Promise to fetch record
*
* @return {Promise}
*/
findOne(params, populate) {
return strapi.entityService.findOne(
{ params: getFetchParams(params), populate },
{ model: modelName }
);
},
/**
* Promise to count record
*
* @return {Promise}
*/
count(params) {
return strapi.entityService.count({ params: getFetchParams(params) }, { model: modelName });
},
/**
* Promise to add record
*
* @return {Promise}
*/
create(data, { files } = {}) {
const sanitizedData = sanitizeInput(data);
if (hasDraftAndPublish(model)) {
setPublishedAt(sanitizedData);
}
return strapi.entityService.create({ data: sanitizedData, files }, { model: modelName });
},
/**
* Promise to edit record
*
* @return {Promise}
*/
update(params, data, { files } = {}) {
const sanitizedData = sanitizeInput(data);
return strapi.entityService.update(
{ params, data: sanitizedData, files },
{ model: modelName }
);
},
/**
* Promise to delete a record
*
* @return {Promise}
*/
delete(params) {
return strapi.entityService.delete({ params }, { model: modelName });
},
/**
* Promise to search records
*
* @return {Promise}
*/
search(params) {
return strapi.entityService.search({ params }, { model: modelName });
},
/**
* Promise to count searched records
*
* @return {Promise}
*/
countSearch(params) {
return strapi.entityService.countSearch(
{ params: getFetchParams(params) },
{ model: modelName }
);
},
};
};
module.exports = createCollectionTypeService;

View File

@ -0,0 +1,81 @@
'use strict';
const _ = require('lodash');
const {
isSingleType,
getNonWritableAttributes,
constants: { DP_PUB_STATE_LIVE },
} = require('strapi-utils').contentTypes;
const createSingleTypeService = require('./single-type');
const createCollectionTypeService = require('./collection-type');
/**
* Returns a core api for the provided model
* @param {{ model: object, strapi: object }} context
* @returns {object}
*/
const createService = ({ model, strapi }) => {
const utils = createUtils({ model });
if (isSingleType(model)) {
return createSingleTypeService({ model, strapi, utils });
}
return createCollectionTypeService({ model, strapi, utils });
};
/**
* Default limit values from config
* @return {{maxLimit: number, defaultLimit: number}}
*/
const getLimitConfigDefaults = () => ({
defaultLimit: _.toNumber(strapi.config.get('api.rest.defaultLimit', 100)),
maxLimit: _.toNumber(strapi.config.get('api.rest.maxLimit')) || null,
});
const getLimitParam = params => {
const { defaultLimit, maxLimit } = getLimitConfigDefaults();
if (params._limit === undefined) {
return defaultLimit;
}
const limit = _.toNumber(params._limit);
// if there is max limit set and params._limit exceeds this number, return configured max limit
if (maxLimit && (limit === -1 || limit > maxLimit)) {
return maxLimit;
}
return limit;
};
/**
* Create default fetch params
* @param {*} params
* @returns
*/
const getFetchParams = (params = {}) => {
return {
_publicationState: DP_PUB_STATE_LIVE,
...params,
_limit: getLimitParam(params),
};
};
/**
* Mixins
*/
const createUtils = ({ model }) => {
return {
// make sure too keep the call to getNonWritableAttributes dynamic
sanitizeInput: data => _.omit(data, getNonWritableAttributes(model)),
getFetchParams,
};
};
module.exports = {
createService,
getFetchParams,
};

View File

@ -0,0 +1,68 @@
'use strict';
/**
* Returns a single type service to handle default core-api actions
*/
const createSingleTypeService = ({ model, strapi, utils }) => {
const { modelName } = model;
const { sanitizeInput, getFetchParams } = utils;
return {
/**
* Returns single type content
*
* @return {Promise}
*/
find(params, populate) {
return strapi.entityService.find(
{ params: getFetchParams(params), populate },
{ model: modelName }
);
},
/**
* Creates or update the single- type content
*
* @return {Promise}
*/
async createOrUpdate(data, { files, query } = {}) {
const entity = await this.find(query);
const sanitizedData = sanitizeInput(data);
if (!entity) {
const count = await strapi.query(modelName).count();
if (count >= 1) {
throw strapi.errors.badRequest('singleType.alreadyExists');
}
return strapi.entityService.create({ data: sanitizedData, files }, { model: modelName });
} else {
return strapi.entityService.update(
{
params: {
id: entity.id,
},
data: sanitizedData,
files,
},
{ model: modelName }
);
}
},
/**
* Deletes the single type content
*
* @return {Promise}
*/
async delete() {
const entity = await this.find();
if (!entity) return;
return strapi.entityService.delete({ params: { id: entity.id } }, { model: modelName });
},
};
};
module.exports = createSingleTypeService;