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): convert babel-loader-helpers to typescript #36237

Merged
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
1 change: 1 addition & 0 deletions packages/gatsby/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@
"@babel/cli": "^7.15.4",
"@babel/helper-plugin-utils": "^7.14.5",
"@babel/register": "^7.15.3",
"@types/babel-core": "^6.25.7",
"@types/eslint": "^8.2.1",
"@types/express": "^4.17.13",
"@types/express-http-proxy": "^1.6.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,20 +153,26 @@ Array [
exports[`Babelrc actions/reducer allows merging config items 2`] = `
Array [
Object {
"dirname": "hi",
"file": Object {
"request": "hello",
"resolved": "hi",
},
"options": Object {
"wat": 1,
},
"value": [Function],
},
Object {
"dirname": "hi2",
"file": Object {
"request": "hello2",
"resolved": "hi2",
},
"options": Object {
"wat": 2,
},
"value": [Function],
},
]
`;
Expand Down
46 changes: 35 additions & 11 deletions packages/gatsby/src/redux/__tests__/babelrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ describe(`Babelrc actions/reducer`, () => {

it(`sets default presets/plugins if there's no userland babelrc`, () => {
const fakeResolver = (moduleName): string => `/path/to/module/${moduleName}`
const babel = { createConfigItem: jest.fn() }
const babel = { createConfigItem: jest.fn() } as any

prepareOptions(babel, { stage: `test` }, fakeResolver)
prepareOptions(babel, { stage: `test` as any }, fakeResolver as any)

expect(babel.createConfigItem.mock.calls).toMatchSnapshot()
})
Expand All @@ -104,15 +104,15 @@ describe(`Babelrc actions/reducer`, () => {
{ name: `test` }
)
let state = babelrcReducer(undefined, action)
expect(state.stages.develop.options.sourceMaps).toBe(`inline`)
expect(state.stages.develop.options!.sourceMaps).toBe(`inline`)

const updateAction = actions.setBabelOptions(
{ options: { sourceMaps: true } },
{ name: `test` }
)
state = babelrcReducer(state, updateAction)

expect(state.stages.develop.options.sourceMaps).toBe(true)
expect(state.stages.develop.options!.sourceMaps).toBe(true)
})

it(`allows setting options on a particular stage`, () => {
Expand All @@ -121,25 +121,49 @@ describe(`Babelrc actions/reducer`, () => {
{ name: `test` }
)
const state = babelrcReducer(undefined, action)
expect(state.stages.develop.options.sourceMaps).toBe(`inline`)
expect(state.stages[`develop-html`].options.sourceMaps).toBe(undefined)
expect(state.stages.develop.options!.sourceMaps).toBe(`inline`)
expect(state.stages[`develop-html`].options!.sourceMaps).toBe(undefined)
})

it(`allows merging config items`, () => {
const babel = { createConfigItem: jest.fn() }
const babel = { createConfigItem: jest.fn() } as any
// This merges in new change.
mergeConfigItemOptions({
items: [{ options: { wat: 1 }, file: { resolved: `hi` } }],
itemToMerge: { options: { wat: 2 }, file: { resolved: `hi` } },
items: [
{
value: (): null => null,
dirname: `hi`,
options: { wat: 1 },
file: { resolved: `hi`, request: `hello` },
},
],
itemToMerge: {
value: (): null => null,
dirname: `hi`,
options: { wat: 2 },
file: { resolved: `hi`, request: `hello` },
},
type: `plugin`,
babel,
})
expect(babel.createConfigItem.mock.calls).toMatchSnapshot()

expect(
mergeConfigItemOptions({
items: [{ options: { wat: 1 }, file: { resolved: `hi` } }],
itemToMerge: { options: { wat: 2 }, file: { resolved: `hi2` } },
items: [
{
value: (): null => null,
dirname: `hi`,
options: { wat: 1 },
file: { resolved: `hi`, request: `hello` },
},
],
itemToMerge: {
value: (): null => null,
dirname: `hi2`,
options: { wat: 2 },
file: { resolved: `hi2`, request: `hello2` },
},
type: `plugin`,
babel,
})
Expand Down
20 changes: 7 additions & 13 deletions packages/gatsby/src/redux/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { TrailingSlash } from "gatsby-page-utils"
import { IProgram } from "../commands/types"
import { IProgram, Stage } from "../commands/types"
import { GraphQLFieldExtensionDefinition } from "../schema/extensions"
import {
DocumentNode,
Expand Down Expand Up @@ -190,25 +190,19 @@ export interface IGatsbyCompleteJobV2 {

export interface IPlugin {
name: string
options: Record<string, any>
options: Record<string, unknown>
}

export interface IBabelStage {
plugins: Array<IPlugin>
presets: Array<IPlugin>
options: {
options?: {
cacheDirectory: boolean
sourceType: string
sourceMaps?: string
}
}

type BabelStageKeys =
| "develop"
| "develop-html"
| "build-html"
| "build-javascript"

export interface IStateProgram extends IProgram {
extensions: Array<string>
browserslist: Array<string>
Expand Down Expand Up @@ -322,7 +316,7 @@ export interface IGatsbyState {
redirects: Array<IRedirect>
babelrc: {
stages: {
[key in BabelStageKeys]: IBabelStage
[key in Stage]: IBabelStage
}
}
schemaCustomization: {
Expand Down Expand Up @@ -468,7 +462,7 @@ export interface IApiFinishedAction {
interface ISetBabelPluginAction {
type: `SET_BABEL_PLUGIN`
payload: {
stage: BabelStageKeys
stage: Stage
name: IPlugin["name"]
options: IPlugin["options"]
}
Expand All @@ -477,7 +471,7 @@ interface ISetBabelPluginAction {
interface ISetBabelPresetAction {
type: `SET_BABEL_PRESET`
payload: {
stage: BabelStageKeys
stage: Stage
name: IPlugin["name"]
options: IPlugin["options"]
}
Expand All @@ -486,7 +480,7 @@ interface ISetBabelPresetAction {
interface ISetBabelOptionsAction {
type: `SET_BABEL_OPTIONS`
payload: {
stage: BabelStageKeys
stage: Stage
name: IPlugin["name"]
options: IPlugin["options"]
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
const path = require(`path`)
const _ = require(`lodash`)
import path from "path"
import _ from "lodash"
import Babel, {
ConfigItem,
PluginItem,
CreateConfigItemOptions,
} from "@babel/core"

import { IBabelStage } from "../redux/types"
import { Stage } from "../commands/types"

interface ILoadCachedConfigReturnType {
stages: {
test: IBabelStage
}
}

const loadCachedConfig = () => {
const loadCachedConfig = (): ILoadCachedConfigReturnType => {
let pluginBabelConfig = {
stages: {
test: { plugins: [], presets: [] },
Expand All @@ -16,7 +30,7 @@ const loadCachedConfig = () => {
return pluginBabelConfig
}

const getCustomOptions = stage => {
export const getCustomOptions = (stage: Stage): IBabelStage["options"] => {
const pluginBabelConfig = loadCachedConfig()
return pluginBabelConfig.stages[stage].options
}
Expand All @@ -30,11 +44,15 @@ const getCustomOptions = stage => {
*/
const configItemsMemoCache = new Map()

const prepareOptions = (
babel,
customOptions = {},
resolve = require.resolve
) => {
interface ICustomOptions extends Record<string, unknown> {
stage: Stage
}

export const prepareOptions = (
babel: typeof Babel,
customOptions: ICustomOptions,
resolve: RequireResolve = require.resolve
): Array<Array<PluginItem>> => {
const {
stage,
reactRuntime,
Expand Down Expand Up @@ -94,7 +112,7 @@ const prepareOptions = (
)
}

const requiredPresets = []
const requiredPresets: Array<PluginItem> = []

// Stage specific plugins to add
if (
Expand All @@ -117,7 +135,7 @@ const prepareOptions = (
}

// Fallback preset
const fallbackPresets = []
const fallbackPresets: Array<ConfigItem> = []

fallbackPresets.push(
babel.createConfigItem(
Expand All @@ -136,24 +154,27 @@ const prepareOptions = (
)

// Go through babel state and create config items for presets/plugins from.
const reduxPlugins = []
const reduxPresets = []
pluginBabelConfig.stages[stage].plugins.forEach(plugin => {
reduxPlugins.push(
babel.createConfigItem([resolve(plugin.name), plugin.options], {
name: plugin.name,
type: `plugin`,
})
)
})
pluginBabelConfig.stages[stage].presets.forEach(preset => {
reduxPresets.push(
babel.createConfigItem([resolve(preset.name), preset.options], {
name: preset.name,
type: `preset`,
})
)
})
const reduxPlugins: Array<PluginItem> = []
const reduxPresets: Array<PluginItem> = []

if (stage) {
pluginBabelConfig.stages[stage].plugins.forEach(plugin => {
reduxPlugins.push(
babel.createConfigItem([resolve(plugin.name), plugin.options], {
dirname: plugin.name,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding the dirname is ok here, but should we keep the name key as well?

https://github.com/babel/babel/blob/main/packages/babel-core/src/config/item.ts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to leave it but the types from babel changed and no longer include it.
The createConfigItem method that we use here comes from this type https://github.com/babel/babel/blob/main/packages/babel-core/src/config/item.ts#L28 and it now accepts only dirname and type.

Copy link
Contributor

@LekoArts LekoArts Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the current babel docs and previous versions the createConfigItem now has these parameters so changing them feels correct (and not adding invalid name key)

type: `plugin`,
})
)
})
pluginBabelConfig.stages[stage].presets.forEach(preset => {
reduxPresets.push(
babel.createConfigItem([resolve(preset.name), preset.options], {
dirname: preset.name,
type: `preset`,
})
)
})
}

const toReturn = [
reduxPresets,
Expand All @@ -168,16 +189,18 @@ const prepareOptions = (
return toReturn
}

const addRequiredPresetOptions = (
babel,
presets,
options = {},
resolve = require.resolve
) => {
export const addRequiredPresetOptions = (
babel: typeof Babel,
presets: Array<ConfigItem>,
options: { stage?: Stage } = {},
resolve: RequireResolve = require.resolve
): Array<PluginItem> => {
// Always pass `stage` option to babel-preset-gatsby
// (even if defined in custom babelrc)
const gatsbyPresetResolved = resolve(`babel-preset-gatsby`)
const index = presets.findIndex(p => p.file.resolved === gatsbyPresetResolved)
const index = presets.findIndex(
p => p.file!.resolved === gatsbyPresetResolved
)

if (index !== -1) {
presets[index] = babel.createConfigItem(
Expand All @@ -191,17 +214,27 @@ const addRequiredPresetOptions = (
return presets
}

const mergeConfigItemOptions = ({ items, itemToMerge, type, babel }) => {
export const mergeConfigItemOptions = ({
items,
itemToMerge,
type,
babel,
}: {
items: Array<ConfigItem>
itemToMerge: ConfigItem
type: CreateConfigItemOptions["type"]
babel: typeof Babel
}): Array<ConfigItem> => {
const index = _.findIndex(
items,
i => i.file.resolved === itemToMerge.file.resolved
i => i.file?.resolved === itemToMerge.file?.resolved
)

// If this exist, merge the options, otherwise, add it to the array
if (index !== -1) {
items[index] = babel.createConfigItem(
[
itemToMerge.file.resolved,
itemToMerge.file?.resolved,
_.merge({}, items[index].options, itemToMerge.options),
],
{
Expand All @@ -214,10 +247,3 @@ const mergeConfigItemOptions = ({ items, itemToMerge, type, babel }) => {

return items
}

exports.getCustomOptions = getCustomOptions

// Export helper functions for testing
exports.prepareOptions = prepareOptions
exports.mergeConfigItemOptions = mergeConfigItemOptions
exports.addRequiredPresetOptions = addRequiredPresetOptions
5 changes: 3 additions & 2 deletions packages/gatsby/src/utils/babel-loader.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
const babelLoader = require(`babel-loader`)

const {
import {
prepareOptions,
getCustomOptions,
mergeConfigItemOptions,
addRequiredPresetOptions,
} = require(`./babel-loader-helpers`)
} from "./babel-loader-helpers"

const { getBrowsersList } = require(`./browserslist`)

/**
Expand Down
Loading