Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(gatsby): migrate date to TypeScript #22430

Merged
merged 4 commits into from
Jul 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/gatsby/src/schema/extensions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const {
} = require(`graphql`)

const { link, fileByPath } = require(`../resolvers`)
const { getDateResolver } = require(`../types/date`)
import { getDateResolver } from "../types/date"

import type { GraphQLFieldConfigArgumentMap, GraphQLFieldConfig } from "graphql"
import type { ComposeFieldConfig, ComposeOutputType } from "graphql-compose"
Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby/src/schema/infer/add-inferred-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const invariant = require(`invariant`)
const report = require(`gatsby-cli/lib/reporter`)

import { isFile } from "./is-file"
const { isDate } = require(`../types/date`)
import { isDate } from "../types/date"
const { addDerivedType } = require(`../types/derived-types`)
import { is32BitInteger } from "../../utils/is-32-bit-integer"
const { getNode, getNodes } = require(`../../redux/nodes`)
Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby/src/schema/schema-composer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { SchemaComposer, GraphQLJSON } = require(`graphql-compose`)
const { getNodeInterface } = require(`./types/node-interface`)
const { GraphQLDate } = require(`./types/date`)
import { GraphQLDate } from "./types/date"
const { addDirectives } = require(`./extensions`)

const createSchemaComposer = ({ fieldExtensions } = {}) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby/src/schema/types/__tests__/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { actions } = require(`../../../redux/actions`)
const { build } = require(`../..`)
const withResolverContext = require(`../../context`)
const { defaultResolver } = require(`../../resolvers`)
const { isDate, looksLikeADate } = require(`../date`)
import { isDate, looksLikeADate } from "../date"

jest.mock(`gatsby-cli/lib/reporter`, () => {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const {
GraphQLInputObjectType,
Kind,
} = require(`graphql`)
const { GraphQLDate } = require(`../date`)
import { GraphQLDate } from "../date"
const { GraphQLJSON } = require(`graphql-compose`)

const getInferredFields = fields => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
const moment = require(`moment`)
const { GraphQLScalarType, Kind } = require(`graphql`)
const { oneLine } = require(`common-tags`)
import moment, { MomentInput, unitOfTime, LocaleSpecifier } from "moment"
import { GraphQLScalarType, Kind, GraphQLFieldConfig } from "graphql"
import { oneLine } from "common-tags"

interface IFormatDateArgs {
date?: Date
fromNow?: boolean
formatString?: string
difference?: unitOfTime.Diff
locale?: LocaleSpecifier
}
interface IDateResolverOption {
locale?: string
formatString?: string
fromNow?: string
difference?: string
from?: string
fromNode?: { type: string; defaultValue: boolean }
}
type DateResolverFieldConfig = GraphQLFieldConfig<any, any, any>
type DateResolver = (
source: any,
args: any,
context: any,
info: any
) => Promise<null | string | number | (string | number)[]>

const ISO_8601_FORMAT = [
`YYYY`,
Expand Down Expand Up @@ -79,14 +102,14 @@ const ISO_8601_FORMAT = [
`YYYYDDDD`,
]

const GraphQLDate = new GraphQLScalarType({
export const GraphQLDate = new GraphQLScalarType({
name: `Date`,
description: oneLine`
A date string, such as 2007-12-03, compliant with the ISO 8601 standard
for representation of dates and times using the Gregorian calendar.`,
serialize: String,
parseValue: String,
parseLiteral(ast) {
parseLiteral(ast): string | undefined {
return ast.kind === Kind.STRING ? ast.value : undefined
},
})
Expand All @@ -109,20 +132,22 @@ const momentFormattingRegexes = {
".": `\\.`,
Z: `(Z|[+-]\\d\\d(?::?\\d\\d)?)`,
}
const ISO_8601_FORMAT_AS_REGEX = ISO_8601_FORMAT.map(format =>
const ISO_8601_FORMAT_AS_REGEX = ISO_8601_FORMAT.map(format => {
const matchedFormat = format.match(momentFormattingTokens)
if (matchedFormat === null) return ``
// convert ISO string to a map of momentTokens ([YYYY, MM, DD])
[...format.match(momentFormattingTokens)]
return [...matchedFormat]
.map(token =>
// see if the token (YYYY or ss) is found, else we just return the value
momentFormattingRegexes[token] ? momentFormattingRegexes[token] : token
)
.join(``)
).join(`|`)
}).join(`|`)

// calculate all lengths of the formats, if a string is longer or smaller it can't be valid
const ISO_8601_FORMAT_LENGTHS = [
...new Set(
ISO_8601_FORMAT.reduce((acc, val) => {
ISO_8601_FORMAT.reduce((acc: number[], val: string) => {
if (!val.endsWith(`Z`)) {
return acc.concat(val.length)
}
Expand Down Expand Up @@ -154,7 +179,7 @@ const looksLikeDateEndRegex = /(\d|Z)$/
* @param {*} value
* @return {boolean}
*/
function looksLikeADate(value) {
export function looksLikeADate(value?: string): boolean {
// quick check if value does not look like a date
if (
!value ||
Expand All @@ -178,7 +203,7 @@ function looksLikeADate(value) {
* @param {*} value
* @return {boolean}
*/
function isDate(value) {
export function isDate(value: MomentInput): boolean {
const momentDate = moment.utc(value, ISO_8601_FORMAT, true)
return typeof value !== `number` && momentDate.isValid()
}
Expand All @@ -189,7 +214,7 @@ const formatDate = ({
difference,
formatString,
locale = `en`,
}) => {
}: IFormatDateArgs): string | number => {
const normalizedDate = JSON.parse(JSON.stringify(date))
if (formatString) {
return moment
Expand All @@ -210,7 +235,10 @@ const formatDate = ({
return normalizedDate
}

const getDateResolver = (options = {}, fieldConfig) => {
export const getDateResolver = (
options: IDateResolverOption = {},
fieldConfig: DateResolverFieldConfig
): { args: Record<string, any>; resolve: DateResolver } => {
const { locale, formatString, fromNow, difference } = options
return {
args: {
Expand Down Expand Up @@ -246,7 +274,7 @@ const getDateResolver = (options = {}, fieldConfig) => {
defaultValue: locale,
},
},
async resolve(source, args, context, info) {
async resolve(source, args, context, info): ReturnType<DateResolver> {
const resolver = fieldConfig.resolve || context.defaultFieldResolver
const date = await resolver(source, args, context, {
...info,
Expand All @@ -261,5 +289,3 @@ const getDateResolver = (options = {}, fieldConfig) => {
},
}
}

module.exports = { GraphQLDate, getDateResolver, isDate, looksLikeADate }
2 changes: 1 addition & 1 deletion packages/gatsby/src/schema/types/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {
const { addDerivedType } = require(`./derived-types`)
const { InputTypeComposer } = require(`graphql-compose`)
const { GraphQLJSON } = require(`graphql-compose`)
const { GraphQLDate } = require(`./date`)
import { GraphQLDate } from "./date"

const SEARCHABLE_ENUM = {
SEARCHABLE: `SEARCHABLE`,
Expand Down