Skip to content

Commit

Permalink
move infering date field to seperate file to improve code readability
Browse files Browse the repository at this point in the history
  • Loading branch information
pieh committed Jan 25, 2018
1 parent d86dba6 commit 266f8d7
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 86 deletions.
89 changes: 3 additions & 86 deletions packages/gatsby/src/schema/infer-graphql-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const {
} = require(`graphql`)
const _ = require(`lodash`)
const invariant = require(`invariant`)
const moment = require(`moment`)
const mime = require(`mime`)
const isRelative = require(`is-relative`)
const isRelativeUrl = require(`is-relative-url`)
Expand All @@ -27,6 +26,7 @@ const {
extractFieldExamples,
isEmptyObjectOrArray,
} = require(`./data-tree-utils`)
const DateType = require("./types/type-date")

import type { GraphQLOutputType } from "graphql"
import type {
Expand All @@ -42,26 +42,6 @@ export type ProcessedNodeType = {
nodeObjectType: GraphQLOutputType,
}

const ISO_8601_FORMAT = [
`YYYY`,
`YYYY-MM`,
`YYYY-MM-DD`,
`YYYYMMDD`,
`YYYY-MM-DDTHHZ`,
`YYYY-MM-DDTHH:mmZ`,
`YYYY-MM-DDTHHmmZ`,
`YYYY-MM-DDTHH:mm:ssZ`,
`YYYY-MM-DDTHHmmssZ`,
`YYYY-MM-DDTHH:mm:ss.SSSZ`,
`YYYY-MM-DDTHHmmss.SSSZ`,
`YYYY-[W]WW`,
`YYYY[W]WW`,
`YYYY-[W]WW-E`,
`YYYY[W]WWE`,
`YYYY-DDDD`,
`YYYYDDDD`,
]

function inferGraphQLType({
exampleValue,
selector,
Expand Down Expand Up @@ -106,71 +86,8 @@ function inferGraphQLType({
return listType
}

// Check if this is a date.
// All the allowed ISO 8601 date-time formats used.
const momentDate = moment.utc(exampleValue, ISO_8601_FORMAT, true)
if (momentDate.isValid() && typeof exampleValue !== `number`) {
return {
type: GraphQLString,
args: {
formatString: {
type: GraphQLString,
description: oneLine`
Format the date using Moment.js' date tokens e.g.
"date(formatString: "YYYY MMMM DD)"
See https://momentjs.com/docs/#/displaying/format/
for documentation for different tokens`,
},
fromNow: {
type: GraphQLBoolean,
description: oneLine`
Returns a string generated with Moment.js' fromNow function`,
},
difference: {
type: GraphQLString,
description: oneLine`
Returns the difference between this date and the current time.
Defaults to miliseconds but you can also pass in as the
measurement years, months, weeks, days, hours, minutes,
and seconds.`,
},
locale: {
type: GraphQLString,
description: oneLine`
Configures the locale Moment.js will use to format the date.
`,
},
},
resolve(object, args) {
let date
if (object[fieldName]) {
date = JSON.parse(JSON.stringify(object[fieldName]))
} else {
return null
}
if (_.isPlainObject(args)) {
const { fromNow, difference, formatString, locale = `en` } = args
if (formatString) {
return moment
.utc(date, ISO_8601_FORMAT, true)
.locale(locale)
.format(formatString)
} else if (fromNow) {
return moment
.utc(date, ISO_8601_FORMAT, true)
.locale(locale)
.fromNow()
} else if (difference) {
return moment().diff(
moment.utc(date, ISO_8601_FORMAT, true).locale(locale),
difference
)
}
}

return date
},
}
if (DateType.shouldInfer(exampleValue)) {
return DateType.createType(fieldName)
}

switch (typeof exampleValue) {
Expand Down
104 changes: 104 additions & 0 deletions packages/gatsby/src/schema/types/type-date.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
const moment = require(`moment`)
const { GraphQLString, GraphQLBoolean } = require(`graphql`)
const _ = require(`lodash`)
const { oneLine } = require(`common-tags`)

const ISO_8601_FORMAT = [
`YYYY`,
`YYYY-MM`,
`YYYY-MM-DD`,
`YYYYMMDD`,
`YYYY-MM-DDTHHZ`,
`YYYY-MM-DDTHH:mmZ`,
`YYYY-MM-DDTHHmmZ`,
`YYYY-MM-DDTHH:mm:ssZ`,
`YYYY-MM-DDTHHmmssZ`,
`YYYY-MM-DDTHH:mm:ss.SSSZ`,
`YYYY-MM-DDTHHmmss.SSSZ`,
`YYYY-[W]WW`,
`YYYY[W]WW`,
`YYYY-[W]WW-E`,
`YYYY[W]WWE`,
`YYYY-DDDD`,
`YYYYDDDD`,
]

const DateFieldDef = {
type: GraphQLString,
args: {
formatString: {
type: GraphQLString,
description: oneLine`
Format the date using Moment.js' date tokens e.g.
"date(formatString: "YYYY MMMM DD)"
See https://momentjs.com/docs/#/displaying/format/
for documentation for different tokens`,
},
fromNow: {
type: GraphQLBoolean,
description: oneLine`
Returns a string generated with Moment.js' fromNow function`,
},
difference: {
type: GraphQLString,
description: oneLine`
Returns the difference between this date and the current time.
Defaults to miliseconds but you can also pass in as the
measurement years, months, weeks, days, hours, minutes,
and seconds.`,
},
locale: {
type: GraphQLString,
description: oneLine`
Configures the locale Moment.js will use to format the date.`,
},
},
}

// Check if this is a date.
// All the allowed ISO 8601 date-time formats used.
function shouldInfer(value) {
const momentDate = moment.utc(value, ISO_8601_FORMAT, true)
return momentDate.isValid() && typeof exampleValue !== `number`
}

function createType(fieldName) {
return {
...DateFieldDef,
resolve(object, args) {
let date
if (object[fieldName]) {
date = JSON.parse(JSON.stringify(object[fieldName]))
} else {
return null
}
return formatDate(date, args)
},
}
}

function formatDate(date, args) {
if (_.isPlainObject(args)) {
const { fromNow, difference, formatString, locale = `en` } = args
if (formatString) {
return moment
.utc(date, ISO_8601_FORMAT, true)
.locale(locale)
.format(formatString)
} else if (fromNow) {
return moment
.utc(date, ISO_8601_FORMAT, true)
.locale(locale)
.fromNow()
} else if (difference) {
return moment().diff(
moment.utc(date, ISO_8601_FORMAT, true).locale(locale),
difference
)
}
}

return date
}

module.exports = { shouldInfer, createType }

0 comments on commit 266f8d7

Please sign in to comment.