diff --git a/e2e-tests/adapters/cypress/e2e/remote-file.cy.ts b/e2e-tests/adapters/cypress/e2e/remote-file.cy.ts index 81b3acb000e2c..5f168eab76c80 100644 --- a/e2e-tests/adapters/cypress/e2e/remote-file.cy.ts +++ b/e2e-tests/adapters/cypress/e2e/remote-file.cy.ts @@ -222,12 +222,17 @@ for (const config of configs) { it(`File CDN`, () => { cy.get('[data-testid="file-public"]').then(async $urls => { - const urls = Array.from( - $urls.map((_, $url) => $url.getAttribute("href")) + const fileCdnFixtures = Array.from( + $urls.map((_, $url) => { + return { + urlWithoutOrigin: $url.getAttribute("href"), + allowed: $url.getAttribute("data-allowed") === "true", + } + }) ) // urls is array of href attribute, not absolute urls, so it already is stripped of origin - for (const urlWithoutOrigin of urls) { + for (const { urlWithoutOrigin, allowed } of fileCdnFixtures) { // using Netlify Image CDN expect(urlWithoutOrigin).to.match( new RegExp(`^${PATH_PREFIX}/_gatsby/file`) @@ -235,7 +240,12 @@ for (const config of configs) { const res = await fetch(urlWithoutOrigin, { method: "HEAD", }) - expect(res.ok).to.be.true + if (allowed) { + expect(res.ok).to.be.true + } else { + expect(res.ok).to.be.false + expect(res.status).to.be.equal(500) + } } }) }) diff --git a/e2e-tests/adapters/gatsby-node.ts b/e2e-tests/adapters/gatsby-node.ts index e054bf7e56693..9342bb30fa191 100644 --- a/e2e-tests/adapters/gatsby-node.ts +++ b/e2e-tests/adapters/gatsby-node.ts @@ -47,6 +47,7 @@ export const createPages: GatsbyNode["createPages"] = async ({ url filename publicUrl + isAllowed } } } @@ -138,7 +139,9 @@ export const createSchemaCustomization: GatsbyNode["createSchemaCustomization"] addRemoteFilePolyfillInterface( schema.buildObjectType({ name: "MyRemoteFile", - fields: {}, + fields: { + isAllowed: `String!`, + }, interfaces: ["Node", "RemoteFile"], }), { @@ -148,6 +151,13 @@ export const createSchemaCustomization: GatsbyNode["createSchemaCustomization"] } ) ) + + if (typeof actions.addRemoteFileAllowedUrl === `function`) { + actions.addRemoteFileAllowedUrl([ + `https://images.unsplash.com/*`, + `https://www.gatsbyjs.com/*`, + ]) + } } export const sourceNodes: GatsbyNode["sourceNodes"] = function sourceNodes({ @@ -191,6 +201,16 @@ export const sourceNodes: GatsbyNode["sourceNodes"] = function sourceNodes({ mimeType: "image/svg+xml", filename: "Gatsby-Logo.svg", type: `MyRemoteFile`, + isAllowed: true, + }, + { + // svg is not considered for image cdn - file cdn will be used + name: "fileB.svg", + url: "https://www.not-allowed.com/not-allowed.svg", + mimeType: "image/svg+xml", + filename: "Gatsby-Logo.svg", + type: `MyRemoteFile`, + isAllowed: false, }, ] diff --git a/e2e-tests/adapters/src/pages/routes/remote-file.jsx b/e2e-tests/adapters/src/pages/routes/remote-file.jsx index c93c3f7eff70b..8f2ceba8a1756 100644 --- a/e2e-tests/adapters/src/pages/routes/remote-file.jsx +++ b/e2e-tests/adapters/src/pages/routes/remote-file.jsx @@ -43,7 +43,11 @@ const RemoteFile = ({ data }) => { return (

- + {node.filename}

@@ -91,6 +95,7 @@ export const pageQuery = graphql` url filename publicUrl + isAllowed } } } diff --git a/e2e-tests/adapters/src/pages/routes/ssr/remote-file.jsx b/e2e-tests/adapters/src/pages/routes/ssr/remote-file.jsx index 923831a179b6d..87477e2ea3b9c 100644 --- a/e2e-tests/adapters/src/pages/routes/ssr/remote-file.jsx +++ b/e2e-tests/adapters/src/pages/routes/ssr/remote-file.jsx @@ -43,7 +43,11 @@ const RemoteFile = ({ data }) => { return (

- + {node.filename}

@@ -98,6 +102,7 @@ export const pageQuery = graphql` url filename publicUrl + isAllowed } } } diff --git a/e2e-tests/adapters/src/templates/remote-file-from-context.jsx b/e2e-tests/adapters/src/templates/remote-file-from-context.jsx index d6532903dce06..4773a88beb1cb 100644 --- a/e2e-tests/adapters/src/templates/remote-file-from-context.jsx +++ b/e2e-tests/adapters/src/templates/remote-file-from-context.jsx @@ -42,7 +42,11 @@ const RemoteFile = ({ pageContext: data }) => { return (

- + {node.filename}

diff --git a/packages/gatsby-adapter-netlify/.babelrc b/packages/gatsby-adapter-netlify/.babelrc index 84af48678d3f0..264f094569e08 100644 --- a/packages/gatsby-adapter-netlify/.babelrc +++ b/packages/gatsby-adapter-netlify/.babelrc @@ -3,7 +3,7 @@ [ "babel-preset-gatsby-package", { - "keepDynamicImports": ["./src/index.ts"] + "keepDynamicImports": ["./src/index.ts", "./src/allowed-remote-urls.ts"] } ] ] diff --git a/packages/gatsby-adapter-netlify/package.json b/packages/gatsby-adapter-netlify/package.json index 0dd2e1552ae59..f5a230377d993 100644 --- a/packages/gatsby-adapter-netlify/package.json +++ b/packages/gatsby-adapter-netlify/package.json @@ -33,6 +33,7 @@ "dependencies": { "@babel/runtime": "^7.20.13", "@netlify/cache-utils": "^5.1.5", + "@netlify/config": "^20.10.0", "@netlify/functions": "^1.6.0", "cookie": "^0.5.0", "fastq": "^1.15.0", diff --git a/packages/gatsby-adapter-netlify/src/allowed-remote-urls.ts b/packages/gatsby-adapter-netlify/src/allowed-remote-urls.ts new file mode 100644 index 0000000000000..daddb94d64a3d --- /dev/null +++ b/packages/gatsby-adapter-netlify/src/allowed-remote-urls.ts @@ -0,0 +1,54 @@ +import type { Reporter, RemoteFileAllowedUrls } from "gatsby" + +export async function handleAllowedRemoteUrlsNetlifyConfig({ + remoteFileAllowedUrls, + reporter, +}: { + remoteFileAllowedUrls: RemoteFileAllowedUrls + reporter: Reporter +}): Promise { + const { resolveConfig } = await import(`@netlify/config`) + const cfg = await resolveConfig() + + if (cfg?.config) { + const allowedUrlsInNetlifyToml: Array = + cfg.config.images?.remote_images ?? [] + + const allowedUrlsInNetlifyTomlRegexes = allowedUrlsInNetlifyToml.map( + regexSource => new RegExp(regexSource) + ) + + const missingAllowedUrlsInNetlifyToml: Array = [] + for (const remoteFileAllowedUrl of remoteFileAllowedUrls) { + // test if url pattern already passes one of the regexes in netlify.toml + const isAlreadyAllowed = allowedUrlsInNetlifyTomlRegexes.some( + allowedRegex => allowedRegex.test(remoteFileAllowedUrl.urlPattern) + ) + + if (!isAlreadyAllowed) { + missingAllowedUrlsInNetlifyToml.push(remoteFileAllowedUrl.regexSource) + } + } + + if (missingAllowedUrlsInNetlifyToml.length > 0) { + const entriesToAddToToml = `${missingAllowedUrlsInNetlifyToml + .map( + missingAllowedUrlInNetlifyToml => + ` ${JSON.stringify(missingAllowedUrlInNetlifyToml)}` + ) + .join(`,\n`)},\n` + + if (typeof cfg.config.images?.remote_images === `undefined`) { + reporter.warn( + `Missing allowed URLs in your Netlify configuration. Add following to your netlify.toml:\n\`\`\`toml\n[images]\nremote_images = [\n${entriesToAddToToml}]\n\`\`\`` + ) + } else { + reporter.warn( + `Missing allowed URLs in your Netlify configuration. Add following entries to your existing \`images.remote_images\` configuration in netlify.toml:\n\`\`\`toml\n${entriesToAddToToml}\`\`\`` + ) + } + } + } else { + reporter.verbose(`[gatsby-adapter-netlify] no netlify.toml found`) + } +} diff --git a/packages/gatsby-adapter-netlify/src/file-cdn-handler.ts b/packages/gatsby-adapter-netlify/src/file-cdn-handler.ts index cc8482c790c04..39f26c18c3023 100644 --- a/packages/gatsby-adapter-netlify/src/file-cdn-handler.ts +++ b/packages/gatsby-adapter-netlify/src/file-cdn-handler.ts @@ -3,6 +3,8 @@ import * as path from "path" import packageJson from "gatsby-adapter-netlify/package.json" +import type { RemoteFileAllowedUrls } from "gatsby" + export interface IFunctionManifest { version: 1 functions: Array< @@ -27,8 +29,10 @@ export interface IFunctionManifest { export async function prepareFileCdnHandler({ pathPrefix, + remoteFileAllowedUrls, }: { pathPrefix: string + remoteFileAllowedUrls: RemoteFileAllowedUrls }): Promise { const functionId = `file-cdn` @@ -48,21 +52,20 @@ export async function prepareFileCdnHandler({ ) const handlerSource = /* typescript */ ` - import type { Context } from "@netlify/edge-functions" + const allowedUrlPatterns = [${remoteFileAllowedUrls.map( + allowedUrl => `new RegExp(\`${allowedUrl.regexSource}\`)` + )}] - export default async (req: Request, context: Context): Promise => { + export default async (req: Request): Promise => { const url = new URL(req.url) const remoteUrl = url.searchParams.get("url") - - // @todo: use allowed remote urls to decide wether request should be allowed - // blocked by https://github.com/gatsbyjs/gatsby/pull/38719 - const isAllowed = true + + const isAllowed = allowedUrlPatterns.some(allowedUrlPattern => allowedUrlPattern.test(remoteUrl)) if (isAllowed) { - console.log(\`URL allowed\`, { remoteUrl }) return fetch(remoteUrl); } else { console.error(\`URL not allowed: \${remoteUrl}\`) - return new Response("Not allowed", { status: 403 }) + return new Response("Bad request", { status: 500 }) } } ` diff --git a/packages/gatsby-adapter-netlify/src/file-cdn-url-generator.ts b/packages/gatsby-adapter-netlify/src/file-cdn-url-generator.ts index 1bc3e37abfe64..f24efd9c8281c 100644 --- a/packages/gatsby-adapter-netlify/src/file-cdn-url-generator.ts +++ b/packages/gatsby-adapter-netlify/src/file-cdn-url-generator.ts @@ -29,8 +29,8 @@ export const generateFileUrl: FileCdnUrlGeneratorFn = function generateFileUrl( baseURL.searchParams.append(`url`, source.url) baseURL.searchParams.append(`cd`, source.internal.contentDigest) - return `${baseURL.pathname}${baseURL.search}` } + return `${baseURL.pathname}${baseURL.search}` } diff --git a/packages/gatsby-adapter-netlify/src/index.ts b/packages/gatsby-adapter-netlify/src/index.ts index 09c802a27fcf4..b34fafbb8718a 100644 --- a/packages/gatsby-adapter-netlify/src/index.ts +++ b/packages/gatsby-adapter-netlify/src/index.ts @@ -4,6 +4,7 @@ import { prepareFunctionVariants } from "./lambda-handler" import { prepareFileCdnHandler } from "./file-cdn-handler" import { handleRoutesManifest } from "./route-handler" import packageJson from "gatsby-adapter-netlify/package.json" +import { handleAllowedRemoteUrlsNetlifyConfig } from "./allowed-remote-urls" interface INetlifyCacheUtils { restore: (paths: Array) => Promise @@ -84,9 +85,19 @@ const createNetlifyAdapter: AdapterInit = options => { functionsManifest, headerRoutes, pathPrefix, + remoteFileAllowedUrls, + reporter, }): Promise { if (useNetlifyImageCDN) { - await prepareFileCdnHandler({ pathPrefix }) + await handleAllowedRemoteUrlsNetlifyConfig({ + remoteFileAllowedUrls, + reporter, + }) + + await prepareFileCdnHandler({ + pathPrefix, + remoteFileAllowedUrls, + }) } const { lambdasThatUseCaching } = await handleRoutesManifest( diff --git a/packages/gatsby-source-contentful/src/gatsby-node.js b/packages/gatsby-source-contentful/src/gatsby-node.js index 99528f805a6c1..8f582ab7a9916 100644 --- a/packages/gatsby-source-contentful/src/gatsby-node.js +++ b/packages/gatsby-source-contentful/src/gatsby-node.js @@ -43,7 +43,10 @@ const validateContentfulAccess = async pluginOptions => { return undefined } -export const onPreInit = async ({ store, reporter }) => { +export const onPreInit = async ( + { store, reporter, actions }, + pluginOptions +) => { // if gatsby-plugin-image is not installed try { await import(`gatsby-plugin-image/graphql-utils`) @@ -69,6 +72,12 @@ export const onPreInit = async ({ store, reporter }) => { }, }) } + + if (typeof actions?.addRemoteFileAllowedUrl === `function`) { + actions.addRemoteFileAllowedUrl( + `https://images.ctfassets.net/${pluginOptions.spaceId}/*` + ) + } } export const pluginOptionsSchema = ({ Joi }) => diff --git a/packages/gatsby-source-drupal/src/gatsby-node.ts b/packages/gatsby-source-drupal/src/gatsby-node.ts index 275aea5c3f949..8317b65758058 100644 --- a/packages/gatsby-source-drupal/src/gatsby-node.ts +++ b/packages/gatsby-source-drupal/src/gatsby-node.ts @@ -132,8 +132,12 @@ function gracefullyRethrow(activity, error) { } } -exports.onPreBootstrap = (_, pluginOptions) => { +exports.onPreBootstrap = ({ actions }, pluginOptions) => { setOptions(pluginOptions) + + if (typeof actions?.addRemoteFileAllowedUrl === `function`) { + actions.addRemoteFileAllowedUrl(urlJoin(pluginOptions.baseUrl, `*`)) + } } exports.sourceNodes = async ( diff --git a/packages/gatsby-source-wordpress/src/gatsby-node.ts b/packages/gatsby-source-wordpress/src/gatsby-node.ts index a14f388f84c02..4c6c62f21bf98 100644 --- a/packages/gatsby-source-wordpress/src/gatsby-node.ts +++ b/packages/gatsby-source-wordpress/src/gatsby-node.ts @@ -24,6 +24,7 @@ exports.createSchemaCustomization = runApiSteps( steps.ensurePluginRequirementsAreMet, steps.ingestRemoteSchema, steps.createSchemaCustomization, + steps.addRemoteFileAllowedUrl, ], `createSchemaCustomization` ) diff --git a/packages/gatsby-source-wordpress/src/steps/add-remote-file-allowed-url.ts b/packages/gatsby-source-wordpress/src/steps/add-remote-file-allowed-url.ts new file mode 100644 index 0000000000000..249a01827e041 --- /dev/null +++ b/packages/gatsby-source-wordpress/src/steps/add-remote-file-allowed-url.ts @@ -0,0 +1,21 @@ +import nodePath from "path" +import { getStore } from "~/store" + +import type { Step } from "~/utils/run-steps" + +export const addRemoteFileAllowedUrl: Step = ({ actions }): void => { + if (typeof actions?.addRemoteFileAllowedUrl !== `function`) { + return + } + + const { wpUrl } = getStore().getState().remoteSchema + + if (!wpUrl) { + return + } + + const wordpressUrl = new URL(wpUrl) + wordpressUrl.pathname = nodePath.posix.join(wordpressUrl.pathname, `*`) + + actions.addRemoteFileAllowedUrl(wordpressUrl.href) +} diff --git a/packages/gatsby-source-wordpress/src/steps/index.ts b/packages/gatsby-source-wordpress/src/steps/index.ts index 7f3845abd5510..e0bfdec0a1c24 100644 --- a/packages/gatsby-source-wordpress/src/steps/index.ts +++ b/packages/gatsby-source-wordpress/src/steps/index.ts @@ -21,6 +21,7 @@ export { logPostBuildWarnings } from "~/steps/log-post-build-warnings" export { imageRoutes } from "~/steps/image-routes" export { setRequestHeaders } from "./set-request-headers" +export { addRemoteFileAllowedUrl } from "./add-remote-file-allowed-url" export { hideAuthPluginOptions, diff --git a/packages/gatsby/index.d.ts b/packages/gatsby/index.d.ts index c95953df30f8f..6ef0ef1a31c02 100644 --- a/packages/gatsby/index.d.ts +++ b/packages/gatsby/index.d.ts @@ -50,6 +50,7 @@ export { ImageCdnTransformArgs, FileCdnUrlGeneratorFn, FileCdnSourceImage, + RemoteFileAllowedUrls, } from "./dist/utils/adapter/types" export const useScrollRestoration: (key: string) => { @@ -1518,7 +1519,15 @@ export interface Actions { /** * Marks the source plugin that called this function as stateful. Gatsby will not check for stale nodes for any plugin that calls this. */ - enableStatefulSourceNodes?(this: void, plugin?: ActionPlugin) + enableStatefulSourceNodes?(this: void, plugin?: ActionPlugin): void + + /** @see https://www.gatsbyjs.com/docs/actions/#addRemoteFileAllowedUrl */ + addRemoteFileAllowedUrl?( + this: void, + url: string | Array, + plugin?: ActionPlugin, + traceId?: string + ): void } export interface Store { diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index 617962f238521..725aeaca54084 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -137,6 +137,7 @@ "opentracing": "^0.14.7", "p-defer": "^3.0.0", "parseurl": "^1.3.3", + "path-to-regexp": "0.1.7", "physical-cpu-count": "^2.0.0", "platform": "^1.3.6", "postcss": "^8.4.24", diff --git a/packages/gatsby/src/redux/actions/restricted.ts b/packages/gatsby/src/redux/actions/restricted.ts index d74000d2977a5..0764b763f8010 100644 --- a/packages/gatsby/src/redux/actions/restricted.ts +++ b/packages/gatsby/src/redux/actions/restricted.ts @@ -22,6 +22,7 @@ import { ICreateResolverContext, IGatsbyPluginContext, ICreateSliceAction, + IAddImageCdnAllowedUrl, } from "../types" import { generateComponentChunkName } from "../../utils/js-chunk-names" import { store } from "../index" @@ -36,6 +37,7 @@ type RestrictionActionNames = | "addThirdPartySchema" | "printTypeDefinitions" | "createSlice" + | "addRemoteFileAllowedUrl" type SomeActionCreator = | ActionCreator @@ -533,6 +535,31 @@ export const actions = { throw new Error(`createSlice is only available in Gatsby v5`) } }, + /** + * Declares URL Pattern that should be allowed to be used for Image or File CDN to prevent using of unexpected RemoteFile URLs. + * + * @availableIn [onPreInit, onPreBootstrap, onPluginInit, createSchemaCustomization] + * + * @param {string | string []} url URLPattern or Array of URL Patternss that should be allowed. + * URLPattern is a string that can contain wildcards (*) or parameter placeholders (e.g. :id). + * @example + * exports.onPreInit = ({ actions }) => { + * actions.addRemoteFileAllowedUrl(`https://your-wordpress-instance.com/*`) + * } + */ + addRemoteFileAllowedUrl: ( + url: string | Array, + plugin: IGatsbyPlugin, + traceId?: string + ): IAddImageCdnAllowedUrl => { + const urls = Array.isArray(url) ? url : [url] + return { + type: `ADD_REMOTE_FILE_ALLOWED_URL`, + payload: { urls }, + plugin, + traceId, + } + }, } const withDeprecationWarning = @@ -656,4 +683,12 @@ export const availableActionsByAPI = mapAvailableActionsToAPIs({ createSlice: { [ALLOWED_IN]: [`createPages`], }, + addRemoteFileAllowedUrl: { + [ALLOWED_IN]: [ + `onPreInit`, + `onPreBootstrap`, + `onPluginInit`, + `createSchemaCustomization`, + ], + }, }) diff --git a/packages/gatsby/src/redux/reducers/index.ts b/packages/gatsby/src/redux/reducers/index.ts index 54e4ef76e47ed..e2b394a5de986 100644 --- a/packages/gatsby/src/redux/reducers/index.ts +++ b/packages/gatsby/src/redux/reducers/index.ts @@ -38,6 +38,7 @@ import { slicesReducer } from "./slices" import { componentsUsingSlicesReducer } from "./components-using-slices" import { slicesByTemplateReducer } from "./slices-by-template" import { adapterReducer } from "./adapter" +import { remoteFileAllowedUrlsReducer } from "./remote-file-allowed-urls" /** * @property exports.nodesTouched Set @@ -83,4 +84,5 @@ export { slicesByTemplateReducer as slicesByTemplate, telemetryReducer as telemetry, adapterReducer as adapter, + remoteFileAllowedUrlsReducer as remoteFileAllowedUrls, } diff --git a/packages/gatsby/src/redux/reducers/remote-file-allowed-urls.ts b/packages/gatsby/src/redux/reducers/remote-file-allowed-urls.ts new file mode 100644 index 0000000000000..b076cdea80642 --- /dev/null +++ b/packages/gatsby/src/redux/reducers/remote-file-allowed-urls.ts @@ -0,0 +1,18 @@ +import { IGatsbyState, ActionsUnion } from "../types" + +export const remoteFileAllowedUrlsReducer = ( + state: IGatsbyState["remoteFileAllowedUrls"] = new Set(), + action: ActionsUnion +): IGatsbyState["remoteFileAllowedUrls"] => { + switch (action.type) { + case `ADD_REMOTE_FILE_ALLOWED_URL`: { + for (const url of action.payload.urls) { + state.add(url) + } + + return state + } + default: + return state + } +} diff --git a/packages/gatsby/src/redux/types.ts b/packages/gatsby/src/redux/types.ts index 01c409da25475..44e8abaafcfa2 100644 --- a/packages/gatsby/src/redux/types.ts +++ b/packages/gatsby/src/redux/types.ts @@ -425,6 +425,7 @@ export interface IGatsbyState { manager: IAdapterManager config: IAdapterFinalConfig } + remoteFileAllowedUrls: Set } export type GatsbyStateKeys = keyof IGatsbyState @@ -539,6 +540,7 @@ export type ActionsUnion = | IClearGatsbyImageSourceUrlAction | ISetAdapterAction | IDisablePluginsByNameAction + | IAddImageCdnAllowedUrl export interface IInitAction { type: `INIT` @@ -1218,6 +1220,15 @@ export interface IDisablePluginsByNameAction { } } +export interface IAddImageCdnAllowedUrl { + type: `ADD_REMOTE_FILE_ALLOWED_URL` + payload: { + urls: Array + } + plugin: IGatsbyPlugin + traceId?: string +} + export interface ITelemetry { gatsbyImageSourceUrls: Set } diff --git a/packages/gatsby/src/utils/adapter/manager.ts b/packages/gatsby/src/utils/adapter/manager.ts index 8e97c6c737ae7..fbe10be215dd0 100644 --- a/packages/gatsby/src/utils/adapter/manager.ts +++ b/packages/gatsby/src/utils/adapter/manager.ts @@ -7,6 +7,7 @@ import { posix } from "path" import { sync as globSync } from "glob" import telemetry from "gatsby-telemetry" import { copy, pathExists, unlink } from "fs-extra" +import pathToRegexp from "path-to-regexp" import type { FunctionsManifest, IAdaptContext, @@ -18,6 +19,7 @@ import type { IAdapterFinalConfig, IAdapterConfig, HeaderRoutes, + RemoteFileAllowedUrls, } from "./types" import { store, readState } from "../../redux" import { getPageMode } from "../page-mode" @@ -204,6 +206,7 @@ export async function initAdapterManager(): Promise { let _routesManifest: RoutesManifest | undefined = undefined let _functionsManifest: FunctionsManifest | undefined = undefined let _headerRoutes: HeaderRoutes | undefined = undefined + let _imageCdnAllowedUrls: RemoteFileAllowedUrls | undefined = undefined const adaptContext: IAdaptContext = { get routesManifest(): RoutesManifest { if (!_routesManifest) { @@ -230,6 +233,20 @@ export async function initAdapterManager(): Promise { return _headerRoutes }, + get remoteFileAllowedUrls(): RemoteFileAllowedUrls { + if (!_imageCdnAllowedUrls) { + _imageCdnAllowedUrls = Array.from( + store.getState().remoteFileAllowedUrls + ).map(urlPattern => { + return { + urlPattern, + regexSource: pathToRegexp(urlPattern).source, + } + }) + } + + return _imageCdnAllowedUrls + }, reporter, // Our internal Gatsby config allows this to be undefined but for the adapter we should always pass through the default values and correctly show this in the TypeScript types trailingSlash: trailingSlash as TrailingSlash, diff --git a/packages/gatsby/src/utils/adapter/types.ts b/packages/gatsby/src/utils/adapter/types.ts index d5f7b8d1a617b..c22e15019c5d1 100644 --- a/packages/gatsby/src/utils/adapter/types.ts +++ b/packages/gatsby/src/utils/adapter/types.ts @@ -117,6 +117,17 @@ interface IDefaultContext { reporter: typeof reporter } +export type RemoteFileAllowedUrls = Array<{ + /** + * Allowed url in URLPattern format. In particular it uses wildcard `*` and param `:param` syntax. + */ + urlPattern: string + /** + *Allowed url in regex source format + */ + regexSource: string +}> + export interface IAdaptContext extends IDefaultContext { routesManifest: RoutesManifest functionsManifest: FunctionsManifest @@ -129,6 +140,12 @@ export interface IAdaptContext extends IDefaultContext { * @see https://www.gatsbyjs.com/docs/reference/config-files/gatsby-config/#trailingslash */ trailingSlash: TrailingSlash + /** + * List of allowed remote file URLs represented in URLPattern and Regex formats. + * Allowed urls are provided by user or plugins using `addRemoteFileAllowedUrl` action. + * @see https://www.gatsbyjs.com/docs/reference/config-files/actions/#addRemoteFileAllowedUrl + */ + remoteFileAllowedUrls: RemoteFileAllowedUrls } export interface ICacheContext extends IDefaultContext { diff --git a/yarn.lock b/yarn.lock index edca74a7eaf04..9604f412e782f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3262,6 +3262,36 @@ path-exists "^5.0.0" readdirp "^3.4.0" +"@netlify/config@^20.10.0": + version "20.10.0" + resolved "https://registry.yarnpkg.com/@netlify/config/-/config-20.10.0.tgz#df51f277c7eaa984105f4e90c3ea676b935c5df3" + integrity sha512-7CNoL5IPSRBzDVzxuQgltZ71D/vZ/oYR29sfN8EXjAFOZPSLtnZgborcPa9V9BXLN4N5h0hFp2A26lnnCttEFg== + dependencies: + chalk "^5.0.0" + cron-parser "^4.1.0" + deepmerge "^4.2.2" + dot-prop "^7.0.0" + execa "^6.0.0" + fast-safe-stringify "^2.0.7" + figures "^5.0.0" + filter-obj "^5.0.0" + find-up "^6.0.0" + indent-string "^5.0.0" + is-plain-obj "^4.0.0" + js-yaml "^4.0.0" + map-obj "^5.0.0" + netlify "^13.1.11" + netlify-headers-parser "^7.1.2" + netlify-redirect-parser "^14.2.0" + node-fetch "^3.3.1" + omit.js "^2.0.2" + p-locate "^6.0.0" + path-type "^5.0.0" + toml "^3.0.0" + tomlify-j0.4 "^3.0.0" + validate-npm-package-name "^4.0.0" + yargs "^17.6.0" + "@netlify/edge-functions@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@netlify/edge-functions/-/edge-functions-2.2.0.tgz#5f7f5c7602a7f98888a4b4421576ca609dad2083" @@ -3274,6 +3304,11 @@ dependencies: is-promise "^4.0.0" +"@netlify/open-api@^2.26.0": + version "2.26.0" + resolved "https://registry.yarnpkg.com/@netlify/open-api/-/open-api-2.26.0.tgz#cdc8033371079955501f4b9a5323f2dcd76741c2" + integrity sha512-B7q+ySzQm6rJhaGbY0Pzqnb1p3FsBqwiPLnLtA17JgTsqmXgQ7j6OQImW9fRJy/Al1ob9M6Oxng/FA2c7aIW1g== + "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": version "2.1.8-no-fsevents.3" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" @@ -7165,6 +7200,13 @@ builtins@^2.0.0: dependencies: semver "^6.0.0" +builtins@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9" + integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== + dependencies: + semver "^7.0.0" + busboy@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -7531,6 +7573,11 @@ chalk@^4.0, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.0.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + change-case-all@1.0.14: version "1.0.14" resolved "https://registry.yarnpkg.com/change-case-all/-/change-case-all-1.0.14.tgz#bac04da08ad143278d0ac3dda7eccd39280bfba1" @@ -8765,6 +8812,13 @@ createerror@1.3.0, createerror@^1.2.0, createerror@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/createerror/-/createerror-1.3.0.tgz#c666bd4cd6b94e35415396569d4649dd0cdb3313" +cron-parser@^4.1.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.9.0.tgz#0340694af3e46a0894978c6f52a6dbb5c0f11ad5" + integrity sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q== + dependencies: + luxon "^3.2.1" + cross-env@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" @@ -9288,6 +9342,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + data-urls@^1.0.0, data-urls@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" @@ -10028,6 +10087,13 @@ dot-prop@^5.1.0, dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" +dot-prop@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-7.2.0.tgz#468172a3529779814d21a779c1ba2f6d76609809" + integrity sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA== + dependencies: + type-fest "^2.11.2" + dotenv-expand@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" @@ -10420,7 +10486,7 @@ escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" -escape-string-regexp@5.0.0: +escape-string-regexp@5.0.0, escape-string-regexp@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== @@ -11032,6 +11098,21 @@ execa@^5.0.0, execa@^5.1.1: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +execa@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-6.1.0.tgz#cea16dee211ff011246556388effa0818394fb20" + integrity sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^3.0.1" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + execall@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45" @@ -11280,7 +11361,7 @@ fast-redact@^3.0.0: resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa" integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw== -fast-safe-stringify@2.1.1: +fast-safe-stringify@2.1.1, fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== @@ -11337,6 +11418,14 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" @@ -11361,6 +11450,14 @@ figures@^3.0.0, figures@^3.1.0, figures@^3.2.0: dependencies: escape-string-regexp "^1.0.5" +figures@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-5.0.0.tgz#126cd055052dea699f8a54e8c9450e6ecfc44d5f" + integrity sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg== + dependencies: + escape-string-regexp "^5.0.0" + is-unicode-supported "^1.2.0" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -11456,6 +11553,11 @@ filter-obj@^1.1.0: resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs= +filter-obj@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-5.1.0.tgz#5bd89676000a713d7db2e197f660274428e524ed" + integrity sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng== + finalhandler@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" @@ -11534,6 +11636,14 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" + integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== + dependencies: + locate-path "^7.1.0" + path-exists "^5.0.0" + find-yarn-workspace-root@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" @@ -11731,6 +11841,13 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -13278,6 +13395,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +human-signals@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-3.0.1.tgz#c740920859dafa50e5a3222da9d3bf4bb0e5eef5" + integrity sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ== + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -14209,6 +14331,11 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -14256,6 +14383,11 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-unicode-supported@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" + integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== + is-upper-case@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-2.0.2.tgz#f1105ced1fe4de906a5f39553e7d3803fd804649" @@ -14911,7 +15043,7 @@ js-levenshtein@^1.1.6: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" -js-yaml@4.1.0, js-yaml@^4.1.0: +js-yaml@4.1.0, js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -15641,7 +15773,7 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -locate-path@^7.0.0: +locate-path@^7.0.0, locate-path@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== @@ -16035,6 +16167,11 @@ lru-queue@^0.1.0: dependencies: es5-ext "~0.10.2" +luxon@^3.2.1: + version "3.4.4" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.4.tgz#cf20dc27dc532ba41a169c43fdcc0063601577af" + integrity sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA== + lz-string@^1.4.4, lz-string@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" @@ -16127,6 +16264,11 @@ map-obj@^4.0.0, map-obj@^4.1.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== +map-obj@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-5.0.2.tgz#174ad9f7e5e4e777a219126d9a734ff3e14a1c68" + integrity sha512-K6K2NgKnTXimT3779/4KxSvobxOtMmx1LBZ3NwRxT/MDIR3Br/fQ4Q+WCX5QxjyUR8zg5+RV9Tbf2c5pAWTD2A== + map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" @@ -16693,6 +16835,11 @@ methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" +micro-api-client@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/micro-api-client/-/micro-api-client-3.3.0.tgz#52dd567d322f10faffe63d19d4feeac4e4ffd215" + integrity sha512-y0y6CUB9RLVsy3kfgayU28746QrNMpSm9O/AYGNsBgOkJr/X/Jk0VLGoO8Ude7Bpa8adywzF+MzXNZRFRsNPhg== + microbundle@^0.15.0, microbundle@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/microbundle/-/microbundle-0.15.1.tgz#3fa67128934b31736823b5c868dae4b92d94e766" @@ -17170,6 +17317,11 @@ mimic-fn@^3.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" @@ -17575,11 +17727,47 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug== +netlify-headers-parser@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/netlify-headers-parser/-/netlify-headers-parser-7.1.2.tgz#5b2f76e030eb8ba423c370c4e4814ddcc9c65e3b" + integrity sha512-DfoboA8PrcLXMan3jIVyLsQtKS+nepKDx6WwZKk5EQDMr2AJoBPCtSHTOLuABzkde1UXdOITf3snmcAmzlNLqw== + dependencies: + escape-string-regexp "^5.0.0" + fast-safe-stringify "^2.0.7" + is-plain-obj "^4.0.0" + map-obj "^5.0.0" + path-exists "^5.0.0" + toml "^3.0.0" + netlify-identity-widget@^1.9.2: version "1.9.2" resolved "https://registry.yarnpkg.com/netlify-identity-widget/-/netlify-identity-widget-1.9.2.tgz#4339c9155fc4c2570ae3ddd61825d952b574b02e" integrity sha512-IbS1JHhs7BflCCvp3C9f6tmNSZqbyBhZ4Gs5+Qxt4IlPybTOVv0PqJ4TAsA7uxh1R+oXOAmk0OOMAkEaPYeCtA== +netlify-redirect-parser@^14.2.0: + version "14.2.0" + resolved "https://registry.yarnpkg.com/netlify-redirect-parser/-/netlify-redirect-parser-14.2.0.tgz#8da1b911b43ea51e0c5fa5dd1401157d1301a8f5" + integrity sha512-3Mi7sMH7XXZhjvXx/5RtJ/rU/E6zKkE4etcYQbEu8B3r872D0opoYyGdPW/MvaYQyVdfg23XEFaEI4zzQTupaw== + dependencies: + fast-safe-stringify "^2.1.1" + filter-obj "^5.0.0" + is-plain-obj "^4.0.0" + path-exists "^5.0.0" + toml "^3.0.0" + +netlify@^13.1.11: + version "13.1.11" + resolved "https://registry.yarnpkg.com/netlify/-/netlify-13.1.11.tgz#f5151bbd5e05cd5a67713f89c05a57dd6377b599" + integrity sha512-exrD6cqwo5avDNtU7YT9iuN0+yoW+aaEUxvr/39oP36wZRKreoPm6KNVisTR9d4lXrPeUG8XI+rERuLhwMQmdw== + dependencies: + "@netlify/open-api" "^2.26.0" + lodash-es "^4.17.21" + micro-api-client "^3.3.0" + node-fetch "^3.0.0" + omit.js "^2.0.2" + p-wait-for "^4.0.0" + qs "^6.9.6" + next-tick@1, next-tick@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" @@ -17654,6 +17842,11 @@ node-dir@^0.1.10, node-dir@^0.1.17: dependencies: minimatch "^3.0.2" +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-environment-flags@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" @@ -17692,6 +17885,15 @@ node-fetch@^2.5.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.11, nod dependencies: whatwg-url "^5.0.0" +node-fetch@^3.0.0, node-fetch@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-gyp-build-optional-packages@5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.3.tgz#92a89d400352c44ad3975010368072b41ad66c17" @@ -17934,6 +18136,13 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -18096,6 +18305,11 @@ octokit-pagination-methods@^1.1.0: resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== +omit.js@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/omit.js/-/omit.js-2.0.2.tgz#dd9b8436fab947a5f3ff214cb2538631e313ec2f" + integrity sha512-hJmu9D+bNB40YpL9jYebQl4lsTW6yEHRTroJzNLqQJYHm7c+NQnJGfZmIWh8S3q3KoaxV1aLhV6B3+0N0/kyJg== + on-exit-leak-free@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" @@ -18132,6 +18346,13 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + open@^7.0.3: version "7.3.1" resolved "https://registry.yarnpkg.com/open/-/open-7.3.1.tgz#111119cb919ca1acd988f49685c4fdd0f4755356" @@ -18442,6 +18663,11 @@ p-timeout@^3.1.0, p-timeout@^3.2.0: dependencies: p-finally "^1.0.0" +p-timeout@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-5.1.0.tgz#b3c691cf4415138ce2d9cfe071dba11f0fee085b" + integrity sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew== + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -18451,6 +18677,13 @@ p-try@^2.0.0, p-try@^2.1.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +p-wait-for@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-wait-for/-/p-wait-for-4.1.0.tgz#290f126f49bbd7c84e0cedccb342cd631aaa0f16" + integrity sha512-i8nE5q++9h8oaQHWltS1Tnnv4IoMDOlqN7C0KFG2OdbK0iFJIt6CROZ8wfBM+K4Pxqfnq4C4lkkpXqTEpB5DZw== + dependencies: + p-timeout "^5.0.0" + p-waterfall@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-waterfall/-/p-waterfall-1.0.0.tgz#7ed94b3ceb3332782353af6aae11aa9fc235bb00" @@ -18773,6 +19006,11 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -18830,6 +19068,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +path-type@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-5.0.0.tgz#14b01ed7aea7ddf9c7c3f46181d4d04f9c785bb8" + integrity sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg== + pause-stream@0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" @@ -20109,7 +20352,7 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" -qs@^6.1.0, qs@^6.11.0, qs@^6.4.0, qs@^6.5.2, qs@^6.9.4: +qs@^6.1.0, qs@^6.11.0, qs@^6.4.0, qs@^6.5.2, qs@^6.9.4, qs@^6.9.6: version "6.11.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== @@ -21749,6 +21992,13 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.0.0, semver@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + semver@^7.1.1, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" @@ -21756,13 +22006,6 @@ semver@^7.1.1, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semve dependencies: lru-cache "^6.0.0" -semver@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -22768,6 +23011,11 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" @@ -23544,6 +23792,16 @@ toml@^2.3.2, toml@^2.3.6: resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.6.tgz#25b0866483a9722474895559088b436fd11f861b" integrity sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ== +toml@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" + integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== + +tomlify-j0.4@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tomlify-j0.4/-/tomlify-j0.4-3.0.0.tgz#99414d45268c3a3b8bf38be82145b7bba34b7473" + integrity sha512-2Ulkc8T7mXJ2l0W476YC/A209PR38Nw8PuaCNtk9uI3t1zzFdGQeWYGQvmj2PZkVvRC/Yoi4xQKMRnWc/N29tQ== + topo@3.x.x: version "3.0.3" resolved "https://registry.yarnpkg.com/topo/-/topo-3.0.3.tgz#d5a67fb2e69307ebeeb08402ec2a2a6f5f7ad95c" @@ -23801,7 +24059,7 @@ type-fest@^1.0.1, type-fest@^1.2.1, type-fest@^1.2.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== -type-fest@^2.19.0: +type-fest@^2.11.2, type-fest@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== @@ -24579,6 +24837,13 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" +validate-npm-package-name@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz#fe8f1c50ac20afdb86f177da85b3600f0ac0d747" + integrity sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q== + dependencies: + builtins "^5.0.0" + validator@13.9.0: version "13.9.0" resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855" @@ -24891,6 +25156,11 @@ web-namespaces@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.2.tgz#c8dc267ab639505276bae19e129dbd6ae72b22b4" +web-streams-polyfill@^3.0.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + web-vitals@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-1.1.2.tgz#06535308168986096239aa84716e68b4c6ae6d1c" @@ -25665,6 +25935,19 @@ yargs@^17.2.1, yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.1.1" +yargs@^17.6.0: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"