diff --git a/packages/strapi-connector-bookshelf/lib/buildDatabaseSchema.js b/packages/strapi-connector-bookshelf/lib/buildDatabaseSchema.js index afdb743de8..e156ae735a 100644 --- a/packages/strapi-connector-bookshelf/lib/buildDatabaseSchema.js +++ b/packages/strapi-connector-bookshelf/lib/buildDatabaseSchema.js @@ -283,15 +283,22 @@ module.exports = async ({ // Add created_at and updated_at field if timestamp option is true if (hasTimestamps) { definition.attributes[createAtCol] = { - type: 'timestamp', + type: 'currentTimestamp', }; definition.attributes[updatedAtCol] = { type: 'timestampUpdate', }; } - // Save all attributes (with timestamps) - model.allAttributes = _.clone(definition.attributes); + // Save all attributes (with timestamps) and right type + model.allAttributes = _.assign(_.clone(definition.attributes), { + [createAtCol]: { + type: 'timestamp', + }, + [updatedAtCol]: { + type: 'timestamp', + }, + }); // Equilize tables if (connection.options && connection.options.autoMigration !== false) { @@ -410,29 +417,34 @@ const getType = ({ definition, attribute, name, tableExists = false }) => { return client === 'pg' ? 'double precision' : 'double'; case 'decimal': return 'decimal(10,2)'; - // TODO: split time types as they should be different case 'date': return 'date'; case 'time': return 'time'; case 'datetime': { - if (client === 'pg') { - return 'timestamp with time zone'; - } - return 'timestamp'; + if (client === 'pg') return 'timestampz'; + return 'datetime'; } case 'timestamp': { if (client === 'pg') { - return 'timestamp with time zone'; + return 'timestampz'; + } + + return 'timestamp'; + } + case 'currentTimestamp': { + if (client === 'pg') { + return 'timestamp with time zone DEFAULT CURRENT_TIMESTAMP'; } else if (client === 'sqlite3' && tableExists) { return 'timestamp DEFAULT NULL'; } + return 'timestamp DEFAULT CURRENT_TIMESTAMP'; } case 'timestampUpdate': switch (client) { case 'pg': - return 'timestamp with time zone'; + return 'timestamp with time zone DEFAULT CURRENT_TIMESTAMP'; case 'sqlite3': if (tableExists) { return 'timestamp DEFAULT NULL'; diff --git a/packages/strapi-connector-bookshelf/lib/parser.js b/packages/strapi-connector-bookshelf/lib/parser.js index 97710c2a24..6e4419633c 100644 --- a/packages/strapi-connector-bookshelf/lib/parser.js +++ b/packages/strapi-connector-bookshelf/lib/parser.js @@ -1,7 +1,6 @@ 'use strict'; const { parseType } = require('strapi-utils'); -const { parse, isValid, parseISO } = require('date-fns'); const createParser = () => (type, value) => { if (value === null) return null; @@ -9,48 +8,9 @@ const createParser = () => (type, value) => { switch (type) { case 'json': return JSON.stringify(value); - case 'time': - return parseType({ type: 'time', value }); - case 'date': - return parseDate(value); - case 'timestamp': - case 'datetime': - return parseDateTimeOrTimestamp(value); default: - return value; + return parseType({ type, value }); } }; -const parseDateOrThrow = format => value => { - try { - let date = parseISO(value); - if (isValid(date)) return date; - - date = parse(value, format, new Date()); - - if (isValid(date)) { - return date; - } else { - throw new Error(`Invalid format, expected a ${format}`); - } - } catch (error) { - throw new Error(`Invalid format, expected a ${format}`); - } -}; - -const parseDateTimeOrTimestamp = value => { - const date = parseISO(value); - if (isValid(date)) return date; - - date.setTime(value); - - if (!isValid(date)) { - throw new Error(`Invalid format, expected a timestamp or an ISO date`); - } - - return date; -}; - -const parseDate = parseDateOrThrow('yyyy-MM-dd'); - module.exports = { createParser }; diff --git a/packages/strapi-connector-mongoose/lib/mount-models.js b/packages/strapi-connector-mongoose/lib/mount-models.js index c2e33e43d2..7d566ae1c9 100644 --- a/packages/strapi-connector-mongoose/lib/mount-models.js +++ b/packages/strapi-connector-mongoose/lib/mount-models.js @@ -203,7 +203,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => { type: 'timestamp', }; target[model].allAttributes[updatedAtCol] = { - type: 'timestampUpdate', + type: 'timestamp', }; } else if (timestampsOption === true) { schema.set('timestamps', true); @@ -214,7 +214,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => { type: 'timestamp', }; target[model].allAttributes.updatedAt = { - type: 'timestampUpdate', + type: 'timestamp', }; } schema.set( diff --git a/packages/strapi-utils/lib/parse-type.js b/packages/strapi-utils/lib/parse-type.js index a98895a4d8..c6cac4a3ed 100644 --- a/packages/strapi-utils/lib/parse-type.js +++ b/packages/strapi-utils/lib/parse-type.js @@ -1,6 +1,7 @@ 'use strict'; const _ = require('lodash'); +const dates = require('date-fns'); const timeRegex = new RegExp( '^(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]{1,3})?$' @@ -19,6 +20,30 @@ const parseTime = value => { return `${hours}:${minutes}:${seconds}.${fractionPart}`; }; +const parseDate = value => { + try { + let date = dates.parseISO(value); + if (dates.isValid(date)) return dates.format(date, 'yyyy-MM-dd'); + + throw new Error(`Invalid format, expected an ISO compatble date`); + } catch (error) { + throw new Error(`Invalid format, expected an ISO compatble date`); + } +}; + +const parseDateTimeOrTimestamp = value => { + const date = dates.parseISO(value); + if (dates.isValid(date)) return date; + + dates.setTime(date, value); + + if (!dates.isValid(date)) { + throw new Error(`Invalid format, expected a timestamp or an ISO date`); + } + + return date; +}; + /** * Cast basic values based on attribute type * @param {Object} options - Options @@ -47,6 +72,13 @@ const parseType = ({ type, value }) => { case 'time': { return parseTime(value); } + case 'date': { + return parseDate(value); + } + case 'timestamp': + case 'datetime': { + return parseDateTimeOrTimestamp(value); + } default: return value; }