Skip to content

Commit

Permalink
chore(gatsby): migrate merge-gatsby-config to TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
taejs committed May 12, 2020
1 parent 885e3e4 commit eb09da2
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 33 deletions.
2 changes: 1 addition & 1 deletion packages/gatsby/src/bootstrap/load-themes/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { createRequireFromPath } = require(`gatsby-core-utils`)
const path = require(`path`)
const mergeGatsbyConfig = require(`../../utils/merge-gatsby-config`)
const { mergeGatsbyConfig } = require(`../../utils/merge-gatsby-config`)
const Promise = require(`bluebird`)
const _ = require(`lodash`)
const debug = require(`debug`)(`gatsby:load-themes`)
Expand Down
1 change: 1 addition & 0 deletions packages/gatsby/src/redux/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface IGatsbyConfig {
developMiddleware?: any
proxy?: any
pathPrefix?: string
mapping?: Record<string, string>
}

export interface IGatsbyNode {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const mergeGatsbyConfig = require(`../merge-gatsby-config`)
import { mergeGatsbyConfig } from "../merge-gatsby-config"

describe(`Merge gatsby config`, () => {
it(`Merging empty config is an identity operation`, () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,16 @@
const _ = require(`lodash`)
/**
* Defines how a theme object is merged with the user's config
*/
module.exports = (a, b) => {
// a and b are gatsby configs, If they have keys, that means there are values to merge
const allGatsbyConfigKeysWithAValue = _.uniq(
Object.keys(a).concat(Object.keys(b))
)
import _ from "lodash"
import { IGatsbyConfig } from "../redux/types"

// reduce the array of mergable keys into a single gatsby config object
const mergedConfig = allGatsbyConfigKeysWithAValue.reduce(
(config, gatsbyConfigKey) => {
// choose a merge function for the config key if there's one defined,
// otherwise use the default value merge function
const mergeFn = howToMerge[gatsbyConfigKey] || howToMerge.byDefault
return {
...config,
[gatsbyConfigKey]: mergeFn(a[gatsbyConfigKey], b[gatsbyConfigKey]),
}
},
{}
)

// return the fully merged config
return mergedConfig
}
type ConfigKey = keyof IGatsbyConfig
type Metadata = IGatsbyConfig["siteMetadata"]
type Plugins = IGatsbyConfig["plugins"]
type PluginEntry =
| string
| {
resolve: string
options: Record<string, unknown>
}
type Mapping = IGatsbyConfig["mapping"]

/**
* Normalize plugin spec before comparing so
Expand All @@ -33,7 +19,7 @@ module.exports = (a, b) => {
* - { resolve: `gatsby-plugin-name`, options: {} }
* are all considered equal
*/
const normalizePluginEntry = entry =>
const normalizePluginEntry = (entry: PluginEntry): PluginEntry =>
_.isString(entry)
? { resolve: entry, options: {} }
: _.isObject(entry)
Expand All @@ -46,15 +32,43 @@ const howToMerge = {
* This makes sure that if a single value is defined, that one it used.
* We prefer the "right" value, because the user's config will be "on the right"
*/
byDefault: (a, b) => b || a,
siteMetadata: (objA, objB) => _.merge({}, objA, objB),
byDefault: (a: ConfigKey, b: ConfigKey): ConfigKey => b || a,
siteMetadata: (objA: Metadata, objB: Metadata): Metadata =>
_.merge({}, objA, objB),
// plugins are concatenated and uniq'd, so we don't get two of the same plugin value
plugins: (a = [], b = []) =>
plugins: (a: Plugins = [], b: Plugins = []): Plugins =>
_.uniqWith(a.concat(b), (a, b) =>
_.isEqual(
_.pick(normalizePluginEntry(a), [`resolve`, `options`]),
_.pick(normalizePluginEntry(b), [`resolve`, `options`])
)
),
mapping: (objA, objB) => _.merge({}, objA, objB),
mapping: (objA: Mapping, objB: Mapping): Mapping => _.merge({}, objA, objB),
}

/**
* Defines how a theme object is merged with the user's config
*/
export const mergeGatsbyConfig = (a, b): IGatsbyConfig => {
// a and b are gatsby configs, If they have keys, that means there are values to merge
const allGatsbyConfigKeysWithAValue = _.uniq(
Object.keys(a).concat(Object.keys(b))
)

// reduce the array of mergable keys into a single gatsby config object
const mergedConfig = allGatsbyConfigKeysWithAValue.reduce(
(config, gatsbyConfigKey) => {
// choose a merge function for the config key if there's one defined,
// otherwise use the default value merge function
const mergeFn = howToMerge[gatsbyConfigKey] || howToMerge.byDefault
return {
...config,
[gatsbyConfigKey]: mergeFn(a[gatsbyConfigKey], b[gatsbyConfigKey]),
}
},
{}
)

// return the fully merged config
return mergedConfig
}

0 comments on commit eb09da2

Please sign in to comment.