Skip to content

Commit

Permalink
feat(gatsby): plugin option validation (#27242)
Browse files Browse the repository at this point in the history
* Add pluginOptionsSchema to google analytics for testing

* Add structured error for plugin option validation errors

* Validate gatsbyNode.pluginOptionsSchema when defined

* Add first test, fix some bugs discovered based on it

* process.exit on invalid plugin options

* Much nicer structured error logging for invalid plugin options

* Move TODO comment to correct place

* Remove unused import

* Add new API to gatsby-node API tests

* Warn on invalid plugin schema

* Gate plugin option validation behind feature flag for now

* less formal wording

* Clean up based on code review

* Type GatsbyNode.pluginOptionsSchema

* Properly type Joi including our .dotenv() extension

* Move custom joi + types to gatsby-plugin-utils

* Disable the .dotenv extension for now
  • Loading branch information
mxstbr authored Oct 7, 2020
1 parent cc1bbfc commit 9b01ca7
Show file tree
Hide file tree
Showing 15 changed files with 2,554 additions and 11 deletions.
1 change: 1 addition & 0 deletions .jestSetup.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
process.env.GATSBY_RECIPES_NO_COLOR = "true"
process.env.GATSBY_EXPERIMENTAL_PLUGIN_OPTION_VALIDATION = "true"
16 changes: 16 additions & 0 deletions packages/gatsby-cli/src/structured-errors/error-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,22 @@ const errors = {
type: Type.PLUGIN,
level: Level.ERROR,
},
// Invalid plugin options
"11331": {
text: (context): string =>
[
stripIndent(`
Invalid plugin options for "${context.pluginName}":
`),
]
.concat([``])
.concat(
context.validationErrors.map(error => `- ${error.message}`).join(`\n`)
)
.join(`\n`),
type: Type.PLUGIN,
level: Level.ERROR,
},
// node object didn't pass validation
"11467": {
text: (context): string =>
Expand Down
46 changes: 39 additions & 7 deletions packages/gatsby-plugin-google-analytics/src/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,39 @@
exports.onPreInit = ({ reporter }, options) => {
if (!options.trackingId) {
reporter.warn(
`The Google Analytics plugin requires a tracking ID. Did you mean to add it?`
)
}
}
exports.pluginOptionsSchema = ({ Joi }) =>
Joi.object({
trackingId: Joi.string()
.required()
.description(
`The property ID; the tracking code won't be generated without it`
),
head: Joi.boolean()
.default(false)
.description(
`Defines where to place the tracking script - \`true\` in the head and \`false\` in the body`
),
anonymize: Joi.boolean().default(false),
respectDNT: Joi.boolean().default(false),
exclude: Joi.array()
.items(Joi.string())
.default([])
.description(`Avoids sending pageview hits from custom paths`),
pageTransitionDelay: Joi.number()
.default(0)
.description(
`Delays sending pageview hits on route update (in milliseconds)`
),
optimizeId: Joi.string().description(
`Enables Google Optimize using your container Id`
),
experimentId: Joi.string().description(
`Enables Google Optimize Experiment ID`
),
variationId: Joi.string().description(
`Set Variation ID. 0 for original 1,2,3....`
),
defer: Joi.boolean().description(
`Defers execution of google analytics script after page load`
),
sampleRate: Joi.number(),
siteSpeedSampleRate: Joi.number(),
cookieDomain: Joi.string(),
})
3 changes: 1 addition & 2 deletions packages/gatsby-plugin-utils/src/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import Joi from "joi"
import { validateOptionsSchema } from "../"
import { validateOptionsSchema, Joi } from "../"

it(`validates a basic schema`, async () => {
const pluginSchema = Joi.object({
Expand Down
1 change: 1 addition & 0 deletions packages/gatsby-plugin-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./validate"
export * from "./joi"
27 changes: 27 additions & 0 deletions packages/gatsby-plugin-utils/src/joi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import joi from "joi"
import { PluginOptionsSchemaJoi } from "./utils/plugin-options-schema-joi-type"

export * from "./utils/plugin-options-schema-joi-type"
export const Joi: PluginOptionsSchemaJoi = joi.extend({
// This tells Joi to extend _all_ types with .dotenv(), see
// https://github.com/sideway/joi/commit/03adf22eb1f06c47d1583617093edee3a96b3873
// @ts-ignore Joi types weren't updated with that commit, PR: https://github.com/sideway/joi/pull/2477
type: /^s/,
rules: {
// NOTE(@mxstbr): Disabled until we decide on the necessity for this API.
// dotenv: {
// args: [`name`],
// validate(value, helpers, args): void {
// if (!args.name) {
// return helpers.error(
// `any.dotenv requires the environment variable name`
// )
// }
// return value
// },
// method(name): Schema {
// return this.$_addRule({ name: `dotenv`, args: { name } })
// },
// },
},
})
Loading

0 comments on commit 9b01ca7

Please sign in to comment.