From a361d9be8ef70b6ffa44202847d4af00b73f5b6d Mon Sep 17 00:00:00 2001 From: Blaine Kasten Date: Fri, 22 Nov 2019 13:07:44 -0600 Subject: [PATCH] chore(gatsby): Begin the great TypeScript migration! --- .babelrc.js | 1 + .circleci/config.yml | 9 + package.json | 6 +- packages/gatsby/package.json | 2 +- .../src/commands/{develop.js => develop.ts} | 107 ++- packages/gatsby/src/query/file-parser.js | 31 +- packages/gatsby/src/query/query-compiler.js | 11 +- packages/gatsby/src/redux/actions/internal.js | 46 +- packages/gatsby/src/redux/actions/public.js | 144 ++-- .../gatsby/src/redux/actions/restricted.js | 41 +- packages/gatsby/src/redux/actions/types.js | 9 +- .../gatsby/src/schema/extensions/index.js | 23 +- packages/gatsby/src/schema/node-model.js | 78 ++- .../gatsby/src/schema/types/type-builders.js | 66 +- packages/gatsby/src/utils/webpack-utils.js | 635 ------------------ packages/gatsby/tsconfig.json | 3 + scripts/check-ts.js | 44 ++ tsconfig.json | 14 +- yarn.lock | 64 +- 19 files changed, 437 insertions(+), 897 deletions(-) rename packages/gatsby/src/commands/{develop.js => develop.ts} (89%) delete mode 100644 packages/gatsby/src/utils/webpack-utils.js create mode 100644 packages/gatsby/tsconfig.json create mode 100644 scripts/check-ts.js diff --git a/.babelrc.js b/.babelrc.js index 4eb42997a778d..5f4159b95e3f8 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -9,5 +9,6 @@ if (process.env.NODE_ENV !== `test`) { module.exports = { sourceMaps: true, presets: ["babel-preset-gatsby-package"], + plugins: [["@babel/plugin-transform-typescript", { isTSX: true }]], ignore, } diff --git a/.circleci/config.yml b/.circleci/config.yml index e12ccff21c1bc..5066c600347d3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -188,6 +188,12 @@ jobs: - run: yarn lint:other - run: yarn check-repo-fields + typecheck: + executor: node + steps: + - <<: *attach_to_bootstrap + - run: yarn test:check + unit_tests_node8: executor: name: node @@ -453,6 +459,9 @@ workflows: jobs: - windows_unit_tests - bootstrap + - typecheck: + requires: + - bootstrap - lint: requires: - bootstrap diff --git a/package.json b/package.json index 76a31ecc79185..abde3ebfa3c60 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,9 @@ "@lerna/prompt": "3.18.5", "@typescript-eslint/eslint-plugin": "^2.9.0", "@typescript-eslint/parser": "^2.9.0", + "@types/jest": "^24.0.23", + "@types/express": "^4.17.2", + "@types/node": "^12.12.11", "babel-eslint": "^10.0.3", "babel-jest": "^24.9.0", "chalk": "^2.4.2", @@ -70,7 +73,7 @@ }, "husky": { "hooks": { - "pre-commit": "lint-staged || node scripts/on-lint-error.js" + "pre-commit": "lint-staged || node scripts/on-lint-error.js && yarn test:check" } }, "scripts": { @@ -99,6 +102,7 @@ "publish-canary": "lerna publish --canary --yes", "publish-next": "lerna publish --npm-tag=next --bump=prerelease", "test": "npm-run-all -s lint jest", + "test:check": "node ./scripts/check-ts", "test:coverage": "jest --coverage", "test:update": "jest --updateSnapshot", "test:watch": "jest --watch", diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index 7d4a05cf5fef0..154b5ee3ac7f2 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -195,7 +195,7 @@ "build:internal-plugins": "copyfiles -u 1 src/internal-plugins/**/package.json dist", "build:rawfiles": "copyfiles -u 1 src/internal-plugins/**/raw_* dist", "build:cjs": "babel cache-dir --out-dir cache-dir/commonjs --ignore **/__tests__", - "build:src": "babel src --out-dir dist --source-maps --verbose --ignore **/gatsby-cli.js,src/internal-plugins/dev-404-page/raw_dev-404-page.js,**/__tests__", + "build:src": "babel src --out-dir dist --source-maps --verbose --ignore **/gatsby-cli.js,src/internal-plugins/dev-404-page/raw_dev-404-page.js,**/__tests__ --extensions \".ts,.js\"", "clean-test-bundles": "find test/ -type f -name bundle.js* -exec rm -rf {} +", "prebuild": "rimraf dist && rimraf cache-dir/commonjs", "postinstall": "node scripts/postinstall.js", diff --git a/packages/gatsby/src/commands/develop.js b/packages/gatsby/src/commands/develop.ts similarity index 89% rename from packages/gatsby/src/commands/develop.js rename to packages/gatsby/src/commands/develop.ts index aae6d240ed110..1911bd3f7b674 100644 --- a/packages/gatsby/src/commands/develop.js +++ b/packages/gatsby/src/commands/develop.ts @@ -1,11 +1,10 @@ -/* @flow */ - const url = require(`url`) const glob = require(`glob`) const fs = require(`fs`) const openurl = require(`better-opn`) const chokidar = require(`chokidar`) -const express = require(`express`) + +import express from "express" const graphqlHTTP = require(`express-graphql`) const graphqlPlayground = require(`graphql-playground-middleware-express`) .default @@ -47,6 +46,27 @@ const { structureWebpackErrors, } = require(`../utils/webpack-error-utils`) +type Cert = { + keyPath: string + certPath: string + key: string + cert: string +} + +type Program = { + useYarn: boolean + open: boolean + openTracingConfigFile: string + port: number + host: string + [`cert-file`]?: string + [`key-file`]?: string + directory: string + https?: boolean + sitePackageJson: { name: string } // TODO make this into package json spec + ssl?: Cert +} + // const isInteractive = process.stdout.isTTY // Watch the static directory and copy files to public as they're added or @@ -61,7 +81,7 @@ onExit(() => { }) const waitJobsFinished = () => - new Promise((resolve, reject) => { + new Promise(resolve => { const onEndJob = () => { if (store.getState().jobs.active.length === 0) { resolve() @@ -72,7 +92,7 @@ const waitJobsFinished = () => onEndJob() }) -async function startServer(program) { +async function startServer(program: Program) { const indexHTMLActivity = report.phantomActivity(`building index.html`, {}) indexHTMLActivity.start() const directory = program.directory @@ -172,7 +192,7 @@ async function startServer(program) { context: {}, customContext: schemaCustomization.context, }), - customFormatErrorFn(err) { + customFormatErrorFn(err: Error) { return { ...formatError(err), stack: err.stack ? err.stack.split(`\n`) : [], @@ -260,7 +280,7 @@ async function startServer(program) { .on(`response`, response => res.writeHead(response.statusCode, response.headers) ) - .on(`error`, (err, _, response) => { + .on(`error`, (err: Error, _: any, response) => { if (response) { res.writeHead(response.statusCode, response.headers) } else { @@ -281,12 +301,12 @@ async function startServer(program) { // This fixes "Unexpected token < in JSON at position 0" runtime // errors after restarting development server and // cause automatic hard refresh in the browser. - app.use(/.*\.hot-update\.json$/i, (req, res) => { + app.use(/.*\.hot-update\.json$/i, (_, res) => { res.status(404).end() }) // Render an HTML page and serve it. - app.use((req, res, next) => { + app.use((_, res) => { res.sendFile(directoryPath(`public/index.html`), err => { if (err) { res.status(500).end() @@ -306,19 +326,23 @@ async function startServer(program) { websocketManager.init({ server, directory: program.directory }) const socket = websocketManager.getSocket() - const listener = server.listen(program.port, program.host, err => { - if (err) { - if (err.code === `EADDRINUSE`) { - // eslint-disable-next-line max-len - report.panic( - `Unable to start Gatsby on port ${program.port} as there's already a process listening on that port.` - ) - return - } + const listener = server.listen( + program.port, + program.host, + (err?: Error & { code: string }) => { + if (err) { + if (err.code === `EADDRINUSE`) { + // eslint-disable-next-line max-len + report.panic( + `Unable to start Gatsby on port ${program.port} as there's already a process listening on that port.` + ) + return + } - report.panic(`There was a problem starting the development server`, err) + report.panic(`There was a problem starting the development server`, err) + } } - }) + ) // Register watcher that rebuilds index.html every time html.js changes. const watchGlobs = [`src/html.js`, `plugins/**/gatsby-ssr.js`].map(path => @@ -333,7 +357,7 @@ async function startServer(program) { return { compiler, listener, webpackActivity } } -module.exports = async (program: any) => { +module.exports = async (program: Program) => { initTracer(program.openTracingConfigFile) report.pendingActivity({ id: `webpack-develop` }) telemetry.trackCli(`DEVELOP_START`) @@ -400,15 +424,15 @@ module.exports = async (program: any) => { let { compiler, webpackActivity } = await startServer(program) - function prepareUrls(protocol, host, port) { - const formatUrl = hostname => + function prepareUrls(protocol: "http" | "https", host: string, port: number) { + const formatUrl = (hostname: string) => url.format({ protocol, hostname, port, pathname: `/`, }) - const prettyPrintUrl = hostname => + const prettyPrintUrl = (hostname: string) => url.format({ protocol, hostname, @@ -458,7 +482,10 @@ module.exports = async (program: any) => { } } - function printInstructions(appName, urls, useYarn) { + function printInstructions( + appName: string, + urls: any // TODO + ) { console.log() console.log(`You can now view ${chalk.bold(appName)} in the browser.`) console.log() @@ -508,7 +535,10 @@ module.exports = async (program: any) => { } function printDeprecationWarnings() { - const deprecatedApis = [`boundActionCreators`, `pathContext`] + const deprecatedApis: (`boundActionCreators` | `pathContext`)[] = [ + `boundActionCreators`, + `pathContext`, + ] const fixMap = { boundActionCreators: { newName: `actions`, @@ -519,15 +549,17 @@ module.exports = async (program: any) => { docsLink: `https://gatsby.dev/pathContext`, }, } - const deprecatedLocations = {} - deprecatedApis.forEach(api => (deprecatedLocations[api] = [])) + const deprecatedLocations = { + boundActionCreators: [] as string[], + pathContext: [] as string[], + } glob .sync(`{,!(node_modules|public)/**/}*.js`, { nodir: true }) - .forEach(file => { + .forEach((file: string) => { const fileText = fs.readFileSync(file) - const matchingApis = deprecatedApis.filter(api => - fileText.includes(api) + const matchingApis = deprecatedApis.filter( + api => fileText.indexOf(api) !== -1 ) matchingApis.forEach(api => deprecatedLocations[api].push(file)) }) @@ -554,7 +586,10 @@ module.exports = async (program: any) => { // console.log(`set invalid`, args, this) // }) - compiler.hooks.watchRun.tapAsync(`log compiling`, function(args, done) { + compiler.hooks.watchRun.tapAsync(`log compiling`, function( + _: any, + done: () => void + ) { if (webpackActivity) { webpackActivity.end() } @@ -570,8 +605,8 @@ module.exports = async (program: any) => { // "done" event fires when Webpack has finished recompiling the bundle. // Whether or not you have warnings or errors, you will get this event. compiler.hooks.done.tapAsync(`print gatsby instructions`, function( - stats, - done + stats: any, // TODO webpack stats + done: () => void ) { // We have switched off the default Webpack output in WebpackDevServer // options so we are going to "massage" the warnings and errors and present @@ -585,10 +620,10 @@ module.exports = async (program: any) => { const isSuccessful = !messages.errors.length if (isSuccessful && isFirstCompile) { - printInstructions(program.sitePackageJson.name, urls, program.useYarn) + printInstructions(program.sitePackageJson.name, urls, true) printDeprecationWarnings() if (program.open) { - Promise.resolve(openurl(urls.localUrlForBrowser)).catch(err => + Promise.resolve(openurl(urls.localUrlForBrowser)).catch(() => console.log( `${chalk.yellow( `warn` diff --git a/packages/gatsby/src/query/file-parser.js b/packages/gatsby/src/query/file-parser.js index aed9187b94671..4d28eee7ef3f0 100644 --- a/packages/gatsby/src/query/file-parser.js +++ b/packages/gatsby/src/query/file-parser.js @@ -1,4 +1,3 @@ -// @flow const fs = require(`fs-extra`) const crypto = require(`crypto`) const _ = require(`lodash`) @@ -15,7 +14,7 @@ const { const report = require(`gatsby-cli/lib/reporter`) -import type { DocumentNode } from "graphql" +// import type { DocumentNode } from "graphql" import { babelParseToAst } from "../utils/babel-parse-to-ast" import { codeFrameColumns } from "@babel/code-frame" @@ -116,21 +115,21 @@ const warnForGlobalTag = file => file ) -type GraphQLDocumentInFile = { - filePath: string, - doc: DocumentNode, - templateLoc: string, - text: string, - hash: string, - isHook: boolean, - isStaticQuery: boolean, -} +// type GraphQLDocumentInFile = { +// filePath: string, +// doc: DocumentNode, +// templateLoc: string, +// text: string, +// hash: string, +// isHook: boolean, +// isStaticQuery: boolean, +// } async function findGraphQLTags( file, text, { parentSpan, addError } = {} -): Promise> { +) /*: Promise>*/ { return new Promise((resolve, reject) => { parseToAst(file, text, { parentSpan, addError }) .then(ast => { @@ -365,7 +364,7 @@ export default class FileParser { this.parentSpan = parentSpan } - async parseFile(file: string, addError): Promise { + async parseFile(file /*: string*/, addError) /*: Promise*/ { let text try { text = await fs.readFile(file, `utf8`) @@ -488,10 +487,10 @@ export default class FileParser { } async parseFiles( - files: Array, + files /*: Array*/, addError - ): Promise> { - const documents = [] + ) /*: Promise> */ { + const documents = new Map() return Promise.all( files.map(file => diff --git a/packages/gatsby/src/query/query-compiler.js b/packages/gatsby/src/query/query-compiler.js index 78a787787cb14..3ebb390061046 100644 --- a/packages/gatsby/src/query/query-compiler.js +++ b/packages/gatsby/src/query/query-compiler.js @@ -1,12 +1,9 @@ -// @flow - /** Query compiler extracts queries and fragments from all files, validates them * and then collocates them with fragments they require. This way fragments * have global scope and can be used in any other query or fragment. */ const _ = require(`lodash`) - const path = require(`path`) const normalize = require(`normalize-path`) const glob = require(`glob`) @@ -45,9 +42,11 @@ const websocketManager = require(`../utils/websocket-manager`) const overlayErrorID = `graphql-compiler` -export default async function compile({ parentSpan } = {}): Promise< +export default async function compile({ + parentSpan, +} = {}) /* : Promise< Map -> { +> */ { // TODO: swap plugins to themes const { program, schema, themes, flattenedPlugins } = store.getState() @@ -286,7 +285,7 @@ const processDefinitions = ({ addError, parentSpan, }) => { - const processedQueries: Queries = new Map() + const processedQueries /*: Queries*/ = new Map() const fragmentsUsedByFragment = new Map() diff --git a/packages/gatsby/src/redux/actions/internal.js b/packages/gatsby/src/redux/actions/internal.js index e685b992993c4..3d264db60ea05 100644 --- a/packages/gatsby/src/redux/actions/internal.js +++ b/packages/gatsby/src/redux/actions/internal.js @@ -1,5 +1,4 @@ -// @flow -import type { Plugin } from "./types" +// import type { Plugin } from "./types" const actions = {} @@ -17,8 +16,8 @@ actions.createPageDependency = ( path, nodeId, connection, - }: { path: string, nodeId: string, connection: string }, - plugin: string = `` + } /* { path: string, nodeId: string, connection: string }*/, + plugin /*: string = ``*/ ) => { return { type: `CREATE_COMPONENT_DEPENDENCY`, @@ -37,7 +36,7 @@ actions.createPageDependency = ( * @param {Array} paths the paths to delete. * @private */ -actions.deleteComponentsDependencies = (paths: string[]) => { +actions.deleteComponentsDependencies = (paths /*: string[]*/) => { return { type: `DELETE_COMPONENTS_DEPENDENCIES`, payload: { @@ -51,13 +50,12 @@ actions.deleteComponentsDependencies = (paths: string[]) => { * this to store the query with its component. * @private */ -actions.replaceComponentQuery = ({ - query, - componentPath, -}: { +actions.replaceComponentQuery = ( + { query, componentPath } /*: { query: string, componentPath: string, -}) => { +}*/ +) => { return { type: `REPLACE_COMPONENT_QUERY`, payload: { @@ -72,7 +70,7 @@ actions.replaceComponentQuery = ({ * components, it calls this to store the query with its component. * @private */ -actions.replaceStaticQuery = (args: any, plugin?: ?Plugin = null) => { +actions.replaceStaticQuery = (args /*: any*/, plugin /*?: ?Plugin*/ = null) => { return { type: `REPLACE_STATIC_QUERY`, plugin, @@ -93,8 +91,8 @@ actions.replaceStaticQuery = (args: any, plugin?: ?Plugin = null) => { */ actions.queryExtracted = ( { componentPath, query }, - plugin: Plugin, - traceId?: string + plugin /*: Plugin*/, + traceId /*?: string*/ ) => { return { type: `QUERY_EXTRACTED`, @@ -116,8 +114,8 @@ actions.queryExtracted = ( */ actions.queryExtractionGraphQLError = ( { componentPath, error }, - plugin: Plugin, - traceId?: string + plugin /*: Plugin*/, + traceId /*?: string*/ ) => { return { type: `QUERY_EXTRACTION_GRAPHQL_ERROR`, @@ -139,8 +137,8 @@ actions.queryExtractionGraphQLError = ( */ actions.queryExtractedBabelSuccess = ( { componentPath }, - plugin: Plugin, - traceId?: string + plugin /*: Plugin*/, + traceId /*?: string*/ ) => { return { type: `QUERY_EXTRACTION_BABEL_SUCCESS`, @@ -162,8 +160,8 @@ actions.queryExtractedBabelSuccess = ( */ actions.queryExtractionBabelError = ( { componentPath, error }, - plugin: Plugin, - traceId?: string + plugin /*: Plugin*/, + traceId /*?: string*/ ) => { return { type: `QUERY_EXTRACTION_BABEL_ERROR`, @@ -179,7 +177,11 @@ actions.queryExtractionBabelError = ( * @param {string} Program status * @private */ -actions.setProgramStatus = (status, plugin: Plugin, traceId?: string) => { +actions.setProgramStatus = ( + status, + plugin /*: Plugin*/, + traceId /*?: string*/ +) => { return { type: `SET_PROGRAM_STATUS`, plugin, @@ -196,8 +198,8 @@ actions.setProgramStatus = (status, plugin: Plugin, traceId?: string) => { */ actions.pageQueryRun = ( { path, componentPath, isPage }, - plugin: Plugin, - traceId?: string + plugin /*: Plugin*/, + traceId /*?: string*/ ) => { return { type: `PAGE_QUERY_RUN`, diff --git a/packages/gatsby/src/redux/actions/public.js b/packages/gatsby/src/redux/actions/public.js index 7e04e0b9d7770..9706cd0bf872b 100644 --- a/packages/gatsby/src/redux/actions/public.js +++ b/packages/gatsby/src/redux/actions/public.js @@ -1,4 +1,3 @@ -// @flow const Joi = require(`@hapi/joi`) const chalk = require(`chalk`) const _ = require(`lodash`) @@ -61,32 +60,32 @@ const findChildren = initialChildren => { return children } -import type { Plugin } from "./types" - -type Job = { - id: string, -} -type PageInput = { - path: string, - component: string, - context?: Object, -} - -type Page = { - path: string, - matchPath: ?string, - component: string, - context: Object, - internalComponentName: string, - componentChunkName: string, - updatedAt: number, -} - -type ActionOptions = { - traceId: ?string, - parentSpan: ?Object, - followsSpan: ?Object, -} +// import type { Plugin } from "./types" + +// type Job = { +// id: string, +// } +// type PageInput = { +// path: string, +// component: string, +// context?: Object, +// } + +// type Page = { +// path: string, +// matchPath: ?string, +// component: string, +// context: Object, +// internalComponentName: string, +// componentChunkName: string, +// updatedAt: number, +// } + +// type ActionOptions = { +// traceId: ?string, +// parentSpan: ?Object, +// followsSpan: ?Object, +// } /** * Delete a page @@ -96,7 +95,7 @@ type ActionOptions = { * @example * deletePage(page) */ -actions.deletePage = (page: PageInput) => { +actions.deletePage = (page /*: PageInput*/) => { return { type: `DELETE_PAGE`, payload: page, @@ -133,9 +132,9 @@ const fileOkCache = {} * }) */ actions.createPage = ( - page: PageInput, - plugin?: Plugin, - actionOptions?: ActionOptions + page /*: PageInput*/, + plugin /*?: Plugin*/, + actionOptions /*?: ActionOptions*/ ) => { let name = `The plugin "${plugin.name}"` if (plugin.name === `default-site-plugin`) { @@ -350,7 +349,7 @@ ${reservedFields.map(f => ` * "${f}"`).join(`\n`)} internalComponentName = `Component${pascalCase(page.path)}` } - let internalPage: Page = { + let internalPage /*: Page*/ = { internalComponentName, path: page.path, matchPath: page.matchPath, @@ -426,7 +425,7 @@ ${reservedFields.map(f => ` * "${f}"`).join(`\n`)} fileOkCache[internalPage.component] = true } - const oldPage: Page = store.getState().pages.get(internalPage.path) + const oldPage /*: Page*/ = store.getState().pages.get(internalPage.path) const contextModified = !!oldPage && !_.isEqual(oldPage.context, internalPage.context) @@ -460,7 +459,11 @@ ${reservedFields.map(f => ` * "${f}"`).join(`\n`)} * @example * deleteNode({node: node}) */ -actions.deleteNode = (options: any, plugin: Plugin, args: any) => { +actions.deleteNode = ( + options /*: any*/, + plugin /*: Plugin*/, + args /*: any*/ +) => { let id // Check if using old method signature. Warn about incorrect usage but get @@ -536,7 +539,7 @@ actions.deleteNode = (options: any, plugin: Plugin, args: any) => { * @example * deleteNodes([`node1`, `node2`]) */ -actions.deleteNodes = (nodes: any[], plugin: Plugin) => { +actions.deleteNodes = (nodes /*: any[]*/, plugin /*: Plugin*/) => { let msg = `The "deleteNodes" action is now deprecated and will be removed in ` + `Gatsby v3. Please use "deleteNode" instead.` @@ -645,9 +648,9 @@ const typeOwners = {} * }) */ const createNode = ( - node: any, - plugin?: Plugin, - actionOptions?: ActionOptions = {} + node /*: any*/, + plugin /*?: Plugin*/, + actionOptions /*?: ActionOptions = {}*/ ) => { if (!_.isObject(node)) { return console.log( @@ -869,7 +872,7 @@ actions.createNode = (...args) => dispatch => { * @example * touchNode({ nodeId: `a-node-id` }) */ -actions.touchNode = (options: any, plugin?: Plugin) => { +actions.touchNode = (options /*: any*/, plugin /*?: Plugin*/) => { let nodeId = _.get(options, `nodeId`) // Check if using old method signature. Warn about incorrect usage @@ -897,13 +900,13 @@ actions.touchNode = (options: any, plugin?: Plugin) => { } } -type CreateNodeInput = { - node: Object, - fieldName?: string, - fieldValue?: string, - name?: string, - value: any, -} +// type CreateNodeInput = { +// node: Object, +// fieldName?: string, +// fieldValue?: string, +// name?: string, +// value: any, +// } /** * Extend another node. The new node field is placed under the `fields` * key on the extended node object. @@ -927,9 +930,9 @@ type CreateNodeInput = { * // The field value is now accessible at node.fields.happiness */ actions.createNodeField = ( - { node, name, value, fieldName, fieldValue }: CreateNodeInput, - plugin: Plugin, - actionOptions?: ActionOptions + { node, name, value, fieldName, fieldValue } /*: CreateNodeInput*/, + plugin /*: Plugin*/, + actionOptions /*?: ActionOptions*/ ) => { if (fieldName) { console.warn( @@ -1002,8 +1005,8 @@ actions.createNodeField = ( * createParentChildLink({ parent: parentNode, child: childNode }) */ actions.createParentChildLink = ( - { parent, child }: { parent: any, child: any }, - plugin?: Plugin + { parent, child } /*: { parent: any, child: any }*/, + plugin /*?: Plugin*/ ) => { // Update parent parent.children.push(child.id) @@ -1025,7 +1028,10 @@ actions.createParentChildLink = ( * * @param {Object} config partial webpack config, to be merged into the current one */ -actions.setWebpackConfig = (config: Object, plugin?: ?Plugin = null) => { +actions.setWebpackConfig = ( + config /*: Object*/, + plugin /*?: ?Plugin*/ = null +) => { return { type: `SET_WEBPACK_CONFIG`, plugin, @@ -1042,7 +1048,10 @@ actions.setWebpackConfig = (config: Object, plugin?: ?Plugin = null) => { * * @param {Object} config complete webpack config */ -actions.replaceWebpackConfig = (config: Object, plugin?: ?Plugin = null) => { +actions.replaceWebpackConfig = ( + config /*: Object*/, + plugin /*?: ?Plugin*/ = null +) => { return { type: `REPLACE_WEBPACK_CONFIG`, plugin, @@ -1061,7 +1070,10 @@ actions.replaceWebpackConfig = (config: Object, plugin?: ?Plugin = null) => { * } * }) */ -actions.setBabelOptions = (options: Object, plugin?: ?Plugin = null) => { +actions.setBabelOptions = ( + options /*: Object*/, + plugin /*?: ?Plugin*/ = null +) => { // Validate let name = `The plugin "${plugin.name}"` if (plugin.name === `default-site-plugin`) { @@ -1103,7 +1115,10 @@ actions.setBabelOptions = (options: Object, plugin?: ?Plugin = null) => { * }, * }) */ -actions.setBabelPlugin = (config: Object, plugin?: ?Plugin = null) => { +actions.setBabelPlugin = ( + config /*: Object*/, + plugin /*?: ?Plugin*/ = null +) => { // Validate let name = `The plugin "${plugin.name}"` if (plugin.name === `default-site-plugin`) { @@ -1139,7 +1154,10 @@ actions.setBabelPlugin = (config: Object, plugin?: ?Plugin = null) => { * }, * }) */ -actions.setBabelPreset = (config: Object, plugin?: ?Plugin = null) => { +actions.setBabelPreset = ( + config /*: Object*/, + plugin /*?: ?Plugin*/ = null +) => { // Validate let name = `The plugin "${plugin.name}"` if (plugin.name === `default-site-plugin`) { @@ -1174,7 +1192,7 @@ actions.setBabelPreset = (config: Object, plugin?: ?Plugin = null) => { * @example * createJob({ id: `write file id: 123`, fileName: `something.jpeg` }) */ -actions.createJob = (job: Job, plugin?: ?Plugin = null) => { +actions.createJob = (job /*: Job*/, plugin /*?: ?Plugin*/ = null) => { return { type: `CREATE_JOB`, plugin, @@ -1191,7 +1209,7 @@ actions.createJob = (job: Job, plugin?: ?Plugin = null) => { * @example * setJob({ id: `write file id: 123`, progress: 50 }) */ -actions.setJob = (job: Job, plugin?: ?Plugin = null) => { +actions.setJob = (job /*: Job*/, plugin /*?: ?Plugin*/ = null) => { return { type: `SET_JOB`, plugin, @@ -1208,7 +1226,7 @@ actions.setJob = (job: Job, plugin?: ?Plugin = null) => { * @example * endJob({ id: `write file id: 123` }) */ -actions.endJob = (job: Job, plugin?: ?Plugin = null) => { +actions.endJob = (job /*: Job*/, plugin /*?: ?Plugin*/ = null) => { return { type: `END_JOB`, plugin, @@ -1225,8 +1243,8 @@ actions.endJob = (job: Job, plugin?: ?Plugin = null) => { * setPluginStatus({ lastFetched: Date.now() }) */ actions.setPluginStatus = ( - status: { [key: string]: mixed }, - plugin: Plugin + status /*: { [key: string]: mixed }*/, + plugin /*: Plugin*/ ) => { return { type: `SET_PLUGIN_STATUS`, @@ -1306,8 +1324,8 @@ actions.createPageDependency = ( path, nodeId, connection, - }: { path: string, nodeId: string, connection: string }, - plugin: string = `` + } /*: { path: string, nodeId: string, connection: string }*/, + plugin /*: string = ``*/ ) => { console.warn( `Calling "createPageDependency" directly from actions in deprecated. Use "createPageDependency" from "gatsby/dist/redux/actions/add-page-dependency".` diff --git a/packages/gatsby/src/redux/actions/restricted.js b/packages/gatsby/src/redux/actions/restricted.js index 6d9d5d6346706..e432b27b3e003 100644 --- a/packages/gatsby/src/redux/actions/restricted.js +++ b/packages/gatsby/src/redux/actions/restricted.js @@ -1,9 +1,8 @@ -// @flow const { camelCase } = require(`lodash`) const report = require(`gatsby-cli/lib/reporter`) const { parseTypeDef } = require(`../../schema/types/type-defs`) -import type { Plugin } from "./types" +// import type { Plugin } from "./types" const actions = {} @@ -21,9 +20,9 @@ const actions = {} * @param {GraphQLSchema} $0.schema GraphQL schema to add */ actions.addThirdPartySchema = ( - { schema }: { schema: GraphQLSchema }, - plugin: Plugin, - traceId?: string + { schema } /*: { schema: GraphQLSchema }*/, + plugin /*: Plugin*/, + traceId /*?: string*/ ) => { return { type: `ADD_THIRD_PARTY_SCHEMA`, @@ -33,7 +32,7 @@ actions.addThirdPartySchema = ( } } -import type GatsbyGraphQLType from "../../schema/types/type-builders" +// import type GatsbyGraphQLType from "../../schema/types/type-builders" /** * Add type definitions to the GraphQL schema. * @@ -176,13 +175,13 @@ import type GatsbyGraphQLType from "../../schema/types/type-builders" * } */ actions.createTypes = ( - types: + types /*: | string | GraphQLOutputType | GatsbyGraphQLType - | Array, - plugin: Plugin, - traceId?: string + | Array*/, + plugin /*: Plugin*/, + traceId /*?: string*/ ) => { return { type: `CREATE_TYPES`, @@ -195,7 +194,7 @@ actions.createTypes = ( } const { reservedExtensionNames } = require(`../../schema/extensions`) -import type GraphQLFieldExtensionDefinition from "../../schema/extensions" +// import type GraphQLFieldExtensionDefinition from "../../schema/extensions" /** * Add a field extension to the GraphQL schema. * @@ -238,9 +237,9 @@ import type GraphQLFieldExtensionDefinition from "../../schema/extensions" * } */ actions.createFieldExtension = ( - extension: GraphQLFieldExtensionDefinition, - plugin: Plugin, - traceId?: string + extension /*: GraphQLFieldExtensionDefinition*/, + plugin /*: Plugin*/, + traceId /*?: string*/ ) => (dispatch, getState) => { const { name } = extension || {} const { fieldExtensions } = getState().schemaCustomization @@ -293,14 +292,14 @@ actions.printTypeDefinitions = ( include, exclude, withFieldTypes = true, - }: { + } /*: { path?: string, include?: { types?: Array, plugins?: Array }, exclude?: { types?: Array, plugins?: Array }, withFieldTypes?: boolean, - }, - plugin: Plugin, - traceId?: string + }*/, + plugin /*: Plugin*/, + traceId /*?: string*/ ) => { return { type: `PRINT_SCHEMA_REQUESTED`, @@ -346,9 +345,9 @@ actions.printTypeDefinitions = ( * } */ actions.createResolverContext = ( - context: object, - plugin: Plugin, - traceId?: string + context /*: object*/, + plugin /*: Plugin*/, + traceId /*?: string*/ ) => dispatch => { if (!context || typeof context !== `object`) { report.error( diff --git a/packages/gatsby/src/redux/actions/types.js b/packages/gatsby/src/redux/actions/types.js index 5980f1797479d..66a52bd9bc85f 100644 --- a/packages/gatsby/src/redux/actions/types.js +++ b/packages/gatsby/src/redux/actions/types.js @@ -1,6 +1,5 @@ -// @flow -type Plugin = { - name: string, -} +// type Plugin = { +// name: string, +// } -export type { Plugin } +// export type { Plugin } diff --git a/packages/gatsby/src/schema/extensions/index.js b/packages/gatsby/src/schema/extensions/index.js index 28f4fc4b6aaa1..6bb8aa033b4df 100644 --- a/packages/gatsby/src/schema/extensions/index.js +++ b/packages/gatsby/src/schema/extensions/index.js @@ -1,4 +1,3 @@ -// @flow const { GraphQLDirective, DirectiveLocation, @@ -8,18 +7,18 @@ const { const { link, fileByPath } = require(`../resolvers`) const { getDateResolver } = require(`../types/date`) -import type { GraphQLFieldConfigArgumentMap, GraphQLFieldConfig } from "graphql" -import type { ComposeFieldConfig, ComposeOutputType } from "graphql-compose" +// import type { GraphQLFieldConfigArgumentMap, GraphQLFieldConfig } from "graphql" +// import type { ComposeFieldConfig, ComposeOutputType } from "graphql-compose" -export interface GraphQLFieldExtensionDefinition { - name: string; - type?: ComposeOutputType; - args?: GraphQLFieldConfigArgumentMap; - extend( - args: GraphQLFieldConfigArgumentMap, - prevFieldConfig: GraphQLFieldConfig - ): $Shape; -} +// export interface GraphQLFieldExtensionDefinition { +// name: string; +// type?: ComposeOutputType; +// args?: GraphQLFieldConfigArgumentMap; +// extend( +// args: GraphQLFieldConfigArgumentMap, +// prevFieldConfig: GraphQLFieldConfig +// ): $Shape; +// } const inferExtensionName = `infer` const dontInferExtensionName = `dontInfer` diff --git a/packages/gatsby/src/schema/node-model.js b/packages/gatsby/src/schema/node-model.js index 11dfcdfaf9902..89659162c6739 100644 --- a/packages/gatsby/src/schema/node-model.js +++ b/packages/gatsby/src/schema/node-model.js @@ -1,9 +1,7 @@ -// @flow - const _ = require(`lodash`) const { isAbstractType, - GraphQLOutputType, + // GraphQLOutputType, GraphQLUnionType, GraphQLList, getNamedType, @@ -13,7 +11,7 @@ const { const invariant = require(`invariant`) const reporter = require(`gatsby-cli/lib/reporter`) -type TypeOrTypeName = string | GraphQLOutputType +// type TypeOrTypeName = string | GraphQLOutputType /** * Optional page dependency information. @@ -22,42 +20,42 @@ type TypeOrTypeName = string | GraphQLOutputType * @property {string} path The path of the page that depends on the retrieved nodes' data * @property {string} [connectionType] Mark this dependency as a connection */ -interface PageDependencies { - path: string; - connectionType?: string; -} - -interface QueryArguments { - type: TypeOrTypeName; - query: { filter: Object, sort?: Object }; - firstOnly?: boolean; -} - -export interface NodeModel { - getNodeById( - { id: string, type?: TypeOrTypeName }, - pageDependencies?: PageDependencies - ): any | null; - getNodesByIds( - { ids: Array, type?: TypeOrTypeName }, - pageDependencies?: PageDependencies - ): Array; - getAllNodes( - { type?: TypeOrTypeName }, - pageDependencies?: PageDependencies - ): Array; - runQuery( - args: QueryArguments, - pageDependencies?: PageDependencies - ): Promise; - getTypes(): Array; - trackPageDependencies( - result: nodeOrNodes, - pageDependencies?: PageDependencies - ): nodesOrNodes; - findRootNodeAncestor(obj: any, predicate: () => boolean): Node | null; - trackInlineObjectsInRootNode(node: Node, sanitize: boolean): Node; -} +// interface PageDependencies { +// path: string; +// connectionType?: string; +// } + +// interface QueryArguments { +// type: TypeOrTypeName; +// query: { filter: Object, sort?: Object }; +// firstOnly?: boolean; +// } + +// export interface NodeModel { +// getNodeById( +// { id: string, type?: TypeOrTypeName }, +// pageDependencies?: PageDependencies +// ): any | null; +// getNodesByIds( +// { ids: Array, type?: TypeOrTypeName }, +// pageDependencies?: PageDependencies +// ): Array; +// getAllNodes( +// { type?: TypeOrTypeName }, +// pageDependencies?: PageDependencies +// ): Array; +// runQuery( +// args: QueryArguments, +// pageDependencies?: PageDependencies +// ): Promise; +// getTypes(): Array; +// trackPageDependencies( +// result: nodeOrNodes, +// pageDependencies?: PageDependencies +// ): nodesOrNodes; +// findRootNodeAncestor(obj: any, predicate: () => boolean): Node | null; +// trackInlineObjectsInRootNode(node: Node, sanitize: boolean): Node; +// } class LocalNodeModel { constructor({ schema, schemaComposer, nodeStore, createPageDependency }) { diff --git a/packages/gatsby/src/schema/types/type-builders.js b/packages/gatsby/src/schema/types/type-builders.js index 0e6ec14731e8d..cc6865f95d550 100644 --- a/packages/gatsby/src/schema/types/type-builders.js +++ b/packages/gatsby/src/schema/types/type-builders.js @@ -1,13 +1,13 @@ // @flow -import type { - ComposeObjectTypeConfig, - ComposeInputObjectTypeConfig, - ComposeInterfaceTypeConfig, - ComposeUnionTypeConfig, - ComposeEnumTypeConfig, - ComposeScalarTypeConfig, -} from "graphql-compose" +// import type { +// ComposeObjectTypeConfig, +// ComposeInputObjectTypeConfig, +// ComposeInterfaceTypeConfig, +// ComposeUnionTypeConfig, +// ComposeEnumTypeConfig, +// ComposeScalarTypeConfig, +// } from "graphql-compose" const GatsbyGraphQLTypeKind = { OBJECT: `OBJECT`, @@ -18,31 +18,31 @@ const GatsbyGraphQLTypeKind = { SCALAR: `SCALAR`, } -export type GatsbyGraphQLType = - | { - kind: GatsbyGraphQLTypeKind.OBJECT, - config: ComposeObjectTypeConfig, - } - | { - kind: GatsbyGraphQLTypeKind.INPUT_OBJECT, - config: ComposeInputObjectTypeConfig, - } - | { - kind: GatsbyGraphQLTypeKind.UNION, - config: ComposeUnionTypeConfig, - } - | { - kind: GatsbyGraphQLTypeKind.INTERFACE, - config: ComposeInterfaceTypeConfig, - } - | { - kind: GatsbyGraphQLTypeKind.ENUM, - config: ComposeEnumTypeConfig, - } - | { - kind: GatsbyGraphQLTypeKind.SCALAR, - config: ComposeScalarTypeConfig, - } +// export type GatsbyGraphQLType = +// | { +// kind: GatsbyGraphQLTypeKind.OBJECT, +// config: ComposeObjectTypeConfig, +// } +// | { +// kind: GatsbyGraphQLTypeKind.INPUT_OBJECT, +// config: ComposeInputObjectTypeConfig, +// } +// | { +// kind: GatsbyGraphQLTypeKind.UNION, +// config: ComposeUnionTypeConfig, +// } +// | { +// kind: GatsbyGraphQLTypeKind.INTERFACE, +// config: ComposeInterfaceTypeConfig, +// } +// | { +// kind: GatsbyGraphQLTypeKind.ENUM, +// config: ComposeEnumTypeConfig, +// } +// | { +// kind: GatsbyGraphQLTypeKind.SCALAR, +// config: ComposeScalarTypeConfig, +// } const buildObjectType = config => { return { diff --git a/packages/gatsby/src/utils/webpack-utils.js b/packages/gatsby/src/utils/webpack-utils.js deleted file mode 100644 index d2d8bd534c218..0000000000000 --- a/packages/gatsby/src/utils/webpack-utils.js +++ /dev/null @@ -1,635 +0,0 @@ -// @flow - -const autoprefixer = require(`autoprefixer`) -const flexbugs = require(`postcss-flexbugs-fixes`) -const TerserPlugin = require(`terser-webpack-plugin`) -const MiniCssExtractPlugin = require(`mini-css-extract-plugin`) -const OptimizeCssAssetsPlugin = require(`optimize-css-assets-webpack-plugin`) -const isWsl = require(`is-wsl`) - -const GatsbyWebpackStatsExtractor = require(`./gatsby-webpack-stats-extractor`) -const GatsbyWebpackEslintGraphqlSchemaReload = require(`./gatsby-webpack-eslint-graphql-schema-reload-plugin`) - -const builtinPlugins = require(`./webpack-plugins`) -const eslintConfig = require(`./eslint-config`) - -type LoaderSpec = string | { loader: string, options?: Object } -type LoaderResolver = (options?: T) => LoaderSpec - -type Condition = string | RegExp | RegExp[] - -type Rule = { - test?: Condition, - use: LoaderSpec[], - exclude?: Condition, - include?: Condition, -} - -type RuleFactory = (options?: T) => Rule - -type ContextualRuleFactory = RuleFactory<*> & { - internal: RuleFactory<*>, - external: RuleFactory<*>, -} - -type PluginInstance = any -type PluginFactory = (...args?: any) => PluginInstance - -type BuiltinPlugins = typeof builtinPlugins - -type Stage = "develop" | "develop-html" | "build-javascript" | "build-html" - -/** - * Configuration options for `createUtils` - */ -export type WebpackUtilsOptions = { stage: Stage, program: any } - -/** - * Utils that produce webpack `loader` objects - */ -export type LoaderUtils = { - json: LoaderResolver<*>, - yaml: LoaderResolver<*>, - null: LoaderResolver<*>, - raw: LoaderResolver<*>, - - style: LoaderResolver<*>, - css: LoaderResolver<*>, - postcss: LoaderResolver<{ - browsers?: string[], - plugins?: Array | ((loader: any) => Array), - }>, - - file: LoaderResolver<*>, - url: LoaderResolver<*>, - js: LoaderResolver<*>, - dependencies: LoaderResovler<*>, - - miniCssExtract: LoaderResolver<*>, - imports: LoaderResolver<*>, - exports: LoaderResolver<*>, - - eslint: LoaderResolver<*>, -} - -/** - * Utils that produce webpack rule objects - */ -export type RuleUtils = { - /** - * Handles JavaScript compilation via babel - */ - js: RuleFactory<*>, - yaml: RuleFactory<*>, - fonts: RuleFactory<*>, - images: RuleFactory<*>, - miscAssets: RuleFactory<*>, - - css: ContextualRuleFactory, - cssModules: RuleFactory<*>, - postcss: ContextualRuleFactory, - - eslint: RuleFactory<*>, -} - -export type PluginUtils = BuiltinPlugins & { - extractText: PluginFactory, - uglify: PluginFactory, - moment: PluginFactory, - extractStats: PluginFactory, -} - -/** - * webpack atoms namespace - */ -export type WebpackUtils = { - loaders: LoaderUtils, - - rules: RuleUtils, - - plugins: PluginUtils, -} - -/** - * A factory method that produces an atoms namespace - */ -module.exports = async ({ - stage, - program, -}: { - stage: Stage, - program: any, -}): Promise => { - const assetRelativeRoot = `static/` - const vendorRegex = /(node_modules|bower_components)/ - const supportedBrowsers = program.browserslist - - const PRODUCTION = !stage.includes(`develop`) - - const isSSR = stage.includes(`html`) - - const makeExternalOnly = (original: RuleFactory<*>) => ( - options = {} - ): Rule => { - let rule = original(options) - rule.include = vendorRegex - return rule - } - - const makeInternalOnly = (original: RuleFactory<*>) => ( - options = {} - ): Rule => { - let rule = original(options) - rule.exclude = vendorRegex - return rule - } - - let ident = 0 - - const loaders: LoaderUtils = { - json: (options = {}) => { - return { - options, - loader: require.resolve(`json-loader`), - } - }, - - yaml: (options = {}) => { - return { - options, - loader: require.resolve(`yaml-loader`), - } - }, - - null: (options = {}) => { - return { - options, - loader: require.resolve(`null-loader`), - } - }, - - raw: (options = {}) => { - return { - options, - loader: require.resolve(`raw-loader`), - } - }, - - style: (options = {}) => { - return { - options, - loader: require.resolve(`style-loader`), - } - }, - - miniCssExtract: (options = {}) => { - return { - options, - // use MiniCssExtractPlugin only on production builds - loader: PRODUCTION - ? MiniCssExtractPlugin.loader - : require.resolve(`style-loader`), - } - }, - - css: (options = {}) => { - return { - loader: isSSR - ? require.resolve(`css-loader/locals`) - : require.resolve(`css-loader`), - options: { - sourceMap: !PRODUCTION, - camelCase: `dashesOnly`, - // https://github.com/webpack-contrib/css-loader/issues/406 - localIdentName: `[name]--[local]--[hash:base64:5]`, - ...options, - }, - } - }, - - postcss: (options = {}) => { - let { - plugins, - overrideBrowserslist = supportedBrowsers, - ...postcssOpts - } = options - - return { - loader: require.resolve(`postcss-loader`), - options: { - ident: `postcss-${++ident}`, - sourceMap: !PRODUCTION, - plugins: loader => { - plugins = - (typeof plugins === `function` ? plugins(loader) : plugins) || [] - - return [ - flexbugs, - autoprefixer({ overrideBrowserslist, flexbox: `no-2009` }), - ...plugins, - ] - }, - ...postcssOpts, - }, - } - }, - - file: (options = {}) => { - return { - loader: require.resolve(`file-loader`), - options: { - name: `${assetRelativeRoot}[name]-[hash].[ext]`, - ...options, - }, - } - }, - - url: (options = {}) => { - return { - loader: require.resolve(`url-loader`), - options: { - limit: 10000, - name: `${assetRelativeRoot}[name]-[hash].[ext]`, - ...options, - }, - } - }, - - js: options => { - return { - options: { - stage, - ...options, - }, - loader: require.resolve(`./babel-loader`), - } - }, - - dependencies: options => { - return { - options, - loader: require.resolve(`babel-loader`), - } - }, - - eslint: (schema = ``) => { - const options = eslintConfig(schema) - - return { - options, - loader: require.resolve(`eslint-loader`), - } - }, - - imports: (options = {}) => { - return { - options, - loader: require.resolve(`imports-loader`), - } - }, - - exports: (options = {}) => { - return { - options, - loader: require.resolve(`exports-loader`), - } - }, - } - - /** - * Rules - */ - const rules = {} - - /** - * JavaScript loader via babel, includes userland code - * and packages that depend on `gatsby` - */ - { - let js = ({ modulesThatUseGatsby = [], ...options } = {}) => { - return { - test: /\.(js|mjs|jsx)$/, - include: modulePath => { - // when it's not coming from node_modules we treat it as a source file. - if (!vendorRegex.test(modulePath)) { - return true - } - - // If the module uses Gatsby as a dependency - // we want to treat it as src so we can extract queries - return modulesThatUseGatsby.some(module => - modulePath.includes(module.path) - ) - }, - type: `javascript/auto`, - use: [ - loaders.js({ - ...options, - configFile: true, - compact: PRODUCTION, - }), - ], - } - } - - rules.js = js - } - - /** - * Node_modules JavaScript loader via babel - * Excludes core-js & babel-runtime to speedup babel transpilation - * Excludes modules that use Gatsby since the `rules.js` already transpiles those - */ - { - let dependencies = ({ modulesThatUseGatsby = [] } = {}) => { - const jsOptions = { - babelrc: false, - configFile: false, - compact: false, - presets: [require.resolve(`babel-preset-gatsby/dependencies`)], - // If an error happens in a package, it's possible to be - // because it was compiled. Thus, we don't want the browser - // debugger to show the original code. Instead, the code - // being evaluated would be much more helpful. - sourceMaps: false, - cacheIdentifier: `${stage}---gatsby-dependencies@${ - require(`babel-preset-gatsby/package.json`).version - }`, - } - - return { - test: /\.(js|mjs)$/, - exclude: modulePath => { - if (vendorRegex.test(modulePath)) { - // If dep uses Gatsby, exclude - if ( - modulesThatUseGatsby.some(module => - modulePath.includes(module.path) - ) - ) { - return true - } - // If dep is babel-runtime or core-js, exclude - if (/@babel(?:\/|\\{1,2})runtime|core-js/.test(modulePath)) { - return true - } - - // If dep is in node_modules and none of the above, include - return false - } - - // If dep is user land code, exclude - return true - }, - type: `javascript/auto`, - use: [loaders.dependencies(jsOptions)], - } - } - - rules.dependencies = dependencies - } - - { - let eslint = schema => { - return { - enforce: `pre`, - test: /\.jsx?$/, - exclude: vendorRegex, - use: [loaders.eslint(schema)], - } - } - - rules.eslint = eslint - } - - rules.yaml = () => { - return { - test: /\.ya?ml/, - use: [loaders.json(), loaders.yaml()], - } - } - - /** - * Font loader - */ - rules.fonts = () => { - return { - use: [loaders.url()], - test: /\.(eot|otf|ttf|woff(2)?)(\?.*)?$/, - } - } - - /** - * Loads image assets, inlines images via a data URI if they are below - * the size threshold - */ - rules.images = () => { - return { - use: [loaders.url()], - test: /\.(ico|svg|jpg|jpeg|png|gif|webp)(\?.*)?$/, - } - } - - /** - * Loads audio and video and inlines them via a data URI if they are below - * the size threshold - */ - rules.media = () => { - return { - use: [loaders.url()], - test: /\.(mp4|webm|ogv|wav|mp3|m4a|aac|oga|flac)$/, - } - } - - /** - * Loads assets without inlining - */ - rules.miscAssets = () => { - return { - use: [loaders.file()], - test: /\.pdf$/, - } - } - - /** - * CSS style loader. - */ - { - const css = ({ browsers, ...options } = {}) => { - const use = [ - loaders.css({ ...options, importLoaders: 1 }), - loaders.postcss({ browsers }), - ] - if (!isSSR) - use.unshift( - loaders.miniCssExtract({ hmr: !PRODUCTION && !options.modules }) - ) - - return { - use, - test: /\.css$/, - } - } - - /** - * CSS style loader, _excludes_ node_modules. - */ - css.internal = makeInternalOnly(css) - css.external = makeExternalOnly(css) - - const cssModules = options => { - const rule = css({ ...options, modules: true }) - delete rule.exclude - rule.test = /\.module\.css$/ - return rule - } - - rules.css = css - rules.cssModules = cssModules - } - - /** - * PostCSS loader. - */ - { - const postcss = options => { - return { - test: /\.css$/, - use: [loaders.css({ importLoaders: 1 }), loaders.postcss(options)], - } - } - - /** - * PostCSS loader, _excludes_ node_modules. - */ - postcss.internal = makeInternalOnly(postcss) - postcss.external = makeExternalOnly(postcss) - rules.postcss = postcss - } - /** - * Plugins - */ - const plugins = { ...builtinPlugins } - - /** - * Minify JavaScript code without regard for IE8. Attempts - * to parallelize the work to save time. Generally only add in Production - */ - plugins.minifyJs = ({ terserOptions, ...options } = {}) => - new TerserPlugin({ - cache: true, - // We can't use parallel in WSL because of https://github.com/gatsbyjs/gatsby/issues/6540 - // This issue was fixed in https://github.com/gatsbyjs/gatsby/pull/12636 - parallel: !isWsl, - exclude: /\.min\.js/, - sourceMap: true, - terserOptions: { - ie8: false, - mangle: { - safari10: true, - }, - parse: { - ecma: 8, - }, - compress: { - ecma: 5, - }, - output: { - ecma: 5, - }, - ...terserOptions, - }, - ...options, - }) - - plugins.minifyCss = ( - options = { - cssProcessorPluginOptions: { - preset: [ - `default`, - { - svgo: { - full: true, - plugins: [ - { - // potentially destructive plugins removed - see https://github.com/gatsbyjs/gatsby/issues/15629 - // convertShapeToPath: true, - // removeViewBox: true, - removeUselessDefs: true, - addAttributesToSVGElement: true, - addClassesToSVGElement: true, - cleanupAttrs: true, - cleanupEnableBackground: true, - cleanupIDs: true, - cleanupListOfValues: true, - cleanupNumericValues: true, - collapseGroups: true, - convertColors: true, - convertPathData: true, - convertStyleToAttrs: true, - convertTransform: true, - inlineStyles: true, - mergePaths: true, - minifyStyles: true, - moveElemsAttrsToGroup: true, - moveGroupAttrsToElems: true, - prefixIds: true, - removeAttributesBySelector: true, - removeAttrs: true, - removeComments: true, - removeDesc: true, - removeDimensions: true, - removeDoctype: true, - removeEditorsNSData: true, - removeElementsByAttr: true, - removeEmptyAttrs: true, - removeEmptyContainers: true, - removeEmptyText: true, - removeHiddenElems: true, - removeMetadata: true, - removeNonInheritableGroupAttrs: true, - removeOffCanvasPaths: true, - removeRasterImages: true, - removeScriptElement: true, - removeStyleElement: true, - removeTitle: true, - removeUnknownsAndDefaults: true, - removeUnusedNS: true, - removeUselessStrokeAndFill: true, - removeXMLNS: true, - removeXMLProcInst: true, - reusePaths: true, - sortAttrs: true, - }, - ], - }, - }, - ], - }, - } - ) => new OptimizeCssAssetsPlugin(options) - - /** - * Extracts css requires into a single file; - * includes some reasonable defaults - */ - plugins.extractText = options => - new MiniCssExtractPlugin({ - filename: `[name].[contenthash].css`, - chunkFilename: `[name].[contenthash].css`, - ...options, - }) - - plugins.moment = () => plugins.ignore(/^\.\/locale$/, /moment$/) - - plugins.extractStats = options => new GatsbyWebpackStatsExtractor(options) - - plugins.eslintGraphqlSchemaReload = options => - new GatsbyWebpackEslintGraphqlSchemaReload(options) - - return { - loaders, - rules: (rules: RuleUtils), - plugins: (plugins: PluginUtils), - } -} diff --git a/packages/gatsby/tsconfig.json b/packages/gatsby/tsconfig.json new file mode 100644 index 0000000000000..4082f16a5d91c --- /dev/null +++ b/packages/gatsby/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tsconfig.json" +} diff --git a/scripts/check-ts.js b/scripts/check-ts.js new file mode 100644 index 0000000000000..45e92973c2f24 --- /dev/null +++ b/scripts/check-ts.js @@ -0,0 +1,44 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +"use strict" + +const fs = require(`fs`) +const path = require(`path`) + +const execa = require(`execa`) + +const PACKAGES_DIR = path.resolve(__dirname, `../packages`) + +const packages = fs + .readdirSync(PACKAGES_DIR) + .map(file => path.resolve(PACKAGES_DIR, file)) + .filter(f => fs.lstatSync(path.resolve(f)).isDirectory()) + +const packagesWithTs = packages.filter(p => + fs.existsSync(path.resolve(p, `tsconfig.json`)) +) + +const args = [ + `--max-old-space-size=4096`, + path.resolve( + require.resolve(`typescript/package.json`), + `..`, + require(`typescript/package.json`).bin.tsc + ), + `-p`, + ...packagesWithTs, + ...process.argv.slice(2), + `--noEmit`, +] + +try { + execa.sync(`node`, args, { stdio: `inherit` }) + console.log(`TypeScript Check: Success`) +} catch (e) { + process.exitCode = 1 +} diff --git a/tsconfig.json b/tsconfig.json index 2cc6d0aee4e43..8508a4f325b92 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,12 @@ { "compilerOptions": { - "target": "es5", - "module": "commonjs", - "lib": ["es2017"], - "strict": true - } + /* Additional Checks */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "esModuleInterop": true, + "typeRoots": ["node_modules/@types"] + }, + "exclude": ["peril/*", "examples/*"] } diff --git a/yarn.lock b/yarn.lock index 7b8b60da0501c..2aea2f2299472 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3709,10 +3709,25 @@ dependencies: "@babel/types" "^7.3.0" +"@types/body-parser@*": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.1.tgz#18fcf61768fb5c30ccc508c21d6fd2e8b3bf7897" + integrity sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w== + dependencies: + "@types/connect" "*" + "@types/node" "*" + "@types/configstore@^2.1.1": version "2.1.1" resolved "https://registry.yarnpkg.com/@types/configstore/-/configstore-2.1.1.tgz#cd1e8553633ad3185c3f2f239ecff5d2643e92b6" +"@types/connect@*": + version "3.4.32" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" + integrity sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg== + dependencies: + "@types/node" "*" + "@types/debug@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-0.0.29.tgz#a1e514adfbd92f03a224ba54d693111dbf1f3754" @@ -3730,6 +3745,23 @@ version "1.2.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" +"@types/express-serve-static-core@*": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.0.tgz#e80c25903df5800e926402b7e8267a675c54a281" + integrity sha512-Xnub7w57uvcBqFdIGoRg1KhNOeEj0vB6ykUM7uFWyxvbdE89GFyqgmUcanAriMr4YOxNFZBAWkfcWIb4WBPt3g== + dependencies: + "@types/node" "*" + "@types/range-parser" "*" + +"@types/express@^4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.2.tgz#a0fb7a23d8855bac31bc01d5a58cadd9b2173e6c" + integrity sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + "@types/get-port@^0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@types/get-port/-/get-port-0.0.4.tgz#eb6bb7423d9f888b632660dc7d2fd3e69a35643e" @@ -3772,11 +3804,23 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/jest@^24.0.23": + version "24.0.23" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.23.tgz#046f8e2ade026fe831623e361a36b6fb9a4463e4" + integrity sha512-L7MBvwfNpe7yVPTXLn32df/EK+AMBFAFvZrRuArGs7npEWnlziUXK+5GMIUTI4NIuwok3XibsjXCs5HxviYXjg== + dependencies: + jest-diff "^24.3.0" + "@types/json-schema@^7.0.3": version "7.0.3" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== +"@types/mime@*": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" + integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -3790,6 +3834,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.8.tgz#e469b4bf9d1c9832aee4907ba8a051494357c12c" integrity sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg== +"@types/node@^12.12.11": + version "12.12.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.11.tgz#bec2961975888d964196bf0016a2f984d793d3ce" + integrity sha512-O+x6uIpa6oMNTkPuHDa9MhMMehlxLAd5QcOvKRjAFsBVpeFWTOPnXbDvILvFgFFZfQ1xh1EZi1FbXxUix+zpsQ== + "@types/node@^12.7.5": version "12.7.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.5.tgz#e19436e7f8e9b4601005d73673b6dc4784ffcc2f" @@ -3829,6 +3878,11 @@ version "1.5.2" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" +"@types/range-parser@*": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" + integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== + "@types/reach__router@^1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.2.6.tgz#b14cf1adbd1a365d204bbf6605cd9dd7b8816c87" @@ -3858,6 +3912,14 @@ dependencies: "@types/node" "*" +"@types/serve-static@*": + version "1.13.3" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" + integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g== + dependencies: + "@types/express-serve-static-core" "*" + "@types/mime" "*" + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -12855,7 +12917,7 @@ jest-diff@^22.4.0, jest-diff@^22.4.3: jest-get-type "^22.4.3" pretty-format "^22.4.3" -jest-diff@^24.9.0: +jest-diff@^24.3.0, jest-diff@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==