Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2691f09

Browse files
authored
chore(gatsby): Update load-plugins to Typescript. (gatsbyjs#22504)
* chore(gatsby): Update load-plugins to Typescript. * define gastsby typings in terms of actual types This ensure's Gastby's typings are consistent with reality. * Update yarn.lock * Apply lint fixes for validate.ts. * Typecheck fix. * Fix typecheck issues. * Typecheck fix. * Update tests to TS and Fix them. * Cast validate.ts use of resolveModuleExports
1 parent 334b2a3 commit 2691f09

File tree

12 files changed

+278
-128
lines changed

12 files changed

+278
-128
lines changed

packages/gatsby/index.d.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
ComposeUnionTypeConfig,
1313
} from "graphql-compose"
1414
import { GraphQLOutputType } from "graphql"
15+
import { PluginRef } from "./src/bootstrap/load-plugins/types"
1516

1617
export {
1718
default as Link,
@@ -168,13 +169,7 @@ export interface GatsbyConfig {
168169
/** When you want to reuse common pieces of data across the site (for example, your site title), you can store that here. */
169170
siteMetadata?: Record<string, unknown>
170171
/** Plugins are Node.js packages that implement Gatsby APIs. The config file accepts an array of plugins. Some plugins may need only to be listed by name, while others may take options. */
171-
plugins?: Array<
172-
| string
173-
| {
174-
resolve: string
175-
options: Record<string, unknown>
176-
}
177-
>
172+
plugins?: Array<PluginRef>
178173
/** It’s common for sites to be hosted somewhere other than the root of their domain. Say we have a Gatsby site at `example.com/blog/`. In this case, we would need a prefix (`/blog`) added to all paths on the site. */
179174
pathPrefix?: string
180175
/** In some circumstances you may want to deploy assets (non-HTML resources such as JavaScript, CSS, etc.) to a separate domain. `assetPrefix` allows you to use Gatsby with assets hosted from a separate domain */

packages/gatsby/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@
158158
"@babel/runtime": "^7.9.6",
159159
"@types/hapi__joi": "^16.0.12",
160160
"@types/reach__router": "^1.3.5",
161+
"@types/semver": "^7.1.0",
161162
"@types/socket.io": "^2.1.4",
163+
"@types/string-similarity": "^3.0.0",
162164
"@types/tmp": "^0.2.0",
163165
"babel-preset-gatsby-package": "^0.4.2",
164166
"cross-env": "^5.2.1",

packages/gatsby/src/bootstrap/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { createSchemaCustomization } from "../utils/create-schema-customization"
1616
import { startPluginRunner } from "../redux/plugin-runner"
1717
const { store, emitter } = require(`../redux`)
1818
import { internalActions } from "../redux/actions"
19-
const loadPlugins = require(`./load-plugins`)
19+
const { loadPlugins } = require(`./load-plugins`)
2020
const loadThemes = require(`./load-themes`)
2121
const reporter = require(`gatsby-cli/lib/reporter`)
2222
import { getConfigFile } from "./get-config-file"

packages/gatsby/src/bootstrap/load-plugins/__tests__/load-plugins.js renamed to packages/gatsby/src/bootstrap/load-plugins/__tests__/load-plugins.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
const loadPlugins = require(`../index`)
2-
const { slash } = require(`gatsby-core-utils`)
1+
import { loadPlugins } from "../index"
2+
import { slash } from "gatsby-core-utils"
3+
import { IFlattenedPlugin } from "../types"
34

45
describe(`Load plugins`, () => {
56
/**
@@ -8,7 +9,9 @@ describe(`Load plugins`, () => {
89
* Version can be updated (we use external plugin in default config).
910
* Both will cause snapshots to differ.
1011
*/
11-
const replaceFieldsThatCanVary = plugins =>
12+
const replaceFieldsThatCanVary = (
13+
plugins: IFlattenedPlugin[]
14+
): IFlattenedPlugin[] =>
1215
plugins.map(plugin => {
1316
if (plugin.pluginOptions && plugin.pluginOptions.path) {
1417
plugin.pluginOptions = {
@@ -176,7 +179,7 @@ describe(`Load plugins`, () => {
176179
plugins = replaceFieldsThatCanVary(plugins)
177180

178181
const tsplugins = plugins.filter(
179-
plugin => plugin.name === `gatsby-plugin-typescript`
182+
(plugin: { name: string }) => plugin.name === `gatsby-plugin-typescript`
180183
)
181184

182185
// TODO: I think we should probably be de-duping, so this should be 1.

packages/gatsby/src/bootstrap/load-plugins/__tests__/validate.js renamed to packages/gatsby/src/bootstrap/load-plugins/__tests__/validate.ts

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,27 @@ jest.mock(`gatsby-cli/lib/reporter`, () => {
88
jest.mock(`../../resolve-module-exports`)
99
jest.mock(`../../../utils/get-latest-apis`)
1010

11-
const reporter = require(`gatsby-cli/lib/reporter`)
12-
const {
11+
import reporter from "gatsby-cli/lib/reporter"
12+
import {
1313
collatePluginAPIs,
1414
handleBadExports,
1515
handleMultipleReplaceRenderers,
1616
warnOnIncompatiblePeerDependency,
17-
} = require(`../validate`)
18-
const { getLatestAPIs } = require(`../../../utils/get-latest-apis`)
17+
ICurrentAPIs,
18+
ExportType,
19+
IEntry,
20+
} from "../validate"
21+
import { getLatestAPIs } from "../../../utils/get-latest-apis"
22+
import { resolveModuleExports } from "../../resolve-module-exports"
1923

2024
beforeEach(() => {
21-
Object.keys(reporter).forEach(key => reporter[key].mockReset())
22-
getLatestAPIs.mockClear()
23-
getLatestAPIs.mockResolvedValue({
25+
Object.keys(reporter).forEach(key => (reporter[key] as jest.Mock).mockReset())
26+
27+
const mocked = (getLatestAPIs as unknown) as jest.MockedFunction<
28+
typeof getLatestAPIs
29+
>
30+
mocked.mockClear()
31+
mocked.mockResolvedValue({
2432
browser: {},
2533
node: {},
2634
ssr: {},
@@ -41,8 +49,11 @@ describe(`collatePluginAPIs`, () => {
4149
}
4250

4351
beforeEach(() => {
44-
const { resolveModuleExports } = require(`../../resolve-module-exports`)
45-
resolveModuleExports(MOCK_RESULTS)
52+
// We call the manual /__mocks__/ implementation of resolveModuleExports,
53+
// which in addition to the normal parameters, also takes a mock results.
54+
// In the future, we might just use jest to mock the return value instead
55+
// of relying on manual mocks.
56+
resolveModuleExports(MOCK_RESULTS as any)
4657
})
4758

4859
it(`Identifies APIs used by a site's plugins`, async () => {
@@ -101,8 +112,16 @@ describe(`collatePluginAPIs`, () => {
101112
})
102113

103114
describe(`handleBadExports`, () => {
104-
const getValidExports = () => {
115+
const getValidExports = (): {
116+
currentAPIs: ICurrentAPIs
117+
badExports: { [api in ExportType]: IEntry[] }
118+
} => {
105119
return {
120+
currentAPIs: {
121+
node: [],
122+
browser: [],
123+
ssr: [],
124+
},
106125
badExports: {
107126
node: [],
108127
browser: [],
@@ -137,6 +156,7 @@ describe(`handleBadExports`, () => {
137156
ssr: [
138157
{
139158
exportName,
159+
pluginVersion: `1.0.0`,
140160
pluginName: `default-site-plugin`,
141161
},
142162
],
@@ -196,7 +216,8 @@ describe(`handleBadExports`, () => {
196216
it(`Adds fixes to context if newer API introduced in Gatsby`, async () => {
197217
const version = `2.2.0`
198218

199-
getLatestAPIs.mockResolvedValueOnce({
219+
const mocked = getLatestAPIs as jest.MockedFunction<typeof getLatestAPIs>
220+
mocked.mockResolvedValueOnce({
200221
browser: {},
201222
ssr: {},
202223
node: {
@@ -220,6 +241,7 @@ describe(`handleBadExports`, () => {
220241
{
221242
exportName: `validatePluginOptions`,
222243
pluginName: `gatsby-source-contentful`,
244+
pluginVersion: version,
223245
},
224246
],
225247
},
@@ -249,18 +271,14 @@ describe(`handleBadExports`, () => {
249271
browser: [``],
250272
ssr: [``],
251273
},
252-
latestAPIs: {
253-
browser: {},
254-
ssr: {},
255-
node: {},
256-
},
257274
badExports: {
258275
browser: [],
259276
ssr: [],
260277
node: [
261278
{
262279
exportName: typoOrOldAPI,
263280
pluginName: `default-site-plugin`,
281+
pluginVersion: `2.1.0`,
264282
},
265283
],
266284
},
@@ -269,7 +287,10 @@ describe(`handleBadExports`, () => {
269287
)
270288

271289
expect(reporter.error).toHaveBeenCalledTimes(typoAPIs.length)
272-
const calls = reporter.error.mock.calls
290+
const calls = ((reporter.error as unknown) as jest.MockedFunction<
291+
typeof reporter.error
292+
>).mock.calls
293+
273294
calls.forEach(([call]) => {
274295
expect(call).toEqual(
275296
expect.objectContaining({
@@ -346,7 +367,9 @@ describe(`handleMultipleReplaceRenderers`, () => {
346367

347368
describe(`warnOnIncompatiblePeerDependency`, () => {
348369
beforeEach(() => {
349-
reporter.warn.mockClear()
370+
;((reporter.warn as unknown) as jest.MockedFunction<
371+
typeof reporter.warn
372+
>).mockClear()
350373
})
351374

352375
it(`Does not warn when no peer dependency`, () => {

packages/gatsby/src/bootstrap/load-plugins/index.js renamed to packages/gatsby/src/bootstrap/load-plugins/index.ts

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,39 @@
1-
const _ = require(`lodash`)
1+
import _ from "lodash"
22

3-
const { store } = require(`../../redux`)
3+
import { store } from "../../redux"
44
import * as nodeAPIs from "../../utils/api-node-docs"
55
import * as browserAPIs from "../../utils/api-browser-docs"
6-
const ssrAPIs = require(`../../../cache-dir/api-ssr-docs`)
7-
const { loadPlugins } = require(`./load`)
8-
const {
6+
import ssrAPIs from "../../../cache-dir/api-ssr-docs"
7+
import { loadPlugins as loadPluginsInternal } from "./load"
8+
import {
99
collatePluginAPIs,
1010
handleBadExports,
1111
handleMultipleReplaceRenderers,
12-
} = require(`./validate`)
12+
ExportType,
13+
ICurrentAPIs,
14+
} from "./validate"
15+
import { IPluginInfo, IFlattenedPlugin, ISiteConfig } from "./types"
1316

14-
const getAPI = api =>
15-
_.keys(api).reduce((merged, key) => {
17+
const getAPI = (
18+
api: { [exportType in ExportType]: { [api: string]: boolean } }
19+
): ICurrentAPIs =>
20+
_.keys(api).reduce<Partial<ICurrentAPIs>>((merged, key) => {
1621
merged[key] = _.keys(api[key])
1722
return merged
18-
}, {})
23+
}, {}) as ICurrentAPIs
1924

2025
// Create a "flattened" array of plugins with all subplugins
2126
// brought to the top-level. This simplifies running gatsby-* files
2227
// for subplugins.
23-
const flattenPlugins = plugins => {
24-
const flattened = []
25-
const extractPlugins = plugin => {
26-
plugin.pluginOptions.plugins.forEach(subPlugin => {
27-
flattened.push(subPlugin)
28-
extractPlugins(subPlugin)
29-
})
28+
const flattenPlugins = (plugins: IPluginInfo[]): IPluginInfo[] => {
29+
const flattened: IPluginInfo[] = []
30+
const extractPlugins = (plugin: IPluginInfo): void => {
31+
if (plugin.pluginOptions && plugin.pluginOptions.plugins) {
32+
plugin.pluginOptions.plugins.forEach(subPlugin => {
33+
flattened.push(subPlugin)
34+
extractPlugins(subPlugin)
35+
})
36+
}
3037
}
3138

3239
plugins.forEach(plugin => {
@@ -37,22 +44,28 @@ const flattenPlugins = plugins => {
3744
return flattened
3845
}
3946

40-
module.exports = async (config = {}, rootDir = null) => {
47+
export async function loadPlugins(
48+
config: ISiteConfig = {},
49+
rootDir: string | null = null
50+
): Promise<IFlattenedPlugin[]> {
4151
const currentAPIs = getAPI({
4252
browser: browserAPIs,
4353
node: nodeAPIs,
4454
ssr: ssrAPIs,
4555
})
56+
4657
// Collate internal plugins, site config plugins, site default plugins
47-
const plugins = loadPlugins(config, rootDir)
58+
const pluginInfos = loadPluginsInternal(config, rootDir)
4859

4960
// Create a flattened array of the plugins
50-
let flattenedPlugins = flattenPlugins(plugins)
61+
const pluginArray = flattenPlugins(pluginInfos)
5162

5263
// Work out which plugins use which APIs, including those which are not
5364
// valid Gatsby APIs, aka 'badExports'
54-
const x = collatePluginAPIs({ currentAPIs, flattenedPlugins })
55-
flattenedPlugins = x.flattenedPlugins
65+
const x = collatePluginAPIs({ currentAPIs, flattenedPlugins: pluginArray })
66+
67+
// From this point on, these are fully-resolved plugins.
68+
let flattenedPlugins = x.flattenedPlugins
5669
const badExports = x.badExports
5770

5871
// Show errors for any non-Gatsby APIs exported from plugins

0 commit comments

Comments
 (0)