From 081add4abf7bc096f7f9363550c4caabf05fe607 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Mon, 3 Aug 2020 13:15:28 -0700 Subject: [PATCH] feat(gatsby-recipes): add recipes gui (#24595) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(gatsby-recipes): Pass data retrieved from the resource to its children via context * chore(gatsby-recipes): Swap out Promise.all for a true queue * feat(gatsby-recipes): Implement a render loop for nested resources * Continue spiking out recipes gui * Hardcode the project root in a clear place for now * Join plan steps in order to create entire recipe plan at once + initial efforts on GUI * WIP * feat(gatsby-recipes): Implement a wait for input state when props are missing for a resource * chore(gatsby-recipes): Use an INVALID_PROP event for schema validation * feat(gatsby-recipes): Wrap intro and each step with components, add metadata * chore(gatsby-recipes): Spike out basic gui component for steps * feat(gatsby-recipes): Pass data retrieved from the resource to its children via context * chore(gatsby-recipes): Swap out Promise.all for a true queue * feat(gatsby-recipes): Implement a render loop for nested resources * Continue spiking out recipes gui * Hardcode the project root in a clear place for now * Join plan steps in order to create entire recipe plan at once + initial efforts on GUI * WIP * feat(gatsby-recipes): Implement a wait for input state when props are missing for a resource * chore(gatsby-recipes): Use an INVALID_PROP event for schema validation * feat(gatsby-recipes): Wrap intro and each step with components, add metadata * chore(gatsby-recipes): Spike out basic gui component for steps * Lots of styling changes * Put text & resources in same steps * Lots more styling tweaks * paragraphs had too much margin bottom * more style tweaks * feat(gatsby-recipes): Implement a wait for input state when props are missing for a resource Also adds the use of an INVALID_PROP event for schema validation. * chore(gatsby-recipes): Use MDX v2 canary for access to the JSX AST * feat(gatsby-recipes): Apply a UUID prop to all resources for input handling * checkin: Begin wiring up event for passing input data to server * fix(gatsby-recipes): Update step wrapping for MDX v2 * fix(gatsby-recipes): Get tests passing, add debugging output * Get applying working * PROGRESSSSS * feat(gatsby-recipes): Allow for inputs based on uuid to override props * Remove sleep * style tweaks * Add updater to input provider, spike out File form * feat(gatsby-recipes): Implement basic input functionality * feat(gatsby-recipes): Spike out a contentful space resource, use renderer for applying plan * feat(gatsby-recipes): Spike out contentful provider and basic rendering (#24655) * feat(gatsby-recipes): Spike out contentful provider and basic rendering * Update packages/gatsby-recipes/src/gui.js * WIP * More design tweaks * Style inline code * Update packages/gatsby-recipes/recipes/cypress.mdx Co-authored-by: Marcy Sutton * Update packages/gatsby-recipes/recipes/cypress.mdx Co-authored-by: Marcy Sutton * Update packages/gatsby-recipes/recipes/cypress.mdx Co-authored-by: Marcy Sutton * feat(gatsby-recipes): fix MDX rendering for exports (#25133) * feat(gatsby-recipes): Handle exports, render MDX directly * Continue working towards proper exports * Continue implementing MDX renderer v2 * More MDX rendering hacking * Finish basic export handling * Small fixes Co-authored-by: John Otander * live updating is working more-or-less * Speedups & cleanups * Rename hook to match signature * Rename context * Add support for useResourceByKey * fix @babel/template not accepting integers as options * Only update resources when it's changed * make child Resource components work * rename useResourceByKey -> useResource * Implement ContentfulEntry resource * Add useProvider & ensure only apply resource once * Address some design feedback * Fix spacing for input forms * Fix spacing and size of step indicator * Flatten nested resources in display * Use input builtins from gatsby-interface * Add special file diff * Get things running again * Reload recipe session on changes - when the recipe file is updated - when the recipe api is restarted - when the browser is refreshed. * Update tests * Only emit updates when the state has actually changed * Fix building recipe component * update resolutions/dependencies * fix fetch dependency * moer fixes * Upgrade to Ink v3 & start migrating cli to showing all steps * Properly handle nested resources when rendering the plan (#25930) * Don't hardcode port * Ensure that nested resource get resourceName populated * feat(gatsby-recipes): Refactor CLI UI for new one-shot show plan (#25939) * feat(gatsby-recipes): Refactor CLI UI for new one-shot show plan * Restore experimental message + showing list of recipes to run * Add a --develop command for hot-reloading of recipes * Add --install command support * Remove unused code + old pre Ink v3 logging system * Cleanup + show step count * Remove console.log * add key * small fixes + add script to start dev server * Add dev instructions for running the recipes graphql server in the foreground * small fixes * @babel/standalone caches transforms unless you delete the require cache * fix linting problems * Extract shared code into common library * Checkin useInput beginning * Ensure that diff html isn't rendered by escaping * Update providers snapshots, looked like they weren't run with chalk turned off * Update other snapshots as well * Begin fixing some lint errors * Fix some more lint errors * Fix grabbing the right resource Co-authored-by: John Otander * move back to v2 for deploying for compatability with the regular CLI * Also do a compatability layer for * test * Add missing dependency * sad * Add rollup to bundle the cli app so we can use Ink v3 * Move packages packed by rollup to be dev dependencies as user won't need to download them * Remove console.logs * Remove logs * feat(gatsby-recipes): copy edits for some recipes (#26009) * Fix rendering li > p * Fix formatting of emotion recipe * Improve recipe * Name of key changed * Match keyed resources correctly in the install step + cleanups * Fix linting errors * fix margin * Surround inlineCode with back ticks so it looks like markdown * vendor ink-link as it's not upgraded to v3 yet * feat(gatsby-recipes) (#26085) * prettier file * Fix linting errors * feat(gatsby-recipes): fix recipes copy 2 (#26115) * feat(gatsby-recipes) * second half of copy edits donezo! * feat(gatsby-source-shopify): Add shopifyShop query (#25763) * Start moving gatsby-telemetry to typescript (#25812) * Fix camelCase * Start moving gatsby-telemetry to ts * Continue converting base to typescript * Debug transpilation issues * Debug transpilation issues * Fix telemetry tests * Add Changelog entry for merged PR #24306 * chore(gatsby-telemetry): Migrate is-truthy to TypeScript (#25884) * Detect vercel again after rebranding in gatsby-telemetry (#25883) * Detect vercel again after rebranding as per https://vercel.com/docs/v2/build-step * Add another Vercel NOW matcher * chore(gatsby-telemetry): Migrate flush to TypeScript (#25886) * feat(gatsby-source-shopify): set link from product variant to product (#25316) * fix: update www (#25874) Co-authored-by: Renovate Bot * docs(gatsby-internals): update page -> node dependency tracking (#25606) * docs(gatsby-internals): update page -> node dependency tracking * Apply suggestions from code review Co-authored-by: Aisha Blake * remove surplus `and` from performance comma list (#25891) * fixed typo (#25896) * fix(gatsby): Support symlinks in static directories (#25894) * Added the link to 'MDX' (#25905) * Update localization-i18n.md (#25902) Some important links for **React-intl** had broken due to update in repo whose links were given. Added the correct links to it. * added a cookieflags option (#25907) Co-authored-by: Thijs van Diessen * fix(readme): gatsby-source-shopify: unify variable names (#25882) * chore(showcase): Add MongoDB Developer Hub (#25892) * Add file names to code blocks (#25879) * enhancement(docs): dictionary.txt -> CodePen -> fix brand name (#25875) * feat(gatsby-admin): list all pages of site (#25744) * feat(gatsby-admin): plugin search (#25903) * Copy plugin search from www into admin * Move to Combobox search * Cleanup * TypeScript cleanup * add algolia types * Fix syntax * fix: Restore CLI port in use prompt feature (#25863) * fix: Restore CLI port in use prompt feature Seems like it got accidentally removed during a big PR? * fix: Ensure port var types are the same The CLI option and default value for `port` is a string, despite the TypeScript typing the arg to `number`. Unclear if `port` should be a `number` elsewhere, so checking for and converting to a number within the utility. * Fix/follow up 25863 (#25915) * fix: Restore CLI port in use prompt feature Seems like it got accidentally removed during a big PR? * fix: Ensure port var types are the same The CLI option and default value for `port` is a string, despite the TypeScript typing the arg to `number`. Unclear if `port` should be a `number` elsewhere, so checking for and converting to a number within the utility. * Force program.port to a number early Co-authored-by: polarathene <5098581+polarathene@users.noreply.github.com> * chore(release): Publish - babel-preset-gatsby@0.5.3 - gatsby-admin@0.1.97 - gatsby-cli@2.12.64 - gatsby-core-utils@1.3.13 - gatsby-page-utils@0.2.18 - gatsby-plugin-google-analytics@2.3.13 - gatsby-plugin-manifest@2.4.20 - gatsby-plugin-mdx@1.2.28 - gatsby-plugin-offline@3.2.20 - gatsby-plugin-page-creator@2.3.18 - gatsby-plugin-preload-fonts@1.2.18 - gatsby-plugin-sharp@2.6.21 - gatsby-recipes@0.1.54 - gatsby-remark-images@3.3.20 - gatsby-source-contentful@2.3.29 - gatsby-source-drupal@3.5.24 - gatsby-source-filesystem@2.3.21 - gatsby-source-shopify@3.2.23 - gatsby-source-wordpress@3.3.24 - gatsby-telemetry@1.3.21 - gatsby-transformer-remark@2.8.26 - gatsby-transformer-sqip@2.3.21 - gatsby@2.24.8 * Capture repositoryId from heroku (#25910) * Capture repositoryId from heroku * Add comments * fixed typo (#25912) * Update README.md (#25901) No need to link to `example.com` it's a sample domain. * Add __BASE_PATH__ definition to storybook config (#25643) * Add __BASE_PATH__ definition to storybook config * Globals need not be defined for Storybook Docs Update to Docs: Removes the need to declare the `__BASE_PATH__` and `__PATH_PREFIX__` in the Storybook config for Tests to work * fix(gatsby): don't place virtual modules in node_modules directory (#25720) * fix(gatsby): don't place virtual modules in node_modules directory * fix eslint rule Co-authored-by: Ward Peeters * chore(doc):Add guide to Deploy Gatsby to DigitalOcean droplet. (#24652) * Added doc for deploying to digitalocean droplet Added doc for deploying gatsby site to digitalocean droplet and configuring domain name with SSL. For issue #24549 . * Updated with deploying to digitalocean droplet doc Updated with deploying to digitalocean droplet doc to fix issue #24549. * Added missing code language flag to fix lint check Lint Check failed due to one code language flag was missing in one of the code snippet in the md file. Fixed that. * Updated grammar and styles as per code review Co-authored-by: Marcy Sutton * Removed the line for brevity * Updated grammar change for line #11 as per code review * Ran prettier to format the code * Added step to install dependencies after cloning * Change case of node to Node as per suggestion. Co-authored-by: Marcy Sutton * Changing optional to required for installing version of Node Gatsby required Node 10, so making the use of n package while installing the Node on digitalocean as a REQUIRED step. Co-authored-by: Marcy Sutton * Adding suggested changes for better understanding. Co-authored-by: Marcy Sutton * Adding the suggested changes. Using "Generate your Gatsby site for production" instead of "Build your gatsby site to generate static site for production" Co-authored-by: Marcy Sutton * Making changes as per suggestion by moderator Making the docs style changes as suggested by moderator marcysutton Co-authored-by: Marcy Sutton * Making changes as per suggestion Co-authored-by: Marcy Sutton * Making changes as per the suggestion Co-authored-by: Marcy Sutton * Update docs/docs/deploying-to-digitalocean-droplet.md Co-authored-by: Marcy Sutton * Making changes as per the suggestion Adding path resemble line to make it easy for people to understand the path Co-authored-by: Marcy Sutton * Adding changes as per the suggestion Co-authored-by: Marcy Sutton * Making changes as per the suggestion Co-authored-by: Marcy Sutton * Added snippet to get rid of permission denied Added snippet to get rid of permission denied while cloning the repository * Adding indentation as per linting rules * Ran prettier * Updating grammar as per suggested Co-authored-by: Marcy Sutton * Added note to copy local repo path for future ref * Ran prettier to format the code Co-authored-by: Marcy Sutton * Update migrating-from-v1-to-v2.md (#25832) * fix dictionary for digitalocean guide (#25936) * fix(docs): show where `getNodesByType` comes from (#25344) * show where getNodesByType comes from * indicate the code is an example per PR feedback Co-authored-by: Marcy Sutton Co-authored-by: Marcy Sutton * chore(docs): Changes to "Setting Up Your Local Dev Environment" doc (#25721) * chore(gatsby): add log to gatsby develop if Admin is enabled (#25943) * feat(gatsby): Defer node mutation during querying (#25479) * Move bootstrap into machine * Add parent span and query extraction * Add rebuildSchemaWithSitePage * Use values from context * Remove logs * Add redirectListener * Changes from review * Log child state transitions * Add state machine for query running * Changes from review * Changes from review * Switch to reporter * Use assertStore * Remove unused action * Remove unusued config * Remove unusued config * Add gql runner reset * Handle node mutation queuing and batching in state machine * Use new pagedata utils * Use develop queue * New xstate syntax * Work-around xstate bug * Track first run * Track first run * Disable --quiet in e2e * Don't defer node mutation if we're outside the state machine * Re-quieten e2e * Listen for query file changes * Lint * Handle webhook * Changes from review * Fix typings * Changes from review * Typefix * feat(gatsby): Move final parts into develop state machine (#25716) * Move remaining parts into state machine * Move top level state machine into state machines dir * Add machine ids * Add missing imports * Resolve api promises * Remove unused action * Move logging into helper * Changes from review * Manually save db * Add comments * Remove first run from query running * Refactor into separate data layer machines * Fix condition Co-authored-by: gatsbybot * chore(release): Publish - gatsby-admin@0.1.98 - gatsby-cli@2.12.65 - gatsby-recipes@0.1.55 - gatsby-source-contentful@2.3.30 - gatsby-source-drupal@3.5.25 - gatsby-source-filesystem@2.3.22 - gatsby-source-shopify@3.2.24 - gatsby-source-wordpress@3.3.25 - gatsby-telemetry@1.3.22 - gatsby@2.24.9 * fix(docs): Fix broken mdx (#25946) * chore(gatsby-admin): build in postbuild of gatsby instead of prepublish (#25940) * Move admin to postbuild of gatsby * Remove prepublish gatsby-admin build * Dont run tests in .cache * Ignore _tests_ in .cache * Use local copy of Gatsby to build gatsby-admin * perf(gatsby-source-contentful): speed up resolving of huge spaces (#25954) closes #25464 * docs: use hello-world starter in quick start guide instead of default starter (#25914) * Small tweak to see if we can reduce errors driven by the default starter using and its dependency on sharp. * chore: format * Reverted working directory name A change to address feedback about changing the name to preserve continuity with current manual recipes. Co-authored-by: gatsbybot * chore(docs): Fix RFC typo (#25970) * chore(gatsby-admin): cleanup stale artifacts pre build (#25972) * Handle webpack in state machine (#25815) Co-authored-by: gatsbybot * chore(release): Publish - gatsby-admin@0.1.99 - gatsby-source-contentful@2.3.31 - gatsby@2.24.10 * fix(gatsby-admin): show error messages in the interface (#25944) * docs(gatsby-admin): more detailed architecture explanation (#25941) * Write more detailed Admin architecture docs * Add section on production deployment to gatsby-admin docs * Absolute URLs so they work on npm etc. * Fix pronouns and wording * Clean up some more * Tighten up language around production deployment Co-authored-by: Brent Jackson * Update packages/gatsby-admin/README.md Co-authored-by: Brent Jackson Co-authored-by: Brent Jackson * fix(gatsby): call predicate for the root ancestor in findRootNodeAncestor (#25974) * fix(gatsby-admin): small design tweaks (#25971) * feat(gatsby): Add internal types export (#25921) * Handle webpack in state machine * Add internal export * feat(plugin-manifest): support SVG favicon (#25276) Co-authored-by: Yogi * maintenance(www) remove unused dependencies (#25463) Co-authored-by: Aisha Blake * Update contributor-swag.md (#25980) Based on a recent increase in the volume of requests, I'm updating how people can request their free Gatsby swag for contributions that aren't made on GitHub. * feat(gatsby-source-filesystem): improve wrong url rejection message (#25965) * feat(gatsby-source-filesystem: improve wrong url rejection message The existing message made tracing down a bug from within the new WP source plugin harder than necessary. Old message: `wrong url: ${url}` Updated message: `url passed to createRemoteFileNode is either missing or not a proper web uri: ${url}` * chore: format * update rejects test to match new message Co-authored-by: gatsbybot * Also detect VERCEL_BUILDER should Vercel one day use it as per the docs (#25926) * fix(babel-preset-gatsby): enable transformer-regenerator (#25983) * fix(docs): bash to shell (#25958) * change bash to shell * dont change text file code language * chore: add tests to static-query filepaths (#25978) * chore: add tests to static-query filepaths * fix windows paths * chore(release): Publish - babel-preset-gatsby@0.5.4 - gatsby-admin@0.1.100 - gatsby-cli@2.12.66 - gatsby-core-utils@1.3.14 - gatsby-page-utils@0.2.19 - gatsby-plugin-manifest@2.4.21 - gatsby-plugin-mdx@1.2.29 - gatsby-plugin-offline@3.2.21 - gatsby-plugin-page-creator@2.3.19 - gatsby-plugin-preload-fonts@1.2.19 - gatsby-plugin-sharp@2.6.22 - gatsby-recipes@0.1.56 - gatsby-remark-images@3.3.21 - gatsby-source-contentful@2.3.32 - gatsby-source-drupal@3.5.26 - gatsby-source-filesystem@2.3.23 - gatsby-source-shopify@3.2.25 - gatsby-source-wordpress@3.3.26 - gatsby-telemetry@1.3.23 - gatsby-transformer-remark@2.8.27 - gatsby-transformer-sqip@2.3.22 - gatsby@2.24.11 * highlighted plugins (#25998) * Revert "perf(gatsby-plugin-mdx): drop another babel step during sourcing" (#26002) This reverts commit 6d0c791e73ddb832f74023983fdad4a67de76d98. * fix: Enable CLI integration tests (#25997) * [docs][glossary] add new entry for client-side rendering (#25984) * add new glossary entry for client-side routing * update text to address rendering vs. routing * Add link to page, rather than anchor Co-authored-by: Hashim Warren * fix: do not augment plugin-options (#26006) * fix(gatsby-recipes) Fix docs for name in NPMPackage * fix: update www (#26043) Co-authored-by: Renovate Bot * Added extra markup (#26030) * Added extra markup I found some js code which was not highlighted so I wrapped it in js code block, secondly, I added the link to reach/router as it was confusing if its react/router or reach/router * added the link to reach/router * Update glossary.md * chore(showcase): Add leanier.com site (#26016) * Add support for cache refresh via GraphiQL (#25960) * Add cache refresh button * Formatting * Explicit return type * www: Remove sw (#26054) * Docs: Add a warning about static queries (#25929) * feat(gatsby): Add top-level error handling to state machine (#25995) * chore: Update stale yarn.lock (#26068) * tests(gatsby): Add unit tests for develop state machine (#26051) * feat(gatsby): Add top-level error handling to state machine * Add initial tests * Add tests for top-level machine * Test error handling * Add post-bootstrap to tests * chore(showcase): Add johnkavanagh.co.uk (#25747) * chore(showcase): Minor changes Showcase Tatjana Volbeke Portfolio (#25613) * fix(gatsby): Defer node mutation in more APIs (#26067) * chore(release): Publish - gatsby-admin@0.1.101 - gatsby-cli@2.12.67 - gatsby-graphiql-explorer@0.4.12 - gatsby-plugin-mdx@1.2.30 - gatsby-plugin-sharp@2.6.23 - gatsby-recipes@0.1.57 - gatsby-remark-copy-linked-files@2.3.12 - gatsby-remark-images-contentful@2.3.12 - gatsby-remark-images@3.3.22 - gatsby-remark-responsive-iframe@2.4.12 - gatsby-source-contentful@2.3.33 - gatsby-transformer-sqip@2.3.23 - gatsby@2.24.12 * chore(showcase): add Julien Karst website (#25682) Co-authored-by: Obinna Ekwuno * chore(showcase): BRIKL & TRUE STORY in showcase (#25631) * chore(showcase): BRIKL & TRUE STORY in showcase * chore(showcase): run prettier sites.yml Co-authored-by: Obinna Ekwuno * chore(blog): Add i18n theme blog post (#26065) * add blog post * fix linting * put head in code tag lol * chore(showcase): add Château de Morey 🏰 (#25683) Co-authored-by: Obinna Ekwuno * chore(showcase): meetup.com (#25792) Co-authored-by: Obinna Ekwuno * chore(gatsby): fix typegen for publishing (#26078) * chore(gatsby): add typescript as dev dependency * chore(gatsby): run typegen after rimraf * fix(gatsby): Delete babel and terser cache dirs (#26053) * Delete babel and terser cache dirs * Clean up yarn lock * fix yarn.lock (?) * verbose gatsby-dev * chore(gatsby): add typescript as dev dependency * Update e2e-test.sh * chore(gatsby): run typegen after rimraf Co-authored-by: Michal Piechowiak Co-authored-by: gatsbybot * fix(gatsby): Load static query results from its own Db (#26077) * Load static query results from its own Db * Keep StaticQueryContext because it is public API * Switch to an Object for static query results from a Map * Move getStaticQueryResults to private API * chore(release): Publish - gatsby-admin@0.1.102 - gatsby@2.24.13 * fix(gatsby-image): add required check for one of fluid or fixed (#25371) * Do not crash the page if the image component is invoked without parameters * added a warning if missing fluid and fixed props * had swapped a condition * doing destructuring in function parameter list * now with functioning tree-shaking * updating function doc: returns undefined, not null * switching to proptypes for validation * Update packages/gatsby-image/src/index.js Co-authored-by: Andreas Ehrencrona Co-authored-by: Ward Peeters * fix(gatsby): Load resources in ProdPageRenderer (#26092) * Load resources in ProdPageRenderer * Add simple unit tests * chore(release): Publish - gatsby-admin@0.1.103 - gatsby-image@2.4.14 - gatsby@2.24.14 * Update gatsby in www * Add plugincreator to API (#26101) * Add plugincreator to API * fix capitlization Co-authored-by: Laurie Barth * chore(showcase): Add Devnet (#25952) Co-authored-by: Obinna Ekwuno * Add pluagin source for page (#26104) Co-authored-by: Laurie Barth * fix(gatsby-source-contentful): support height parameter for srcset (#25776) * Calculate fixed image width if necessary * Calculate fixed image width if necessary * Revert snapshot test changes * Bring back new test * Update snapshot * chore(docs): Add author Colby Fayock (#26109) * adding Colby Fayock author avatar and bio * Update author.yaml adding new line at end of file * pretier * Use commonmark option to better handle list parsing * revert fixpack changes to root package.json * Squashed commit of the following: commit 33aff39ede60a1d190f5c3d6798380f0971a5eaa Author: Kyle Mathews Date: Thu Jul 30 13:09:59 2020 -0700 Update index.md * Actually fix lint error * Fix test * more fixing tests * Only log when DEBUG=true * Remove --quiet to see errors * Add rollup * resolve conflicts * remove testing code * Make yarn.lock file valid * WORK PLEASE * Add yoga-layout-prebuilt as explicit dependency to make rollup + yarn 2.0 happy * Add node-fetch as dependency * Update packages/gatsby-recipes/src/graphql-server/server.js Co-authored-by: Peter van der Zee <209817+pvdz@users.noreply.github.com> * Use string matching for NPMPackage versions * Add missing string matcher * Fix lint error * Add missing normalize.css dep Co-authored-by: John Otander Co-authored-by: Marcy Sutton Co-authored-by: shannonbux <32467162+shannonbux@users.noreply.github.com> Co-authored-by: Paul Scanlon Co-authored-by: Jarmo Isotalo Co-authored-by: Blaine Kasten Co-authored-by: Johnny Zabala Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Renovate Bot Co-authored-by: Michal Piechowiak Co-authored-by: Aisha Blake Co-authored-by: Michael Murphy Co-authored-by: Dawood Sadiq Co-authored-by: James Brooks <52410024+jabrks@users.noreply.github.com> Co-authored-by: Haseeb Khan Co-authored-by: Ankit Ghosh <33004850+kaknut@users.noreply.github.com> Co-authored-by: Thijs Co-authored-by: Thijs van Diessen Co-authored-by: Muescha <184316+muescha@users.noreply.github.com> Co-authored-by: Jordan Stapinski Co-authored-by: Max Stoiber Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Co-authored-by: Nabeel Valley <36758308+nabeelvalley@users.noreply.github.com> Co-authored-by: Ward Peeters Co-authored-by: Vatsal Mistry Co-authored-by: Jack Co-authored-by: Kurt Tomlinson Co-authored-by: Lennart Co-authored-by: Matt Kane Co-authored-by: gatsbybot Co-authored-by: Benedikt Rötsch Co-authored-by: Joel Smith Co-authored-by: Brent Jackson Co-authored-by: Vladimir Razuvaev Co-authored-by: Alex Moon Co-authored-by: Yogi Co-authored-by: Nat Alison <1278991+tesseralis@users.noreply.github.com> Co-authored-by: Laci-Texter <46265213+Laci-Texter@users.noreply.github.com> Co-authored-by: Tyler Barnes Co-authored-by: LB Co-authored-by: Hashim Warren Co-authored-by: anubhavmeet <57403244+anubhavmeet@users.noreply.github.com> Co-authored-by: Dan Kirkham Co-authored-by: Sidhartha Chatterjee Co-authored-by: John Kavanagh Co-authored-by: Julius Co-authored-by: Julien Karst Co-authored-by: Obinna Ekwuno Co-authored-by: Tobias Meixner Co-authored-by: Andy Stanberry Co-authored-by: Andreas Ehrencrona Co-authored-by: Andreas Ehrencrona Co-authored-by: Laurie Barth Co-authored-by: Marin Matošević <7361552+Marin-Matosevic@users.noreply.github.com> Co-authored-by: Sean Baines Co-authored-by: Colby Fayock Co-authored-by: Peter van der Zee <209817+pvdz@users.noreply.github.com> --- packages/gatsby-cli/src/create-cli.ts | 24 +- packages/gatsby-cli/src/recipes.ts | 8 +- packages/gatsby-recipes/.babelrc.json | 7 + packages/gatsby-recipes/README.md | 2 + ...l.config.js => non-rollup-babel.config.js} | 0 packages/gatsby-recipes/package.json | 117 +- .../recipes/animated-page-transitions.mdx | 10 +- packages/gatsby-recipes/recipes/ava.mdx | 12 +- packages/gatsby-recipes/recipes/cypress.mdx | 23 +- packages/gatsby-recipes/recipes/emotion.mdx | 14 +- packages/gatsby-recipes/recipes/eslint.mdx | 16 +- .../recipes/gatsby-plugin-layout.mdx | 13 +- .../recipes/gatsby-plugin-react-helmet.mdx | 16 +- .../recipes/gatsby-theme-blog-core.mdx | 13 +- .../recipes/gatsby-theme-blog.mdx | 13 +- .../recipes/gatsby-theme-notes.mdx | 13 +- .../gatsby-recipes/recipes/gitlab-ci-cd.mdx | 10 +- packages/gatsby-recipes/recipes/jest.mdx | 20 +- .../gatsby-recipes/recipes/mdx-images.mdx | 20 +- packages/gatsby-recipes/recipes/mdx-pages.mdx | 18 +- packages/gatsby-recipes/recipes/preact.mdx | 10 +- .../recipes/prettier-git-hook.mdx | 20 +- packages/gatsby-recipes/recipes/pwa.mdx | 16 +- packages/gatsby-recipes/recipes/sass.mdx | 12 +- .../gatsby-recipes/recipes/storybook-js.mdx | 18 +- .../gatsby-recipes/recipes/storybook-ts.mdx | 18 +- .../recipes/styled-components.mdx | 10 +- .../gatsby-recipes/recipes/tailwindcss.mdx | 11 +- packages/gatsby-recipes/recipes/theme-ui.mdx | 12 +- .../recipes/travis-deploy-github-pages.mdx | 12 +- .../gatsby-recipes/recipes/typescript.mdx | 12 +- packages/gatsby-recipes/recipes/wordpress.mdx | 18 +- packages/gatsby-recipes/rollup.config.js | 60 + packages/gatsby-recipes/src/apply-plan.js | 42 +- .../src/{cli.js => cli/index.js} | 531 ++++----- packages/gatsby-recipes/src/components/mdx.js | 35 + packages/gatsby-recipes/src/create-plan.js | 10 +- .../gatsby-recipes/src/create-types.test.js | 160 +++ .../src/graphql-server/index.js | 24 +- .../src/graphql-server/server.js | 121 +- .../graphql-server/start-dev-cli-server.js | 37 + packages/gatsby-recipes/src/gui.js | 1015 +++++++++++++++++ packages/gatsby-recipes/src/index.js | 5 +- .../parser/__snapshots__/index.test.js.snap | 102 -- packages/gatsby-recipes/src/parser/index.js | 88 +- .../gatsby-recipes/src/parser/index.test.js | 12 +- packages/gatsby-recipes/src/parser/util.js | 25 + .../src/parser/validate.test.js | 4 +- .../src/providers/contentful/client.js | 11 + .../src/providers/contentful/entry.js | 80 ++ .../src/providers/contentful/environment.js | 65 ++ .../src/providers/contentful/space.js | 94 ++ .../src/providers/contentful/type.js | 75 ++ .../gatsby-recipes/src/providers/fs/file.js | 2 +- .../src/providers/gatsby/plugin.js | 46 +- .../src/providers/gatsby/plugin.test.js | 2 +- .../gatsby/utils/build-plugin-node.js | 7 +- .../npm/__snapshots__/script.test.js.snap | 8 +- .../src/providers/npm/script.js | 4 +- .../src/providers/resource-schema.js | 1 + .../src/providers/utils/get-diff.js | 2 +- .../src/providers/utils/get-graphql-fields.js | 16 +- .../utils/get-graphql-fields.test.js | 20 +- .../__snapshots__/index.test.js.snap | 18 - .../src/recipe-machine/index.js | 90 +- .../src/recipe-machine/index.test.js | 53 +- .../renderer/babel-plugin-copy-key-prop.js | 17 + .../babel-plugin-move-export-keywords.js | 56 + .../babel-plugin-remove-shortcodes.js | 74 ++ packages/gatsby-recipes/src/renderer/index.js | 55 +- .../gatsby-recipes/src/renderer/index.test.js | 81 +- .../src/renderer/input-provider.js | 30 + packages/gatsby-recipes/src/renderer/input.js | 15 + .../src/renderer/parent-resource-provider.js | 19 + .../src/renderer/provider-provider.js | 18 + .../gatsby-recipes/src/renderer/reconciler.js | 23 +- .../gatsby-recipes/src/renderer/render.js | 245 +++- .../src/renderer/render.test.js | 133 ++- .../src/renderer/resource-components.js | 14 +- .../src/renderer/resource-provider.js | 22 + .../src/renderer/step-component.js | 22 + .../renderer/transform-to-plan-structure.js | 61 +- packages/gatsby-recipes/src/resources.js | 8 + .../src/transform-recipe-mdx.js | 59 + packages/gatsby/package.json | 7 +- scripts/e2e-test.sh | 2 +- yarn.lock | 813 ++++++++++--- 87 files changed, 4110 insertions(+), 1067 deletions(-) create mode 100644 packages/gatsby-recipes/.babelrc.json rename packages/gatsby-recipes/{babel.config.js => non-rollup-babel.config.js} (100%) create mode 100644 packages/gatsby-recipes/rollup.config.js rename packages/gatsby-recipes/src/{cli.js => cli/index.js} (53%) create mode 100644 packages/gatsby-recipes/src/components/mdx.js create mode 100644 packages/gatsby-recipes/src/graphql-server/start-dev-cli-server.js create mode 100644 packages/gatsby-recipes/src/gui.js delete mode 100644 packages/gatsby-recipes/src/parser/__snapshots__/index.test.js.snap create mode 100644 packages/gatsby-recipes/src/parser/util.js create mode 100644 packages/gatsby-recipes/src/providers/contentful/client.js create mode 100644 packages/gatsby-recipes/src/providers/contentful/entry.js create mode 100644 packages/gatsby-recipes/src/providers/contentful/environment.js create mode 100644 packages/gatsby-recipes/src/providers/contentful/space.js create mode 100644 packages/gatsby-recipes/src/providers/contentful/type.js delete mode 100644 packages/gatsby-recipes/src/recipe-machine/__snapshots__/index.test.js.snap create mode 100644 packages/gatsby-recipes/src/renderer/babel-plugin-copy-key-prop.js create mode 100644 packages/gatsby-recipes/src/renderer/babel-plugin-move-export-keywords.js create mode 100644 packages/gatsby-recipes/src/renderer/babel-plugin-remove-shortcodes.js create mode 100644 packages/gatsby-recipes/src/renderer/input-provider.js create mode 100644 packages/gatsby-recipes/src/renderer/input.js create mode 100644 packages/gatsby-recipes/src/renderer/parent-resource-provider.js create mode 100644 packages/gatsby-recipes/src/renderer/provider-provider.js create mode 100644 packages/gatsby-recipes/src/renderer/resource-provider.js create mode 100644 packages/gatsby-recipes/src/renderer/step-component.js create mode 100644 packages/gatsby-recipes/src/transform-recipe-mdx.js diff --git a/packages/gatsby-cli/src/create-cli.ts b/packages/gatsby-cli/src/create-cli.ts index 4b5d575fb966e..532bc83cd70f4 100644 --- a/packages/gatsby-cli/src/create-cli.ts +++ b/packages/gatsby-cli/src/create-cli.ts @@ -354,9 +354,29 @@ function buildLocalCommands(cli: yargs.Argv, isLocalSite: boolean): void { cli.command({ command: `recipes [recipe]`, describe: `[EXPERIMENTAL] Run a recipe`, + builder: _ => + _.option(`D`, { + alias: `develop`, + type: `boolean`, + default: false, + describe: `Start recipe in develop mode to live-develop your recipe (defaults to false)`, + }).option(`I`, { + alias: `install`, + type: `boolean`, + default: false, + describe: `Install recipe (defaults to plan mode)`, + }), handler: handlerP( - async ({ recipe }: yargs.Arguments<{ recipe: string | undefined }>) => { - await recipesHandler(siteInfo.directory, recipe) + async ({ + recipe, + develop, + install, + }: yargs.Arguments<{ + recipe: string | undefined + develop: boolean + install: boolean + }>) => { + await recipesHandler(siteInfo.directory, recipe, develop, install) } ), }) diff --git a/packages/gatsby-cli/src/recipes.ts b/packages/gatsby-cli/src/recipes.ts index 79b6504d5b887..fe7af7c1fa3c6 100644 --- a/packages/gatsby-cli/src/recipes.ts +++ b/packages/gatsby-cli/src/recipes.ts @@ -1,9 +1,11 @@ import { trackCli } from "gatsby-telemetry" -import runRecipe, { startGraphQLServer } from "gatsby-recipes" +import { startGraphQLServer, recipesHandler as runRecipe } from "gatsby-recipes" export async function recipesHandler( projectRoot: string, - recipe: string | undefined + recipe: string | undefined, + develop: boolean, + install: boolean ): Promise { trackCli(`RECIPE_RUN`, { name: recipe }) @@ -11,6 +13,8 @@ export async function recipesHandler( return runRecipe({ recipe, + isDevelopMode: develop, + isInstallMode: install, graphqlPort: graphql.port, projectRoot, }) diff --git a/packages/gatsby-recipes/.babelrc.json b/packages/gatsby-recipes/.babelrc.json new file mode 100644 index 0000000000000..e4718b43d4b14 --- /dev/null +++ b/packages/gatsby-recipes/.babelrc.json @@ -0,0 +1,7 @@ +{ + "presets": [ + ["@babel/env", { "modules": false, "targets": { "node": "current" } }], + "@babel/preset-react" + ], + "plugins": ["@babel/plugin-transform-runtime"] +} diff --git a/packages/gatsby-recipes/README.md b/packages/gatsby-recipes/README.md index 30b37083df7d3..464169b0d2c42 100644 --- a/packages/gatsby-recipes/README.md +++ b/packages/gatsby-recipes/README.md @@ -241,6 +241,8 @@ DEBUG=true node --inspect-brk ./node_modules/.bin/gatsby recipes ./test.mdx Then, open up Chrome and click the node icon in dev tools. +To see log output from the Recipes graphql server, run in a terminal `node node_modules/gatsby-recipes/dist/graphql-server/start-dev-cli-server.js` + ### Official recipes MDX source for the official recipes lives at [https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-recipes/recipes](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-recipes/recipes). diff --git a/packages/gatsby-recipes/babel.config.js b/packages/gatsby-recipes/non-rollup-babel.config.js similarity index 100% rename from packages/gatsby-recipes/babel.config.js rename to packages/gatsby-recipes/non-rollup-babel.config.js diff --git a/packages/gatsby-recipes/package.json b/packages/gatsby-recipes/package.json index 2d49a99405b90..99ddd214e3a8e 100644 --- a/packages/gatsby-recipes/package.json +++ b/packages/gatsby-recipes/package.json @@ -3,36 +3,47 @@ "description": "Core functionality for Gatsby Recipes", "version": "0.1.59", "author": "Kyle Mathews ", - "main": "dist/index.js", "bugs": { "url": "https://github.com/gatsbyjs/gatsby/issues" }, "dependencies": { - "@babel/core": "^7.10.3", - "@babel/generator": "^7.10.3", - "@babel/helper-plugin-utils": "^7.10.3", - "@babel/plugin-transform-react-jsx": "^7.10.3", - "@babel/standalone": "^7.10.3", - "@babel/template": "^7.10.3", - "@babel/types": "^7.10.3", - "@graphql-tools/schema": "^6.0.11", - "@graphql-tools/utils": "^6.0.11", - "@hapi/hoek": "8.x", + "@babel/core": "^7.9.6", + "@babel/generator": "^7.9.6", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.9.4", + "@babel/plugin-transform-react-jsx": "^7.9.4", + "@babel/standalone": "^7.10.2", + "@babel/template": "^7.8.6", + "@babel/types": "^7.9.6", + "@emotion/core": "^10.0.14", + "@emotion/styled": "^10.0.14", + "@graphql-tools/schema": "^6.0.14", + "@graphql-tools/utils": "^6.0.14", + "@hapi/hoek": "8.x.x", "@hapi/joi": "^15.1.1", - "@mdx-js/mdx": "^1.6.6", - "@mdx-js/react": "^1.6.6", - "@mdx-js/runtime": "^1.6.6", - "acorn": "^7.3.1", + "@mdx-js/mdx": "^2.0.0-next.4", + "@mdx-js/react": "^2.0.0-next.4", + "@mdx-js/runtime": "^2.0.0-next.4", + "acorn": "^7.2.0", "acorn-jsx": "^5.2.0", + "ansi-html": "^0.0.7", + "babel-plugin-remove-export-keywords": "^1.6.5", + "chokidar": "3.4.0", + "concurrently": "^5.0.0", + "contentful-management": "^5.26.3", "cors": "^2.8.5", "debug": "^4.1.1", "detect-port": "^1.3.0", + "dotenv": "^8.2.0", "execa": "^4.0.2", "express": "^4.17.1", "express-graphql": "^0.9.0", + "flatted": "^3.0.0", + "formik": "^2.0.8", "fs-extra": "^8.1.0", "gatsby-core-utils": "^1.3.14", - "gatsby-telemetry": "^1.3.25", + "gatsby-interface": "^0.0.166", + "gatsby-telemetry": "^1.3.24", "glob": "^7.1.6", "graphql": "^14.6.0", "graphql-compose": "^6.3.8", @@ -40,21 +51,24 @@ "graphql-type-json": "^0.3.2", "hicat": "^0.7.0", "html-tag-names": "^1.1.5", - "ink": "^2.7.1", - "ink-box": "^1.0.0", - "ink-link": "^1.1.0", - "ink-select-input": "^3.1.2", - "ink-spinner": "^3.1.0", "is-binary-path": "^2.1.0", "is-url": "^1.2.4", + "isomorphic-fetch": "^2.1.0", "jest-diff": "^25.5.0", "lodash": "^4.17.15", "mkdirp": "^0.5.1", - "node-fetch": "^2.6.0", + "node-fetch": "^2.5.0", + "normalize.css": "^8.0.1", + "p-queue": "^6.4.0", "pkg-dir": "^4.2.0", "prettier": "^2.0.5", + "prop-types": "^15.6.1", + "property-information": "5.5.0", + "react-circular-progressbar": "^2.0.0", + "react-icons": "^3.0.1", "react-reconciler": "^0.25.1", - "remark-mdx": "^1.6.6", + "remark-mdx": "^2.0.0-next.4", + "remark-mdxjs": "^2.0.0-next.4", "remark-parse": "^6.0.3", "remark-stringify": "^8.1.0", "resolve-cwd": "^3.0.0", @@ -65,50 +79,73 @@ "subscriptions-transport-ws": "^0.9.16", "svg-tag-names": "^2.0.1", "unified": "^8.4.2", + "unist-util-remove": "^2.0.0", "unist-util-visit": "^2.0.2", - "urql": "^1.9.8", + "urql": "^1.9.7", + "uuid": "^8.2.0", "ws": "^7.3.0", - "xstate": "^4.11.0" - }, - "peerDependencies": { - "react": "^16.12.0" + "xstate": "^4.9.1", + "yoga-layout-prebuilt": "^1.9.6", + "yup": "^0.27.0" }, "devDependencies": { "@babel/cli": "^7.10.3", + "@babel/plugin-transform-runtime": "^7.0.0", + "@rollup/plugin-babel": "^5.1.0", + "@rollup/plugin-commonjs": "^14.0.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^8.4.0", + "ink": "next", + "ink-select-input": "^4.0.0", + "ink-spinner": "^4.0.0-0", "react": "^16.12.0", "rimraf": "^3.0.2", + "rollup": "^2.23.0", + "rollup-plugin-auto-external": "^2.0.0", + "rollup-plugin-internal": "^1.0.0", + "terminal-link": "^2.0.0", "tmp-promise": "^2.1.0" }, "homepage": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-recipes#readme", + "jest": { + "testPathIgnorePatterns": [ + "/.cache/", + "dist" + ], + "testEnvironment": "node" + }, "keywords": [ "gatsby", "gatsby-recipes", "mdx" ], "license": "MIT", + "main": "dist/index.js", "repository": { "type": "git", "url": "https://github.com/gatsbyjs/gatsby.git", "directory": "packages/gatsby-recipes" }, "resolutions": { - "graphql": "^14.6.0" - }, - "jest": { - "testPathIgnorePatterns": [ - "/.cache/", - "dist" - ], - "testEnvironment": "node" + "@mdx-js/mdx": "^2.0.0-next.4", + "@mdx-js/react": "^2.0.0-next.4", + "@mdx-js/runtime": "^2.0.0-next.4", + "graphql": "^14.6.0", + "property-information": "5.5.0", + "remark-mdx": "^2.0.0-next.4", + "remark-mdxjs": "^2.0.0-next.4" }, "scripts": { - "build": "babel src --out-dir dist --ignore \"**/__tests__\" --extensions \".ts,.js,.tsx\"", - "build:watch": "npm run build -- --watch", + "build": "concurrently \"npm run build:babel\" \"npm run build:rollup\"", + "build:babel": "babel --config-file ./non-rollup-babel.config.js src --out-dir dist --ignore \"**/__tests__\" --extensions \".ts,.js,.tsx\"", + "build:rollup": "rollup -c", + "build:watch": "npm run build:babel -- --watch", "prebuild": "rimraf dist", "prepare": "npm run build", "prewatch": "rimraf dist", - "watch": "npm run build:watch", "test": "jest", - "test:watch": "jest --watch" + "test:watch": "jest --watch", + "watch": "concurrently \"npm run build:watch\" \"npm run watch:rollup\"", + "watch:rollup": "rollup -c -w" } } diff --git a/packages/gatsby-recipes/recipes/animated-page-transitions.mdx b/packages/gatsby-recipes/recipes/animated-page-transitions.mdx index 0cee28993c6ea..fe655a5021729 100644 --- a/packages/gatsby-recipes/recipes/animated-page-transitions.mdx +++ b/packages/gatsby-recipes/recipes/animated-page-transitions.mdx @@ -2,22 +2,24 @@ This recipe helps you create transitions for animating between entering and exiting Gatsby pages. +This recipe: + --- -The first step is installing the NPM packages you need: +Installs these NPM packages: --- -Add the plugin to your Gatsby config. +Adds the following plugin to your Gatsby config: --- -Now let's create a few example pages to animate between: +Creates a few example pages to animate between: @@ -28,5 +30,3 @@ Now let's create a few example pages to animate between: When you run your site you can navigate to http://localhost:8000/transition-paint-drip to try it out. See more examples about usage in the docs for the transition link plugin: https://transitionlink.tylerbarnes.ca/docs/ - -And your recipe is served! diff --git a/packages/gatsby-recipes/recipes/ava.mdx b/packages/gatsby-recipes/recipes/ava.mdx index 059ae32223e0b..71b86eca47cd0 100644 --- a/packages/gatsby-recipes/recipes/ava.mdx +++ b/packages/gatsby-recipes/recipes/ava.mdx @@ -1,16 +1,18 @@ # Add AVA -This recipe helps you setup AVA in your Gatsby site to test components and utilities +This recipe helps you setup AVA in your Gatsby site to test components and utilities. + +This recipe: --- -Install the `ava` package +Installs the `ava` package. --- -Adding some AVA test files for you to play with +Adds some AVA test files for you to play with. --- -Well look at that — we've added dependencies to your package.json and we also installed a useful package `gatsby-cypress`. `gatsby-cypress` exposes additional Cypress functionality which makes Gatsby and Cypress work together just a bit more nicely. We'll show that later with our first test, but hold tight for just a bit because first we need to scaffold out some boilerplate files for Cypress. - ---- +Creates a local `cypress` folder with two sub-folders, `support` and `plugins`. It automatically includes all the `gatsby-cypress` utilities, which you can use in your first test. @@ -12,15 +16,13 @@ Install necessary NPM packages --- -Install the Emotion plugin in gatsby-config.js +Installs the Emotion plugin in gatsby-config.js --- -Sweet, now it's ready to go. - -Let's also write out an example page you can use to play +Writes out an example page you can use to play with Emotion. --- -Install `gatsby-plugin-eslint` +Installs `gatsby-plugin-eslint`. --- -Write out a basic .eslintrc.js file that you can extend with your own chosen +Writes out a basic .eslintrc.js file that you can extend with your own chosen eslint plugins and presets. --- -Install the Layout plugin in gatsby-config.js +Installs the Layout plugin in gatsby-config.js --- -Sweet, now it's ready to go! - -Let's also write out a sample layout component to get started with. +Writes out a sample layout component to get started with. --- -Install the React Helmet plugin in gatsby-config.js +Installs the React Helmet plugin in `gatsby-config.js`. --- -Great, now it's ready to go! - -It's also common to have a `` component which helps ensure pages have the necessary title and meta tags. - -We'll write out one now. +Writes out an `` component which helps ensure pages have the necessary title and meta tags. --- -Install the gatsby-theme-blog-core plugin in gatsby-config.js. Make use of the `basePath` configuration so the blog listing appears at `/blog`. +Installs the `gatsby-theme-blog-core` plugin in `gatsby-config.js` and makes use of the `basePath` configuration so the blog listing appears at `/blog`. --- -Now let's add some posts! + +Adds some posts. --- -You're now set up to style your blog however you like! +After installing this recipe, you will be setup to style your blog however you like. -Run `gatsby develop` and check out `http://localhost:8000/blog` for the list of posts. +When you've finished installing the recipe, run `gatsby develop` and check out `http://localhost:8000/blog` for the list of posts. Example content is available at `http://localhost:8000/blog/hello-world` and `http://localhost:8000/blog/second-post`. diff --git a/packages/gatsby-recipes/recipes/gatsby-theme-blog.mdx b/packages/gatsby-recipes/recipes/gatsby-theme-blog.mdx index 367daa7b6227f..e8bd0233e5167 100644 --- a/packages/gatsby-recipes/recipes/gatsby-theme-blog.mdx +++ b/packages/gatsby-recipes/recipes/gatsby-theme-blog.mdx @@ -2,29 +2,30 @@ [Gatsby theme blog](https://www.gatsbyjs.org/packages/gatsby-theme-blog/) is a great theme for adding blog functionality to your site. +This recipe: + --- -Install necessary NPM packages +Installs necessary NPM packages. --- -Install the gatsby-theme-blog plugin in gatsby-config.js. Make use of the `basePath` configuration so the blog listing appears at `/blog`. +Installs the `gatsby-theme-blog` plugin in `gatsby-config.js` and makes use of the `basePath` configuration so the blog listing appears at `/blog`. --- -Now let's add a post! + +Adds a post. --- -And just like that, you're ready to start blogging! - -Run `gatsby develop` and check out `http://localhost:8000/blog` for the list of posts. +When you've finished installing the recipe, run `gatsby develop` and check out `http://localhost:8000/blog` for the list of posts. Example content is available at `http://localhost:8000/blog/first-blog`. diff --git a/packages/gatsby-recipes/recipes/gatsby-theme-notes.mdx b/packages/gatsby-recipes/recipes/gatsby-theme-notes.mdx index daf681ee74d2c..c1e77d942c250 100644 --- a/packages/gatsby-recipes/recipes/gatsby-theme-notes.mdx +++ b/packages/gatsby-recipes/recipes/gatsby-theme-notes.mdx @@ -2,28 +2,31 @@ [Gatsby theme notes](https://www.gatsbyjs.org/packages/gatsby-theme-notes) is a great theme for adding learning notes to your site. +This recipe: + --- -Install necessary NPM package +Installs necessary NPM package. --- -Install the gatsby-theme-notes plugin in gatsby-config.js +Installs the `gatsby-theme-notes` plugin in `gatsby-config.js`. --- -Now let's add a note! + +Adds a note. --- -Now you're ready to use your site for notetaking. +After installing this recipe, you can use your site for notetaking. -Run `gatsby develop` and check out `http://localhost:8000/notes` for the list of notes. +When you've finished installing the recipe, run `gatsby develop` and check out `http://localhost:8000/notes` for the list of notes. --- diff --git a/packages/gatsby-recipes/recipes/gitlab-ci-cd.mdx b/packages/gatsby-recipes/recipes/gitlab-ci-cd.mdx index 3144986ffe22e..b051195a5dff0 100644 --- a/packages/gatsby-recipes/recipes/gitlab-ci-cd.mdx +++ b/packages/gatsby-recipes/recipes/gitlab-ci-cd.mdx @@ -1,10 +1,12 @@ # Add GitLab CI/CD -This recipe helps you setup GitLab CI/CD in your Gatsby site to create a pipeline on gitlab.com +This recipe helps you setup GitLab CI/CD in your Gatsby site to create a pipeline on gitlab.com. + +This recipe: --- -Adding the `.gitlab-ci.yml` +Adds the `.gitlab-ci.yml`. ` you will have your gatsby project building! +After installing this recipe, every time you `git push ` you will have your gatsby project building. ---- +More resources: - See how you can develop this simple file into something more real world [GitLab CI/CD Docs](https://docs.gitlab.com/ee/ci/README.html) - Check this especially to learn how to make your newly build available for a next job - [GitLab Job Artifacts Docs](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html) diff --git a/packages/gatsby-recipes/recipes/jest.mdx b/packages/gatsby-recipes/recipes/jest.mdx index 4618a6a79a2f3..c2ec3cedcf954 100644 --- a/packages/gatsby-recipes/recipes/jest.mdx +++ b/packages/gatsby-recipes/recipes/jest.mdx @@ -1,20 +1,22 @@ # Add Jest -This recipe helps you setup Jest in your Gatsby site to test components and utilities +This recipe helps you setup Jest in your Gatsby site to test components and utilities. +This recipe: + --- -Installing the `jest` package +Installs the `jest` package. --- -Adding some jest test files for you to play with +Adds some jest test files for you to play with. + +--- + +Once you've installed this recipe, try running `npm run test` and jest will run your test. And, while writing tests, you can run `npm run test:watch` and tests will re-run +as you edit them. diff --git a/packages/gatsby-recipes/recipes/mdx-images.mdx b/packages/gatsby-recipes/recipes/mdx-images.mdx index df3620af89fa1..b631cc6ef69b5 100644 --- a/packages/gatsby-recipes/recipes/mdx-images.mdx +++ b/packages/gatsby-recipes/recipes/mdx-images.mdx @@ -1,13 +1,16 @@ # Setup images in MDX with Gatsby This recipe installs and configures all -the necessary NPM packages & Gatsby Plugins +the necessary NPM packages & Gatsby plugins to enable inline-images in MDX and MD files. Based on https://www.gatsbyjs.org/docs/working-with-images-in-markdown/ +This recipe: + --- -Install NPM Packages + +Installs NPM Packages. ---- - @@ -38,9 +39,8 @@ Install NPM Packages /> --- -Install Gatsby Plugins -First, add `gatsby-source-filesystem` to read images from the src/images +Adds Gatsby plugin `gatsby-source-filesystem` to read images from the src/images directory. + --- -Finally, configure `gatsby-plugin-mdx` to resolve images in MDX files. +Configures `gatsby-plugin-mdx` to resolve images in MDX files. --- -Then we'll add an example MDX page for you to play with. +Adds an example MDX page for you to play with. @@ -14,7 +16,7 @@ Install the necessary NPM packages: --- -Add the Preact plugin to your Gatsby config. It will setup the correct configuration, which will let gatsby use Preact instead of React. +Adds the Preact plugin to your Gatsby config. It will setup the correct configuration, which will let gatsby use Preact instead of React. @@ -14,7 +16,7 @@ Install packages. --- -Implement git hooks for prettier. +Implements git hooks for `prettier`. --- -Add the manifest plugin and the offline plugin to your Gatsby config, which will add a manifest file and a service worker for you. +Adds the manifest plugin and the offline plugin to your Gatsby config, which will add a manifest file and a service worker for you. -We also add a default icon @ src/images/icon.svg (which you can replace afterwards with your own). +It also adds a default icon @ src/images/icon.svg (which you can replace afterwards with your own). --- -Install the Emotion plugin in gatsby-config.js +Installs the Emotion plugin in `gatsby-config.js`. --- -Sweet, now it's ready to go. - -Let's also write out an example stylesheet and page you can use to play +Writes out an example stylesheet and page you can use to play with Sass. @@ -19,7 +21,7 @@ Install babel plugins and presets as well as the Storybook React NPM packages an --- -Create JavaScript Storybook webpack config (main.js) +Creates JavaScript Storybook webpack config (`main.js`). @@ -23,7 +25,7 @@ Install TypesScript + babel plugins and presets as well as the Storybook React N --- -Create custom Storybook webpack config (main.js) +Creates custom Storybook webpack config (`main.js`). @@ -13,15 +15,13 @@ Install necessary NPM packages --- -Install the Styled Components plugin in gatsby-config.js +Installs the Styled Components plugin in `gatsby-config.js`. --- -Sweet, now it's ready to go. - -Let's also write out an example page you can use to play +Writes out an example page you can use to play with Styled Components. --- -Install necessary Gatsby Plugins +Installs necessary Gatsby plugins. --- -Setup necessary Files +Sets up necessary files. ---- - -You are good to go diff --git a/packages/gatsby-recipes/recipes/theme-ui.mdx b/packages/gatsby-recipes/recipes/theme-ui.mdx index a8a240f27ce52..e28d8662012ed 100644 --- a/packages/gatsby-recipes/recipes/theme-ui.mdx +++ b/packages/gatsby-recipes/recipes/theme-ui.mdx @@ -4,9 +4,11 @@ This recipe helps you start developing with the [Theme UI](https://theme-ui.com) +This recipe: + --- -Install packages. +Installs packages. @@ -14,13 +16,13 @@ Install packages. --- -Add the plugin `gatsby-plugin-theme-ui` to your `gatsby-config.js`. +Adds the plugin `gatsby-plugin-theme-ui` to your `gatsby-config.js`. --- -Write out Theme UI configuration files. +Writes out Theme UI configuration files. @@ -13,18 +15,16 @@ Install necessary NPM packages --- -Install the plugin `gatsby-plugin-typescript` in your `gatsby-config.js`. +Installs the plugin `gatsby-plugin-typescript` in your `gatsby-config.js`. --- -Add a tsconfig.json file to control how TypeScript processes your code. +Adds a `tsconfig.json` file to control how TypeScript processes your code. --- -TypeScript is now setup! - -You can now add TypeScript code, components, and pages in your sites `src` directory. +After installing this recipe, you can add TypeScript code, components, and pages in your sites `src` directory. diff --git a/packages/gatsby-recipes/recipes/wordpress.mdx b/packages/gatsby-recipes/recipes/wordpress.mdx index 1b229f260e55c..2ba0c19a46607 100644 --- a/packages/gatsby-recipes/recipes/wordpress.mdx +++ b/packages/gatsby-recipes/recipes/wordpress.mdx @@ -1,16 +1,18 @@ # Setup Gatsby with WordPress REST API -This recipes setups and configures gatsby-source-wordpress and starter page templates for a WordPress-powered Gatsby site. +This recipes sets up and configures `gatsby-source-wordpress` and starter page templates for a WordPress-powered Gatsby site. + +This recipe: --- -Install necessary NPM packages +Installs necessary NPM packages. --- -Install `gatsby-source-wordpress` to pull the WordPress data into Gatsby. Note, once this recipe finishes, you will need to update the config to point to your actual WordPress URL +Installs `gatsby-source-wordpress` to pull the WordPress data into Gatsby. Note, once this recipe finishes, you will need to update the config to point to your actual WordPress URL. --- -Create basic post/page/category/tag/user templates +Creates basic post, page, category, tag, and user templates. { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array) - } -} - -const applyPlan = async stepPlan => { - let appliedResources = [] - // We apply each resource serially for now — we can parallelize in the - // future for SPEED - await asyncForEach(stepPlan, async resourcePlan => { - const resource = resources[resourcePlan.resourceName] - - try { - const changedResources = await resource.create( - ctx, - resourcePlan.resourceDefinitions - ) +module.exports = async (context, cb) => { + const stepAsMdx = [...context.steps, ...context.exports].join(`\n`) - appliedResources = appliedResources.concat(changedResources) - - return - } catch (e) { - throw e - } - }) - - return appliedResources + try { + const result = await render(stepAsMdx, cb, context.inputs, true) + return result + } catch (e) { + console.log(e) + throw e + } } - -module.exports = applyPlan diff --git a/packages/gatsby-recipes/src/cli.js b/packages/gatsby-recipes/src/cli/index.js similarity index 53% rename from packages/gatsby-recipes/src/cli.js rename to packages/gatsby-recipes/src/cli/index.js index 66da0cfdc6e9e..8d60e3aa4d8d7 100644 --- a/packages/gatsby-recipes/src/cli.js +++ b/packages/gatsby-recipes/src/cli/index.js @@ -1,14 +1,18 @@ -const fs = require(`fs`) -const lodash = require(`lodash`) -const Boxen = require(`ink-box`) const React = require(`react`) -const { useState } = require(`react`) -const { render, Box, Text, Color, useInput, useApp, Static } = require(`ink`) -const Spinner = require(`ink-spinner`).default -const Link = require(`ink-link`) -const MDX = require(`@mdx-js/runtime`) +const { useState, useEffect } = require(`react`) +import SelectInput from "ink-select-input" +import { render, Box, Text, useInput, useApp, Transform } from "ink" +import Spinner from "ink-spinner" +import MDX from "../components/mdx" const hicat = require(`hicat`) -import { trackCli } from "gatsby-telemetry" +const { trackCli } = require(`gatsby-telemetry`) +import { + useResource, + useResourceByUUID, + ResourceProvider, +} from "../renderer/resource-provider" +import terminalLink from "terminal-link" +import PropTypes from "prop-types" const { createClient, useMutation, @@ -20,18 +24,38 @@ const { const { SubscriptionClient } = require(`subscriptions-transport-ws`) const fetch = require(`node-fetch`) const ws = require(`ws`) -const SelectInput = require(`ink-select-input`).default const semver = require(`semver`) +const remove = require(`unist-util-remove`) -const MAX_UI_WIDTH = 67 +const removeJsx = () => tree => { + remove(tree, `export`, () => true) + return tree +} -// TODO try this and write out success stuff & last message? -// const enterAltScreenCommand = "\x1b[?1049h" -// const leaveAltScreenCommand = "\x1b[?1049l" -// process.stdout.write(enterAltScreenCommand) -// process.on("exit", () => { -// process.stdout.write(leaveAltScreenCommand) -// }) +// Inline ink-link as it's not upgraded to v3 yet +const Link = props => ( + + terminalLink(children, props.url, { fallback: props.fallback }) + } + > + {props.children} + +) + +Link.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]).isRequired, + url: PropTypes.string, + fallback: PropTypes.bool, +} + +Link.defaultProps = { + url: ``, + fallback: true, +} // Check for what version of React is loaded & warn if it's too low. if (semver.lt(React.version, `16.8.0`)) { @@ -42,19 +66,24 @@ if (semver.lt(React.version, `16.8.0`)) { const WelcomeMessage = () => ( <> - - Thank you for trying the experimental version of Gatsby Recipes! - + + Thank you for trying the experimental version of Gatsby Recipes! + +
- Please ask questions, share your recipes, report bugs, and subscribe for - updates in our umbrella issue at - https://github.com/gatsbyjs/gatsby/issues/22991 + + Please ask questions, share your recipes, report bugs, and subscribe for + updates in our umbrella issue at + https://github.com/gatsbyjs/gatsby/issues/22991 +
) @@ -170,36 +199,29 @@ const RecipesList = ({ setRecipe }) => { ] return ( - ( - + {item.isSelected ? `>>` : ` `} {item.label} - + )} itemComponent={props => ( - {props.label} + + {props.isSelected} + {` `} + {props.label} + )} /> ) } -let renderCount = 1 - -const Div = props => { - const width = Math.min(process.stdout.columns, MAX_UI_WIDTH) - return ( - - ) -} +const Div = props => ( + +) // Markdown ignores new lines and so do we. function eliminateNewLines(children) { @@ -218,8 +240,33 @@ function eliminateNewLines(children) { }) } +const ResourceComponent = props => { + let resource + if (props._key) { + resource = useResource(props._key) + } else { + resource = useResourceByUUID(props._uuid) + } + + return ( +
+ + {resource.resourceName}: + + {resource?.describe} + {resource?.diff ? ( + <> + {` `} + {resource?.diff}" + + ) : null} +
+ ) +} + const components = { - inlineCode: props => , + inlineCode: props => `{props.children}`, + pre: props =>
, code: props => { // eslint-disable-next-line let language = "```" @@ -238,75 +285,78 @@ const components = { ) }, h1: props => ( -
+ -
- ), - h2: props => ( -
- -
- ), - h3: props => ( -
- -
- ), - h4: props => ( -
- -
- ), - h5: props => ( -
- -
- ), - h6: props => ( -
- -
+ ), + h2: props => , + h3: props => , + h4: props => , + h5: props => , + h6: props => , a: ({ href, children }) => {children}, strong: props => , em: props => , p: props => { const children = eliminateNewLines(props.children) return ( -
+
{children}
) }, + // Don't use for li > p as that breaks Ink. + "li.p": props => { + const children = eliminateNewLines(props.children) + return {children} + }, + // p: () => `hi`, // null, ul: props =>
{props.children}
, li: props => * {props.children}, Config: () => null, - GatsbyPlugin: () => null, - NPMPackageJson: () => null, - NPMPackage: () => null, - File: () => null, - Directory: () => null, + GatsbyPlugin: props => , + NPMPackageJson: props => , + NPMPackage: props => , + File: props => , + Directory: props => , GatsbyShadowFile: () => null, - NPMScript: () => null, -} + NPMScript: props => , + RecipeIntroduction: props =>
, + RecipeStep: props => { + const children = React.Children.toArray(props.children) + const firstChild = children.shift() + children.unshift( + + + {props.step}){` `} + + {firstChild} + + ) -let logStream -const log = (label, textOrObj) => { - if (process.env.DEBUG) { - logStream = - logStream ?? fs.createWriteStream(`recipe-client.log`, { flags: `a` }) - logStream.write(`[${label}]:\n`) - logStream.write(require(`util`).inspect(textOrObj)) - logStream.write(`\n`) - } + return ( +
+ + {children} + +
+ ) + }, + div: props =>
, } -log( - `started client`, - `======================================= ${new Date().toJSON()}` -) - -module.exports = async ({ recipe, graphqlPort, projectRoot }) => { +export default async ({ + recipe, + isDevelopMode, + isInstallMode, + graphqlPort, + projectRoot, +}) => { try { const GRAPHQL_ENDPOINT = `http://localhost:${graphqlPort}/graphql` @@ -336,7 +386,68 @@ module.exports = async ({ recipe, graphqlPort, projectRoot }) => { }), ], }) + const Plan = ({ state, localRecipe, isDevelopMode }) => { + const { exit } = useApp() + // Exit the app after we render + useEffect(() => { + if (!isDevelopMode) { + exit() + } + }, []) + + return ( + <> + p.resourceName !== `Input`) || [] + } + > + + {isDevelopMode ? ( + + + DEVELOP MODE + + + ) : null} + + {state.context.exports?.join(`\n`) + + `\n\n` + + state.context.steps.join(`\n`)} + + {`\n------\n`} + To install this recipe, run: + {` `} + + {` `}gatsby recipes {localRecipe} --install + + {` `} + + + ) + } + + const Installing = ({ state }) => ( +
+ {state.context.plan.map((p, i) => ( +
+ {p.resourceName}: + + {` `} + {p.isDone ? `✅ ` : } + {` `} + {p.isDone ? p._message : p.describe} + {` `} + {state.context.elapsed > 0 && ( + ({state.context.elapsed / 1000}s elapsed) + )} + +
+ ))} +
+ ) + let sentContinue = false const RecipeInterpreter = () => { const { exit } = useApp() // eslint-disable-next-line @@ -362,24 +473,36 @@ module.exports = async ({ recipe, graphqlPort, projectRoot }) => { } `) // eslint-disable-next-line - const [__, sendEvent] = useMutation(` - mutation($event: String!) { - sendEvent(event: $event) + const [__, _sendEvent] = useMutation(` + mutation($event: String!, $input: String) { + sendEvent(event: $event, input: $input) } `) + const sendEvent = ({ event, input }) => { + if (input) { + _sendEvent({ + event, + input: JSON.stringify(input), + }) + } else { + _sendEvent({ event }) + } + } + subscriptionClient.connectionCallback = async () => { if (!showRecipesList) { - log(`createOperation`) try { - await createOperation({ recipePath: localRecipe, projectRoot }) + await createOperation({ + recipePath: localRecipe, + projectRoot, + }) } catch (e) { - log(`error creating operation`, e) + console.log(`error creating operation`, e) } } } - log(`subscriptionResponse`, subscriptionResponse) const state = subscriptionResponse.data && JSON.parse(subscriptionResponse.data.operation.state) @@ -393,8 +516,6 @@ module.exports = async ({ recipe, graphqlPort, projectRoot }) => { } }) - log(`subscriptionResponse.data`, subscriptionResponse.data) - if (showRecipesList) { return ( <> @@ -404,6 +525,7 @@ module.exports = async ({ recipe, graphqlPort, projectRoot }) => { { + setRecipe(recipeItem.value.slice(0, -4)) trackCli(`RECIPE_RUN`, { name: recipeItem.value }) showRecipesList = false try { @@ -412,7 +534,7 @@ module.exports = async ({ recipe, graphqlPort, projectRoot }) => { projectRoot, }) } catch (e) { - log(`error creating operation`, e) + console.log(`error creating operation`, e) } }} /> @@ -420,140 +542,50 @@ module.exports = async ({ recipe, graphqlPort, projectRoot }) => { ) } - if (!state) { - return ( - - Loading recipe - - ) - } - /* - * TODOs - * Listen to "y" to continue (in addition to enter) - */ - - log(`render`, `${renderCount} ${new Date().toJSON()}`) - renderCount += 1 - - const isDone = state.value === `done` + const Error = ({ state }) => { + if (state && state.context && state.context.error) { + return {JSON.stringify(state.context.error, null, 2)} + } - // If we're done with an error, render out error (happens below) - // then exit. - if (state.value === `doneError`) { - process.nextTick(() => process.exit()) + return null } - if (process.env.DEBUG) { - log(`state`, state) - log(`plan`, state.context.plan) - log(`stepResources`, state.context.stepResources) + if (state?.value === `doneError`) { + return } - const PresentStep = ({ state }) => { - const isPlan = state.context.plan && state.context.plan.length > 0 - const isPresetPlanState = state.value === `presentPlan` - const isRunningStep = state.value === `applyingPlan` - - if (isRunningStep) { - return null - } + let isReady - if (!isPlan || !isPresetPlanState) { - return ( -
- >> Press enter to continue -
- ) + // If installing, continue from presentPlan to applyingPlan + if (state?.value === `presentPlan` && isInstallMode) { + if (!sentContinue) { + sendEvent({ event: `CONTINUE` }) + sentContinue = true } - - return ( -
-
- - Proposed changes - -
- {state.context.plan.map((p, i) => ( -
- {p.resourceName}: - * {p.describe} - {p.diff && p.diff !== `` && ( - <> - --- - {p.diff} - --- - - )} -
- ))} -
- >> Press enter to run this step -
-
- ) } - const RunningStep = ({ state }) => { - const isPlan = state.context.plan && state.context.plan.length > 0 - const isRunningStep = state.value === `applyingPlan` - - if (!isPlan || !isRunningStep) { - return null - } + // install mode + if (isInstallMode) { + isReady = state?.value === `applyingPlan` || state?.value === `done` + } else { + isReady = state?.value === `presentPlan` + } + if (!isReady) { return ( -
- {state.context.plan.map((p, i) => ( -
- {p.resourceName}: - - {` `} - {p.describe} - {` `} - {state.context.elapsed > 0 && ( - ({state.context.elapsed / 1000}s elapsed) - )} - -
- ))} -
+ + Loading recipe + ) } - const Error = ({ state }) => { - log(`errors`, state) - if (state && state.context && state.context.error) { - return ( - {JSON.stringify(state.context.error, null, 2)} - ) - } - - return null - } + const isDone = state.value === `done` + // If we're done with an error, render out error (happens below) + // then exit. if (state.value === `doneError`) { - return - } - - const staticMessages = {} - for (let step = 0; step < state.context.currentStep; step++) { - staticMessages[step] = [ - { - type: `mdx`, - key: `mdx-${step}`, - value: state.context.steps[step], - }, - ] + process.nextTick(() => process.exit()) } - lodash.flattenDeep(state.context.stepResources).forEach((res, i) => { - staticMessages[res._currentStep].push({ - type: `resource`, - key: `finished-stuff-${i}`, - value: res._message, - }) - }) - - log(`staticMessages`, staticMessages) if (isDone) { process.nextTick(() => { @@ -562,53 +594,22 @@ module.exports = async ({ recipe, graphqlPort, projectRoot }) => { process.stdout.write( `\n\n---\n\n\nThe recipe finished successfully!\n\n` ) - lodash.flattenDeep(state.context.stepResources).forEach((res, i) => { - process.stdout.write(`✅ ${res._message}\n`) - }) process.exit() }) // return null } - return ( - <> -
- - {Object.keys(staticMessages).map((key, iStep) => - staticMessages[key].map((r, i) => { - if (r.type && r.type === `mdx`) { - return ( -
- {iStep === 0 && Completed Steps} -
- {iStep !== 0 && `---`} -
- {iStep !== 0 && Step {iStep}} - {r.value} -
- ) - } - return ✅ {r.value} - }) - )} -
-
- {state.context.currentStep === 0 && } - {state.context.currentStep > 0 && !isDone && ( -
- - Step {state.context.currentStep} /{` `} - {state.context.steps.length - 1} - -
- )} - - {state.context.steps[state.context.currentStep]} - - {!isDone && } - {!isDone && } - - ) + if (isInstallMode) { + return + } else { + return ( + + ) + } } const Wrapper = () => ( @@ -626,6 +627,6 @@ module.exports = async ({ recipe, graphqlPort, projectRoot }) => { const { waitUntilExit } = render(, { experimental: true }) await waitUntilExit() } catch (e) { - log(e) + console.log(e) } } diff --git a/packages/gatsby-recipes/src/components/mdx.js b/packages/gatsby-recipes/src/components/mdx.js new file mode 100644 index 0000000000000..1eeabfe5be9c5 --- /dev/null +++ b/packages/gatsby-recipes/src/components/mdx.js @@ -0,0 +1,35 @@ +import React from "react" +import { mdx as createElement, MDXProvider } from "@mdx-js/react" +import { useInput, useInputByKey } from "../renderer/input-provider" +import { useResource } from "../renderer/resource-provider" +import { useProvider } from "../renderer/provider-provider" +import transformRecipeMDX from "../transform-recipe-mdx" + +const transformCodeForEval = jsx => `${jsx} + + return React.createElement(MDXProvider, { components }, + React.createElement(MDXContent, props) + );` + +export default ({ children: mdxSrc, scope, components, ...props }) => { + const fullScope = { + mdx: createElement, + MDXProvider, + React, + components, + props, + useInput, + useInputByKey, + useResource, + useProvider, + ...scope, + } + const scopeKeys = Object.keys(fullScope) + const scopeValues = Object.values(fullScope) + + const srcCode = transformRecipeMDX(mdxSrc) + + const fn = new Function(...scopeKeys, transformCodeForEval(srcCode)) + + return fn(...scopeValues) +} diff --git a/packages/gatsby-recipes/src/create-plan.js b/packages/gatsby-recipes/src/create-plan.js index 39d7815197fe5..7bfa2f74e2158 100644 --- a/packages/gatsby-recipes/src/create-plan.js +++ b/packages/gatsby-recipes/src/create-plan.js @@ -1,14 +1,10 @@ const render = require(`./renderer`) -// TODO: Properly handle context in the renderer -// const SITE_ROOT = process.cwd() -// const ctx = { root: SITE_ROOT } - -module.exports = async context => { - const stepAsMdx = context.steps[context.currentStep] +module.exports = async (context, cb) => { + const stepAsMdx = [...context.steps, ...context.exports].join(`\n`) try { - const result = await render(stepAsMdx) + const result = await render(stepAsMdx, cb, context.inputs) return result } catch (e) { throw e diff --git a/packages/gatsby-recipes/src/create-types.test.js b/packages/gatsby-recipes/src/create-types.test.js index 54df14f67e465..8b2e484acac5b 100644 --- a/packages/gatsby-recipes/src/create-types.test.js +++ b/packages/gatsby-recipes/src/create-types.test.js @@ -4,6 +4,42 @@ test(`create-types`, () => { const result = createTypes() expect(result.mutationTypes).toMatchInlineSnapshot(` Object { + "createContentfulEntry": Object { + "args": Object { + "contentfulEntry": Object { + "type": "ContentfulEntryInput", + }, + }, + "resolve": [Function], + "type": "ContentfulEntry", + }, + "createContentfulEnvironment": Object { + "args": Object { + "contentfulEnvironment": Object { + "type": "ContentfulEnvironmentInput", + }, + }, + "resolve": [Function], + "type": "ContentfulEnvironment", + }, + "createContentfulSpace": Object { + "args": Object { + "contentfulSpace": Object { + "type": "ContentfulSpaceInput", + }, + }, + "resolve": [Function], + "type": "ContentfulSpace", + }, + "createContentfulType": Object { + "args": Object { + "contentfulType": Object { + "type": "ContentfulTypeInput", + }, + }, + "resolve": [Function], + "type": "ContentfulType", + }, "createDirectory": Object { "args": Object { "directory": Object { @@ -85,6 +121,42 @@ test(`create-types`, () => { "resolve": [Function], "type": "NPMScript", }, + "destroyContentfulEntry": Object { + "args": Object { + "contentfulEntry": Object { + "type": "ContentfulEntryInput", + }, + }, + "resolve": [Function], + "type": "ContentfulEntry", + }, + "destroyContentfulEnvironment": Object { + "args": Object { + "contentfulEnvironment": Object { + "type": "ContentfulEnvironmentInput", + }, + }, + "resolve": [Function], + "type": "ContentfulEnvironment", + }, + "destroyContentfulSpace": Object { + "args": Object { + "contentfulSpace": Object { + "type": "ContentfulSpaceInput", + }, + }, + "resolve": [Function], + "type": "ContentfulSpace", + }, + "destroyContentfulType": Object { + "args": Object { + "contentfulType": Object { + "type": "ContentfulTypeInput", + }, + }, + "resolve": [Function], + "type": "ContentfulType", + }, "destroyDirectory": Object { "args": Object { "directory": Object { @@ -166,6 +238,42 @@ test(`create-types`, () => { "resolve": [Function], "type": "NPMScript", }, + "updateContentfulEntry": Object { + "args": Object { + "contentfulEntry": Object { + "type": "ContentfulEntryInput", + }, + }, + "resolve": [Function], + "type": "ContentfulEntry", + }, + "updateContentfulEnvironment": Object { + "args": Object { + "contentfulEnvironment": Object { + "type": "ContentfulEnvironmentInput", + }, + }, + "resolve": [Function], + "type": "ContentfulEnvironment", + }, + "updateContentfulSpace": Object { + "args": Object { + "contentfulSpace": Object { + "type": "ContentfulSpaceInput", + }, + }, + "resolve": [Function], + "type": "ContentfulSpace", + }, + "updateContentfulType": Object { + "args": Object { + "contentfulType": Object { + "type": "ContentfulTypeInput", + }, + }, + "resolve": [Function], + "type": "ContentfulType", + }, "updateDirectory": Object { "args": Object { "directory": Object { @@ -251,6 +359,22 @@ test(`create-types`, () => { `) expect(result.queryTypes).toMatchInlineSnapshot(` Object { + "allContentfulEntry": Object { + "resolve": [Function], + "type": "ContentfulEntryConnection", + }, + "allContentfulEnvironment": Object { + "resolve": [Function], + "type": "ContentfulEnvironmentConnection", + }, + "allContentfulSpace": Object { + "resolve": [Function], + "type": "ContentfulSpaceConnection", + }, + "allContentfulType": Object { + "resolve": [Function], + "type": "ContentfulTypeConnection", + }, "allGatsbyPage": Object { "resolve": [Function], "type": "GatsbyPageConnection", @@ -271,6 +395,42 @@ test(`create-types`, () => { "resolve": [Function], "type": "NPMScriptConnection", }, + "contentfulEntry": Object { + "args": Object { + "id": Object { + "type": "String", + }, + }, + "resolve": [Function], + "type": "ContentfulEntry", + }, + "contentfulEnvironment": Object { + "args": Object { + "id": Object { + "type": "String", + }, + }, + "resolve": [Function], + "type": "ContentfulEnvironment", + }, + "contentfulSpace": Object { + "args": Object { + "id": Object { + "type": "String", + }, + }, + "resolve": [Function], + "type": "ContentfulSpace", + }, + "contentfulType": Object { + "args": Object { + "id": Object { + "type": "String", + }, + }, + "resolve": [Function], + "type": "ContentfulType", + }, "directory": Object { "args": Object { "id": Object { diff --git a/packages/gatsby-recipes/src/graphql-server/index.js b/packages/gatsby-recipes/src/graphql-server/index.js index 3e0ff375b36aa..452c33066a909 100644 --- a/packages/gatsby-recipes/src/graphql-server/index.js +++ b/packages/gatsby-recipes/src/graphql-server/index.js @@ -10,7 +10,7 @@ const { // NOTE(@mxstbr): The forceStart boolean enforces us to start the recipes graphql server // even if another instance might already be running. This is necessary to ensure the gatsby // develop command does not _not_ run the server if the user is running gatsby recipes at the same time. -exports.startGraphQLServer = async (programPath, forceStart) => { +export default async (programPath, forceStart) => { let { port } = (await getService(programPath, `recipesgraphqlserver`)) || {} if (!port || forceStart) { @@ -19,15 +19,19 @@ exports.startGraphQLServer = async (programPath, forceStart) => { port = await detectPort(50400) await createServiceLock(programPath, `recipesgraphqlserver`, { port }) - const subprocess = execa(`node`, [require.resolve(`./server.js`), port], { - all: true, - env: { - // Chalk doesn't want to output color in a child process - // as it (correctly) thinks it's not in a normal terminal environemnt. - // Since we're just returning data, we'll override that. - FORCE_COLOR: `true`, - }, - }) + const subprocess = execa( + `node`, + [require.resolve(`gatsby-recipes/dist/graphql-server/server.js`), port], + { + all: true, + env: { + // Chalk doesn't want to output color in a child process + // as it (correctly) thinks it's not in a normal terminal environemnt. + // Since we're just returning data, we'll override that. + FORCE_COLOR: `true`, + }, + } + ) // eslint-disable-next-line no-unused-expressions subprocess.stderr?.on(`data`, data => { diff --git a/packages/gatsby-recipes/src/graphql-server/server.js b/packages/gatsby-recipes/src/graphql-server/server.js index c9e32cb63d367..244b38521b602 100644 --- a/packages/gatsby-recipes/src/graphql-server/server.js +++ b/packages/gatsby-recipes/src/graphql-server/server.js @@ -1,5 +1,9 @@ +require(`dotenv`).config() + const express = require(`express`) +const chokidar = require(`chokidar`) const graphqlHTTP = require(`express-graphql`) +const { v4: uuidv4 } = require(`uuid`) const { GraphQLSchema, GraphQLObjectType, @@ -13,6 +17,11 @@ const { createServer } = require(`http`) const { interpret } = require(`xstate`) const pkgDir = require(`pkg-dir`) const cors = require(`cors`) +const lodash = require(`lodash`) + +// Create a session id — mostly useful to tell the client when the server +// has restarted +const sessionId = uuidv4() const recipeMachine = require(`../recipe-machine`) const createTypes = require(`../create-types`) @@ -22,55 +31,76 @@ const SITE_ROOT = pkgDir.sync(process.cwd()) const pubsub = new PubSub() const PORT = process.argv[2] || 50400 -const emitOperation = state => { - console.log(state) - pubsub.publish(`operation`, { - state: JSON.stringify(state), - }) +let lastState = {} +const emitUpdate = state => { + // eslint-disable-next-line no-unused-vars + const { lastEvent, ...cleanedState } = state + if (!lodash.isEqual(cleanedState, lastState)) { + pubsub.publish(`operation`, { + state: JSON.stringify(cleanedState), + }) + + lastState = cleanedState + } } // only one service can run at a time. let service -const applyPlan = ({ recipePath, projectRoot }) => { +const startRecipe = ({ recipePath, projectRoot }) => { const initialState = { context: { recipePath, projectRoot, steps: [], currentStep: 0 }, value: `init`, } - // Interpret the machine, and add a listener for whenever a transition occurs. - service = interpret( - recipeMachine.withContext(initialState.context) - ).onTransition(state => { - // Don't emit again unless there's a state change. - console.log(`===onTransition`, { - event: state.event, - state: state.value, - context: state.context, - stepResources: state.context.stepResources, - plan: state.context.plan, - }) - if (state.changed) { - console.log(`===state.changed`, { + const startService = () => { + // Interpret the machine, and add a listener for whenever a transition occurs. + service = interpret( + recipeMachine.withContext(initialState.context) + ).onTransition(state => { + // Don't emit again unless there's a state change. + console.log(`===onTransition`, { + event: state.event, state: state.value, - currentStep: state.context.currentStep, }) - // Wait until plans are created before updating the UI - if (state.value !== `creatingPlan`) { - emitOperation({ - context: state.context, - lastEvent: state.event, - value: state.value, + if (state.changed) { + console.log(`===state.changed`, { + state: state.value, + currentStep: state.context.currentStep, }) + // Wait until plans are created before updating the UI + if ( + [`presentPlan`, `done`, `doneError`, `applyingPlan`].includes( + state.value + ) + ) { + emitUpdate({ + context: state.context, + lastEvent: state.event, + value: state.value, + }) + } } - } - }) - // Start the service - try { - service.start() - } catch (e) { - console.log(`recipe machine failed to start`, e) + if (state.value === `done`) { + service.stop() + } + }) + + // Start the service + try { + service.start() + } catch (e) { + console.log(`recipe machine failed to start`, e) + } } + + chokidar + .watch(initialState.context.recipePath) + .on(`change`, (filename, stats) => { + startService() + }) + + startService() } const OperationType = new GraphQLObjectType({ @@ -99,18 +129,22 @@ const rootMutationType = new GraphQLObjectType({ projectRoot: { type: GraphQLString }, }, resolve: (_data, args) => { - console.log(`received operation`, args.recipePath) - applyPlan(args) + console.log(`received operation`, args) + startRecipe(args) }, }, sendEvent: { type: GraphQLString, args: { event: { type: GraphQLString }, + input: { type: GraphQLString }, }, resolve: (_, args) => { - console.log(`event received`, args) - service.send(args.event) + console.log(`!!! event received`, args) + service.send({ + type: args.event, + data: args.input && JSON.parse(args.input), + }) }, }, } @@ -139,7 +173,7 @@ const schema = new GraphQLSchema({ const app = express() const server = createServer(app) -console.log(`listening on localhost:4000`) +console.log(`listening on localhost:${PORT}`) app.use(cors()) @@ -152,6 +186,15 @@ app.use( }) ) +app.use(`/session`, (req, res) => { + res.send(sessionId) +}) + +// DEBUGGING +app.use(`/service`, (req, res) => { + res.json(service) +}) + server.listen(PORT, () => { new SubscriptionServer( { diff --git a/packages/gatsby-recipes/src/graphql-server/start-dev-cli-server.js b/packages/gatsby-recipes/src/graphql-server/start-dev-cli-server.js new file mode 100644 index 0000000000000..0f49bb53a3852 --- /dev/null +++ b/packages/gatsby-recipes/src/graphql-server/start-dev-cli-server.js @@ -0,0 +1,37 @@ +const { createServiceLock } = require(`gatsby-core-utils/dist/service-lock`) +const execa = require(`execa`) + +const startServer = async () => { + // Use 50400 as our port as it's a highly composite number! Meaning it has + // more divisors than any smaller positive integer. + const port = 50400 + await createServiceLock(process.cwd(), `recipesgraphqlserver`, { port }) + + const subprocess = execa(`node`, [require.resolve(`./server.js`), port], { + all: true, + env: { + // Chalk doesn't want to output color in a child process + // as it (correctly) thinks it's not in a normal terminal environemnt. + // Since we're just returning data, we'll override that. + FORCE_COLOR: `true`, + }, + }) + + // eslint-disable-next-line no-unused-expressions + subprocess.stderr?.on(`data`, data => { + console.log(data.toString()) + }) + + // eslint-disable-next-line no-unused-expressions + subprocess.stdout?.on(`data`, data => { + console.log(data.toString()) + }) + + process.on(`exit`, () => { + subprocess.kill(`SIGTERM`, { + forceKillAfterTimeout: 2000, + }) + }) +} + +startServer() diff --git a/packages/gatsby-recipes/src/gui.js b/packages/gatsby-recipes/src/gui.js new file mode 100644 index 0000000000000..2243374eb6742 --- /dev/null +++ b/packages/gatsby-recipes/src/gui.js @@ -0,0 +1,1015 @@ +/** @jsx jsx */ +import { jsx, ThemeProvider as ThemeUIProvider, Styled } from "theme-ui" +const lodash = require(`lodash`) +// eslint-disable-next-line +const React = require(`react`) +const { useState } = require(`react`) +const ansi2HTML = require(`ansi-html`) +const remove = require(`unist-util-remove`) +const { Global } = require(`@emotion/core`) +// const ws = require(`ws`) +const fetch = require(`isomorphic-fetch`) +import { MdRefresh, MdBrightness1 } from "react-icons/md" +import { keyframes } from "@emotion/core" +import MDX from "./components/mdx" + +const { + Button, + ThemeProvider, + TextAreaField, + TextAreaFieldControl, + getTheme, + BaseAnchor, + Heading, + SuccessIcon, + InputField, + InputFieldLabel, + InputFieldControl, +} = require(`gatsby-interface`) +const { + createClient, + useMutation, + useSubscription, + Provider, + defaultExchanges, + subscriptionExchange, +} = require(`urql`) +const UrqlProvider = Provider +const { SubscriptionClient } = require(`subscriptions-transport-ws`) +const slugify = require(`slugify`) +require(`normalize.css`) + +import { InputProvider } from "./renderer/input-provider" +import { ResourceProvider } from "./renderer/resource-provider" + +const theme = getTheme() + +ansi2HTML.setColors({ + red: theme.tones.DANGER.medium.slice(1), + green: theme.tones.SUCCESS.medium.slice(1), + yellow: theme.tones.WARNING.medium.slice(1), +}) + +// const InputFieldBlock = React.forwardRef((props, ref) => { +// const { +// id, +// label, +// labelSize, +// error, +// hint, +// className, +// validationMode, +// layout, +// ...rest +// } = props + +// const hasError = false + +// return ( +// +// +// +// {label} +// +// +// {hint} +// +// {error} +// +// +// +// ) +// }) + +const makeResourceId = res => { + if (!res.describe) { + res.describe = `` + } + const id = encodeURIComponent(`${res.resourceName}-${slugify(res.describe)}`) + return id +} + +let sendEvent + +const PROJECT_ROOT = + `/Users/kylemathews/programs/recipes-test` && + `/Users/johno-mini/c/gatsby/starters/blog` + +const Spinner = () => Loading... + +const escapeTags = str => str.replace(/ ( + theme.tones.BRAND.superLight, + borderRadius: 2, + padding: 4, + }} + dangerouslySetInnerHTML={{ + __html: ansi2HTML(escapeTags(resourcePlan.diff)), + }} + /> +) + +const Diff = ({ resourcePlan, ...props }) => { + if (!resourcePlan.diff) { + return null + } + + if (resourcePlan.resourceName === `File`) { + return ( +
theme.tones.BRAND.superLight, + border: theme => `1px solid ${theme.tones.BRAND.lighter}`, + borderRadius: 2, + }} + > + `1px solid ${theme.tones.BRAND.lighter}`, + }} + > + {resourcePlan.resourceDefinitions.path} + + +
+ ) + } + + return ( + `1px solid ${theme.tones.BRAND.lighter}`, + }} + /> + ) +} + +const WelcomeMessage = () => ( +
theme.tones.BRAND.superLight, + border: theme => `1px solid ${theme.tones.BRAND.light}`, + padding: 4, + }} + > + + Thank you for trying the experimental version of Gatsby Recipes! 🤗 + + + Please ask questions, share your recipes, report bugs, and subscribe for + updates in our umbrella issue at{` `} + + https://github.com/gatsbyjs/gatsby/issues/22991 + + +
+) + +const RecipesList = ({ setRecipe }) => { + const items = [ + { + label: `Add a custom ESLint config`, + value: `eslint.mdx`, + }, + { + label: `Add Jest`, + value: `jest.mdx`, + }, + { + label: `Add Gatsby Theme Blog`, + value: `gatsby-theme-blog`, + }, + { + label: `Add persistent layout component with gatsby-plugin-layout`, + value: `gatsby-plugin-layout`, + }, + { + label: `Add Theme UI`, + value: `theme-ui.mdx`, + }, + { + label: `Add Emotion`, + value: `emotion.mdx`, + }, + { + label: `Add support for MDX Pages`, + value: `mdx-pages.mdx`, + }, + { + label: `Add support for MDX Pages with images`, + value: `mdx-images.mdx`, + }, + { + label: `Add Styled Components`, + value: `styled-components.mdx`, + }, + { + label: `Add Tailwind`, + value: `tailwindcss.mdx`, + }, + { + label: `Add Sass`, + value: `sass.mdx`, + }, + { + label: `Add Typescript`, + value: `typescript.mdx`, + }, + { + label: `Add Cypress testing`, + value: `cypress.mdx`, + }, + { + label: `Add animated page transition support`, + value: `animated-page-transitions.mdx`, + }, + { + label: `Add plugins to make site a PWA`, + value: `pwa.mdx`, + }, + { + label: `Add React Helmet`, + value: `gatsby-plugin-react-helmet.mdx`, + }, + { + label: `Add Storybook - JavaScript`, + value: `storybook-js.mdx`, + }, + { + label: `Add Storybook - TypeScript`, + value: `storybook-ts.mdx`, + }, + // TODO remaining recipes + ] + + return ( + + ) +} + +const components = { + Config: () => null, + GatsbyPlugin: () => null, + NPMPackageJson: () => null, + NPMPackage: () => null, + File: () => null, + Input: () => null, + Directory: () => null, + GatsbyShadowFile: () => null, + NPMScript: () => null, + RecipeIntroduction: props =>
{props.children}
, + RecipeStep: props =>
{props.children}
, + ContentfulSpace: () => null, + ContentfulEnvironment: () => null, + ContentfulType: () => null, +} + +const log = (label, textOrObj) => { + console.log(label, textOrObj) +} + +log( + `started client`, + `======================================= ${new Date().toJSON()}` +) + +const removeJsx = () => tree => { + remove(tree, `export`, () => true) + return tree +} + +const recipe = `styled-components.mdx` +// recipe = `jest.mdx`, +// recipe, +const graphqlPort = 50400 +const projectRoot = PROJECT_ROOT + +const API_ENDPOINT = `http://localhost:${graphqlPort}` +const GRAPHQL_ENDPOINT = `${API_ENDPOINT}/graphql` + +const subscriptionClient = new SubscriptionClient( + `ws://localhost:${graphqlPort}/graphql`, + { + reconnect: true, + } + // ws +) + +let isSubscriptionConnected = false +let isRecipeStarted = false +let sessionId +subscriptionClient.connectionCallback = async () => { + isSubscriptionConnected = true +} + +const checkServerSession = async () => { + const response = await fetch(`${API_ENDPOINT}/session`) + const newSessionId = await response.text() + if (!sessionId) { + sessionId = newSessionId + } else if (newSessionId !== sessionId) { + window.location.reload() + } +} + +let showRecipesList = false + +if (!recipe) { + showRecipesList = true +} + +const client = createClient({ + fetch, + url: GRAPHQL_ENDPOINT, + exchanges: [ + ...defaultExchanges, + subscriptionExchange({ + forwardSubscription(operation) { + return subscriptionClient.request(operation) + }, + }), + ], +}) + +const ResourcePlan = ({ resourcePlan, isLastPlan }) => ( +
+
+ + {resourcePlan.resourceName} + {` `}—{` `} + {resourcePlan.describe} + +
+ + {resourcePlan.resourceChildren + ? resourcePlan.resourceChildren.map(resource => ( + + )) + : null} +
+) + +const Step = ({ state, step, i }) => { + const stepResources = state.context?.plan?.filter( + p => parseInt(p._stepMetadata.step, 10) === i + 1 + ) + + return ( +
`1px solid ${theme.tones.BRAND.light}`, + marginBottom: 7, + }} + > +
theme.tones.BRAND.dark, + right: `6px`, + top: `6px`, + border: theme => `1px solid ${theme.tones.BRAND.light}`, + borderRadius: 9999, + height: 30, + width: 30, + display: `flex`, + alignContent: `center`, + justifyContent: `center`, + lineHeight: `28px`, + }} + > + {i + 1} +
+
*": { + marginY: 0, + }, + borderTopLeftRadius: 2, + borderTopRightRadius: 2, + borderBottom: theme => `1px solid ${theme.tones.BRAND.light}`, + background: theme => theme.tones.BRAND.lighter, + padding: 4, + }} + > +
+ + {state.context.exports?.join(`\n`) + `\n\n` + step} + +
+
+ {stepResources?.length > 0 && ( +
+
+ {stepResources?.map((res, i) => { + if (res.resourceName === `Input`) { + if (res.type === `textarea`) { + return ( +
+ +
+ {res.label} +
+ { + sendInputEvent({ + uuid: res._uuid, + key: res._key, + value: e.target.value, + }) + }} + /> +
+
+ ) + } + return ( +
+ +
+ {res.label} +
+ { + sendInputEvent({ + uuid: res._uuid, + key: res._key, + value: e.target.value, + }) + }} + /> +
+
+ ) + } + + return null + })} +
+
+ theme.tones.NEUTRAL.darker, + fontWeight: 500, + }} + as={`h3`} + > + Proposed changes + + {stepResources?.map((res, i) => { + if (res.resourceName !== `Input`) { + return ( + + ) + } + + return null + })} +
+
+ )} +
+ ) +} + +const sendInputEvent = event => { + sendEvent({ + event: `INPUT_ADDED`, + input: event, + }) +} + +const ResourceMessage = ({ state, resource }) => { + let icon = ( + + ) + let message = resource.describe + + if (state.value === `applyingPlan` && resource.isDone) { + icon = + } else if (state.value === `applyingPlan`) { + const keyframe = keyframes` + 0% { + transform: rotate(0); + } + 100% { + transform: rotate(360deg); + } +` + icon = ( + + ) + message = resource.describe + } else if (state.value === `done`) { + icon = + message = resource._message + } + + return ( + <> + {icon} + {` `} + { + e.preventDefault() + const target = document.getElementById(e.currentTarget.hash.slice(1)) + target.scrollIntoView({ + behavior: `smooth`, // smooth scroll + block: `start`, // the upper border of the element will be aligned at the top of the visible part of the window of the scrollable area. + }) + }} + > + {message} + + + ) +} + +const ButtonText = state => { + if (state.value === `done`) { + return `Refresh State` + } + + return `Install Recipe` +} + +const ResourceChildren = ({ resourceChildren, state }) => { + if (!resourceChildren || !resourceChildren.length) { + return null + } + + return ( + + {resourceChildren.map(resource => ( + + + + + ))} + + ) +} + +function Wrapper({ children }) { + return
{children}
+} + +const RecipeInterpreter = () => { + // eslint-disable-next-line + const [localRecipe, setRecipe] = useState(recipe) + + const [subscriptionResponse] = useSubscription( + { + query: ` + subscription { + operation { + state + } + } + `, + }, + (_prev, now) => now + ) + + // eslint-disable-next-line + const [_, createOperation] = useMutation(` + mutation ($recipePath: String!, $projectRoot: String!) { + createOperation(recipePath: $recipePath, projectRoot: $projectRoot) + } + `) + // eslint-disable-next-line + const [__, _sendEvent] = useMutation(` + mutation($event: String!, $input: String) { + sendEvent(event: $event, input: $input) + } + `) + + sendEvent = ({ event, input }) => { + if (input) { + _sendEvent({ event, input: JSON.stringify(input) }) + } else { + _sendEvent({ event }) + } + } + + const startRecipe = async () => { + if (!showRecipesList) { + log(`createOperation`) + if (!isRecipeStarted) { + isRecipeStarted = true + try { + await createOperation({ recipePath: localRecipe, projectRoot }) + } catch (e) { + log(`error creating operation`, e) + isRecipeStarted = false + } + } + + checkServerSession() + } + } + + subscriptionClient.connectionCallback = async () => { + checkServerSession() + startRecipe() + } + + if (isSubscriptionConnected) { + startRecipe() + } + + const state = + subscriptionResponse.data && + JSON.parse(subscriptionResponse.data.operation.state) + + if (showRecipesList) { + return ( + + + Select a recipe to run + { + showRecipesList = false + try { + await createOperation({ + recipePath: recipeItem, + projectRoot, + }) + } catch (e) { + log(`error creating operation`, e) + } + }} + /> + + ) + } + + if (!state) { + return ( + + Loading recipe + + ) + } + + const isDone = state.value === `done` + + if (state.value === `doneError`) { + console.log(`doneError state`, state) + } + + log(`state`, state) + log(`plan`, state.context.plan) + log(`stepResources`, state.context.stepResources) + + const staticMessages = {} + for (let step = 0; step < state.context.currentStep; step++) { + staticMessages[step] = [ + { + type: `mdx`, + key: `mdx-${step}`, + value: state.context.steps[step], + }, + ] + } + lodash.flattenDeep(state.context.stepResources).forEach((res, i) => { + staticMessages[res._currentStep].push({ + type: `resource`, + key: `finished-stuff-${i}`, + value: res._message, + }) + }) + + log(`staticMessages`, staticMessages) + log(`renderTime`, new Date()) + + if (isDone) { + process.nextTick(() => { + subscriptionClient.close() + log(`The recipe finished successfully`) + lodash.flattenDeep(state.context.stepResources).forEach((res, i) => { + log(`✅ ${res._message}\n`) + }) + }) + } + + const plansWithoutInputs = state.context.plan?.filter( + p => p.resourceName !== `Input` + ) + + const groupedPlans = lodash.groupBy(plansWithoutInputs, p => p.resourceName) + + return ( + <> + {` `} + p.resourceName !== `Input` && p.resourceDefinitions?._key + ) || [] + } + > + + + +
+
+ + {state.context.exports?.join(`\n`) + + `\n\n` + + state.context.steps[0]} + +
+ +
+
+ + {plansWithoutInputs?.length} + {` `} + Changes + + {Object.entries(groupedPlans).map(([resourceName, plans]) => ( +
+ + {resourceName} + + + {plans + .filter(p => p.resourceName !== `Input`) + .map((p, i) => ( + + + + + ))} + +
+ ))} +
+ + + {state.context.steps.length - 1} Steps + + {state.context.steps.slice(1).map((step, i) => ( + + ))} +
+
+
+ + ) +} + +const WithProviders = ({ children }) => { + const baseTheme = getTheme() + + const theme = { + ...baseTheme, + colors: { + ...baseTheme.colors, + background: `white`, + }, + fontWeights: { + ...baseTheme.fontWeights, + }, + styles: { + h1: { + fontSize: 6, + fontFamily: `heading`, + fontWeight: `heading`, + mt: 0, + mb: 4, + }, + h2: { + fontSize: 5, + fontFamily: `heading`, + fontWeight: `heading`, + mt: 0, + mb: 4, + }, + p: { + color: baseTheme.tones.NEUTRAL.dark, + fontSize: 2, + fontFamily: `body`, + fontWeight: `body`, + mt: 0, + mb: 4, + lineHeight: 1.45, + }, + pre: { + fontFamily: baseTheme.fonts.monospace, + fontSize: 0, + lineHeight: 1.45, + mt: 0, + mb: 6, + whiteSpace: `pre-wrap`, + }, + inlineCode: { + backgroundColor: `hsla(0,0%,0%,0.06)`, + color: baseTheme.tones.NEUTRAL.darker, + borderRadius: `3px`, + py: `0.2em`, + px: `0.2em`, + fontSize: `90%`, + }, + ol: { + color: baseTheme.tones.NEUTRAL.dark, + paddingLeft: 8, + mt: 0, + mb: 6, + fontFamily: `body`, + fontWeight: `body`, + }, + ul: { + color: baseTheme.tones.NEUTRAL.dark, + paddingLeft: 8, + mt: 0, + mb: 6, + fontFamily: `body`, + fontWeight: `body`, + }, + li: { + color: baseTheme.tones.NEUTRAL.dark, + mb: 2, + fontFamily: `body`, + fontWeight: `body`, + lineHeight: 1.6, + }, + }, + } + + return ( + + + +
{children}
+
+
+
+ ) +} + +const GlobalStyles = () => ( + +) + +export default () => ( + + + + +) diff --git a/packages/gatsby-recipes/src/index.js b/packages/gatsby-recipes/src/index.js index c48bc30eb1a28..c152ecc7bb585 100644 --- a/packages/gatsby-recipes/src/index.js +++ b/packages/gatsby-recipes/src/index.js @@ -1,8 +1,7 @@ import cli from "./cli" - -export { startGraphQLServer } from "./graphql-server" +import startGraphQLServer from "./graphql-server" // data = { recipe?: string, graphqlPort: number, projectRoot: string } const recipesHandler = async data => cli(data) -export default recipesHandler +export { startGraphQLServer, recipesHandler } diff --git a/packages/gatsby-recipes/src/parser/__snapshots__/index.test.js.snap b/packages/gatsby-recipes/src/parser/__snapshots__/index.test.js.snap deleted file mode 100644 index 912293949143d..0000000000000 --- a/packages/gatsby-recipes/src/parser/__snapshots__/index.test.js.snap +++ /dev/null @@ -1,102 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`fetches a recipe from unpkg when official short form 1`] = ` -Array [ - "# Setup Theme UI - -This recipe helps you start developing with the [Theme UI](https://theme-ui.com) styling library. - - -", - "Install packages. - - - - -", - "Add the plugin \`gatsby-plugin-theme-ui\` to your \`gatsby-config.js\`. - - -", - "Write out Theme UI configuration files. - - - - -", - "**Success**! - -You're ready to get started! - -- Read the docs: -- Learn about the theme specification: - -_note:_ if you're running this recipe on the default starter (or any other starter with -base css), you'll need to remove the require to \`layout.css\` in the \`components/layout.js\` file -as otherwise they'll override some theme-ui styles. -", -] -`; - -exports[`partitions the MDX into steps 1`] = ` -Array [ - "# Automatically run Prettier on Git commits - -Make sure all of your code is run through Prettier when you commit it to git. -We achieve this by configuring prettier to run on git hooks using husky and -lint-staged. -", - "Install packages. - - - - -", - "Implement git hooks for prettier. - - - -", - "Write prettier config files. - - - -", - "Prettier, husky, and lint-staged are now installed! You can edit your \`.prettierrc\` -if you'd like to change your prettier configuration. -", -] -`; diff --git a/packages/gatsby-recipes/src/parser/index.js b/packages/gatsby-recipes/src/parser/index.js index 921465aa81255..759605f601727 100644 --- a/packages/gatsby-recipes/src/parser/index.js +++ b/packages/gatsby-recipes/src/parser/index.js @@ -1,20 +1,61 @@ const unified = require(`unified`) const remarkMdx = require(`remark-mdx`) +const remarkMdxjs = require(`remark-mdxjs`) const remarkParse = require(`remark-parse`) const remarkStringify = require(`remark-stringify`) const fetch = require(`node-fetch`) const fs = require(`fs-extra`) const isUrl = require(`is-url`) const path = require(`path`) +const visit = require(`unist-util-visit`) +const remove = require(`unist-util-remove`) -const asRoot = nodes => { +const { uuid } = require(`./util`) + +const IGNORED_COMPONENTS = [`RecipeIntroduction`, `RecipeStep`] + +const asRoot = node => { return { type: `root`, - children: nodes, + children: [node], } } -const u = unified().use(remarkParse).use(remarkStringify).use(remarkMdx) +const pluckExports = tree => { + let exports = [] + visit(tree, `export`, node => { + exports.push(node) + }) + + remove(tree, `export`) + + return exports +} + +const applyUuid = tree => { + visit(tree, `mdxBlockElement`, node => { + if (!IGNORED_COMPONENTS.includes(node.name)) { + node.attributes.push({ + type: `mdxAttribute`, + name: `_uuid`, + value: uuid(), + }) + node.attributes.push({ + type: `mdxAttribute`, + name: `_type`, + value: node.name, + }) + } + }) + + return tree +} + +const u = unified() + .use(remarkParse) + .use(remarkStringify) + .use(remarkMdx) + .use(remarkMdxjs) const partitionSteps = ast => { const steps = [] @@ -34,18 +75,53 @@ const partitionSteps = ast => { } const toMdx = nodes => { - const stepAst = asRoot(nodes) - return u.stringify(stepAst) + const stepAst = applyUuid(asRoot(nodes)) + const mdxSrc = u.stringify(stepAst) + + return mdxSrc } const parse = async src => { try { const ast = u.parse(src) - const steps = partitionSteps(ast) + const exportNodes = pluckExports(ast) + const [intro, ...resourceSteps] = partitionSteps(ast) + + const wrappedIntroStep = { + type: `mdxBlockElement`, + name: `RecipeIntroduction`, + attributes: [], + children: intro, + } + + const wrappedResourceSteps = resourceSteps.map((step, i) => { + return { + type: `mdxBlockElement`, + name: `RecipeStep`, + attributes: [ + { + type: `mdxAttribute`, + name: `step`, + value: String(i + 1), + }, + { + type: `mdxAttribute`, + name: `totalSteps`, + value: String(resourceSteps.length), + }, + ], + children: step, + } + }) + + const steps = [wrappedIntroStep, ...wrappedResourceSteps] + ast.children = [...exportNodes, ...ast.children] return { ast, steps, + exports: exportNodes, + exportsAsMdx: exportNodes.map(toMdx), stepsAsMdx: steps.map(toMdx), } } catch (e) { diff --git a/packages/gatsby-recipes/src/parser/index.test.js b/packages/gatsby-recipes/src/parser/index.test.js index 7647167b24e1b..39b9f5205a800 100644 --- a/packages/gatsby-recipes/src/parser/index.test.js +++ b/packages/gatsby-recipes/src/parser/index.test.js @@ -13,7 +13,10 @@ jest.setTimeout(100000) test(`fetches a recipe from unpkg when official short form`, async () => { const result = await parser(`theme-ui`) - expect(result.stepsAsMdx).toMatchSnapshot() + expect(result.stepsAsMdx[0]).toMatch(`# Setup Theme UI`) + expect(result.stepsAsMdx[1]).toMatch(`Install packages`) + expect(result.stepsAsMdx[1]).toMatch(` { +// XXX: This needs to be updated for MDX v2, there error will be native +// from the parser and we're currently swallowing it +test.skip(`validate returns a syntax error`, () => { const result = validate(fixture) expect(result.line).toEqual(7) diff --git a/packages/gatsby-recipes/src/providers/contentful/client.js b/packages/gatsby-recipes/src/providers/contentful/client.js new file mode 100644 index 0000000000000..a924d4695daf9 --- /dev/null +++ b/packages/gatsby-recipes/src/providers/contentful/client.js @@ -0,0 +1,11 @@ +import { createClient } from "contentful-management" + +let client + +if (process.env.CONTENTFUL_ACCESS_TOKEN) { + client = createClient({ + accessToken: process.env.CONTENTFUL_ACCESS_TOKEN, + }) +} + +export default client diff --git a/packages/gatsby-recipes/src/providers/contentful/entry.js b/packages/gatsby-recipes/src/providers/contentful/entry.js new file mode 100644 index 0000000000000..191e80d6b1518 --- /dev/null +++ b/packages/gatsby-recipes/src/providers/contentful/entry.js @@ -0,0 +1,80 @@ +import Joi from "@hapi/joi" + +import resourceSchema from "../resource-schema" +import client from "./client" +const getDiff = require(`../utils/get-diff`) + +const create = async (context, { fields }) => { + const spaceId = context.ContentfulSpace.id + const contentTypeId = context.ContentfulType.id + const space = await client.getSpace(spaceId) + + const entry = await space.createEntryWithId(contentTypeId, `pizza-face`, { + fields: { + title: { + "en-US": fields.title, + }, + body: { + "en-US": fields.body, + }, + }, + }) + + await entry.publish() + + console.log(`new entry`, entry) + + return { + ...entry, + id: entry.sys.id, + _message: message(entry), + } +} + +const read = async (context, name) => {} + +const destroy = async (_context, id) => {} + +const all = async () => {} + +const schema = { + fields: Joi.object(), + sys: Joi.object(), + ...resourceSchema, +} + +const validate = resource => + Joi.validate(resource, schema, { abortEarly: false }) + +const plan = async (context, { id, fields }) => { + // const currentResource = await read(context, id) + let currentResource + console.log({ context }) + + if (!currentResource) { + return { + currentState: ``, + describe: `Create Contentful entry for "${context.ContentfulType.name}"`, + diff: getDiff({}, fields), + // diffExists: true, + // skipDiff: true, + } + } else { + return { + currentState: currentResource, + describe: `Contentful type ${currentResource.name} already exists`, + // diff: getDiff(plan.currentState, plan.newState), + } + } +} + +const message = resource => `Created Contentful Entry "${resource.name}"` + +module.exports.schema = schema +module.exports.validate = validate +module.exports.plan = plan +module.exports.create = create +module.exports.read = read +module.exports.update = create +module.exports.destroy = destroy +module.exports.all = all diff --git a/packages/gatsby-recipes/src/providers/contentful/environment.js b/packages/gatsby-recipes/src/providers/contentful/environment.js new file mode 100644 index 0000000000000..67b16a4b56f48 --- /dev/null +++ b/packages/gatsby-recipes/src/providers/contentful/environment.js @@ -0,0 +1,65 @@ +import Joi from "@hapi/joi" + +import client from "./client" +import resourceSchema from "../resource-schema" + +const create = async (context, { name }) => { + const spaceId = context.ContentfulSpace.id + const space = await client.getSpace(spaceId) + const environment = await space.createEnvironment({ name }) + + return { + name: environment.name, + id: environment.sys.id, + _message: message(environment), + } +} + +const read = async (context, name) => { + console.log({ context, name }) + + return undefined +} + +const destroy = async (_context, id) => {} + +const all = async () => {} + +const schema = { + name: Joi.string(), + ...resourceSchema, +} + +const validate = resource => + Joi.validate(resource, schema, { abortEarly: false }) + +const plan = async (context, { id, name }) => { + console.log({ context, name, id }) + const currentResource = await read(context, id || name) + + if (!currentResource) { + return { + currentState: ``, + describe: `Create Contentful environment ${name}`, + diffExists: true, + skipDiff: true, + } + } else { + return { + currentState: currentResource, + describe: `Contentful environment ${name} already exists`, + diff: ``, + } + } +} + +const message = resource => `Created Contentful environment "${resource.name}"` + +module.exports.schema = schema +module.exports.validate = validate +module.exports.plan = plan +module.exports.create = create +module.exports.read = read +module.exports.update = create +module.exports.destroy = destroy +module.exports.all = all diff --git a/packages/gatsby-recipes/src/providers/contentful/space.js b/packages/gatsby-recipes/src/providers/contentful/space.js new file mode 100644 index 0000000000000..d206c86f88962 --- /dev/null +++ b/packages/gatsby-recipes/src/providers/contentful/space.js @@ -0,0 +1,94 @@ +import Joi from "@hapi/joi" + +import client from "./client" +import resourceSchema from "../resource-schema" + +const create = async (_context, { name }) => { + const space = await client.createSpace({ name }) + const deliveryAccessToken = await space.createApiKey({ + name: `gatsby`, + }) + + return { + name: space.name, + id: space.sys.id, + deliveryAccessToken: deliveryAccessToken.accessToken, + _message: message(space), + } +} + +const read = async (_context, name) => { + const spaces = await all() + console.log(`all spaces`, spaces) + + if (!spaces) { + return null + } + + const space = spaces.find(s => s.name === name) + + return { + ...space, + id: space.sys.id, + } +} + +const destroy = async (_context, id) => { + const space = await client.getSpace(id) + + const spaceResource = { + name: space.name, + id: space.sys.id, + } + + await space.delete() + + return spaceResource +} + +const all = async () => { + const spaces = client.getSpaces() + + return spaces.items +} + +const schema = { + name: Joi.string(), + ...resourceSchema, +} + +const validate = resource => + Joi.validate(resource, schema, { abortEarly: false }) + +const plan = async (context, { id, name }) => { + const currentResource = await read(context, id || name) + + if (!currentResource) { + return { + name, + id: `(Known after install)`, + deliveryAccessToken: `(Known after install)`, + currentState: ``, + describe: `Create Contentful space "${name}"`, + diffExists: true, + skipDiff: true, + } + } else { + return { + currentState: currentResource, + describe: `Contentful space ${name} already exists`, + diff: ``, + } + } +} + +const message = resource => `Created Contentful space ${resource.name}` + +module.exports.schema = schema +module.exports.validate = validate +module.exports.plan = plan +module.exports.create = create +module.exports.read = read +module.exports.update = create +module.exports.destroy = destroy +module.exports.all = all diff --git a/packages/gatsby-recipes/src/providers/contentful/type.js b/packages/gatsby-recipes/src/providers/contentful/type.js new file mode 100644 index 0000000000000..ef4586eff81a2 --- /dev/null +++ b/packages/gatsby-recipes/src/providers/contentful/type.js @@ -0,0 +1,75 @@ +import Joi from "@hapi/joi" + +import client from "./client" +import resourceSchema from "../resource-schema" +import getGraphqlFields from "../utils/get-graphql-fields" +const getDiff = require(`../utils/get-diff`) + +const GRAPHQL_FIELD_OPTIONS = { + metadata: [`type`, `name`], +} + +const create = async (context, { schema }) => { + const spaceId = context.ContentfulSpace.id + const space = await client.getSpace(spaceId) + + const fields = getGraphqlFields(schema, GRAPHQL_FIELD_OPTIONS)[0] + const contentType = await space.createContentTypeWithId(fields.name, fields) + await contentType.publish() + + return { + name: contentType.name, + id: contentType.sys.id, + _message: message(contentType), + } +} + +const read = async (context, name) => {} + +const destroy = async (_context, id) => {} + +const all = async () => {} + +const schema = { + schema: Joi.string(), + ...resourceSchema, +} + +const validate = resource => + Joi.validate(resource, schema, { abortEarly: false }) + +const plan = async (context, { id, schema }) => { + const currentResource = await read(context, id) + + const fields = getGraphqlFields(schema, GRAPHQL_FIELD_OPTIONS)[0] + console.log(`contentful type`, { currentResource, schema, id, fields }) + + if (!currentResource) { + return { + id: `(Known after install)`, + name: fields.name, + currentState: ``, + describe: `Create Contentful type "${fields.name}"`, + diff: getDiff({}, fields), + // diffExists: true, + // skipDiff: true, + } + } else { + return { + currentState: currentResource, + describe: `Contentful type ${currentResource.name} already exists`, + // diff: getDiff(plan.currentState, plan.newState), + } + } +} + +const message = resource => `Created Contentful type "${resource.name}"` + +module.exports.schema = schema +module.exports.validate = validate +module.exports.plan = plan +module.exports.create = create +module.exports.read = read +module.exports.update = create +module.exports.destroy = destroy +module.exports.all = all diff --git a/packages/gatsby-recipes/src/providers/fs/file.js b/packages/gatsby-recipes/src/providers/fs/file.js index dcb661464e146..3065a90bb64c9 100644 --- a/packages/gatsby-recipes/src/providers/fs/file.js +++ b/packages/gatsby-recipes/src/providers/fs/file.js @@ -103,7 +103,7 @@ module.exports.plan = async (context, { id, path: filePath, content }) => { } if (plan.currentState !== plan.newState) { - plan.diff = await getDiff(plan.currentState, plan.newState) + plan.diff = getDiff(plan.currentState, plan.newState) } return plan diff --git a/packages/gatsby-recipes/src/providers/gatsby/plugin.js b/packages/gatsby-recipes/src/providers/gatsby/plugin.js index b6fd87bed5f1b..9e38c1a5857ea 100644 --- a/packages/gatsby-recipes/src/providers/gatsby/plugin.js +++ b/packages/gatsby-recipes/src/providers/gatsby/plugin.js @@ -147,13 +147,7 @@ const getPluginsFromConfig = src => { const getConfigPath = root => path.join(root, `gatsby-config.js`) -const readConfigFile = async root => { - let src - try { - src = await fs.readFile(getConfigPath(root), `utf8`) - } catch (e) { - if (e.code === `ENOENT`) { - src = `/** +const defaultConfig = `/** * Configure your Gatsby site with this file. * * See: https://www.gatsbyjs.org/docs/gatsby-config/ @@ -162,15 +156,48 @@ const readConfigFile = async root => { module.exports = { plugins: [], }` + +const readConfigFile = async root => { + let src + try { + src = await fs.readFile(getConfigPath(root), `utf8`) + } catch (e) { + if (e.code === `ENOENT`) { + src = defaultConfig } else { throw e } } + if (src === ``) { + src = defaultConfig + } + return src } +class MissingInfoError extends Error { + constructor(foo = `bar`, ...params) { + // Pass remaining arguments (including vendor specific ones) to parent constructor + super(...params) + + // Maintains proper stack trace for where our error was thrown (only available on V8) + if (Error.captureStackTrace) { + Error.captureStackTrace(this, MissingInfoError) + } + + this.name = `MissingInfoError` + // Custom debugging information + this.foo = foo + this.date = new Date() + } +} + const create = async ({ root }, { name, options, key }) => { + // TODO generalize this — it's for the demo. + if (options?.accessToken === `(Known after install)`) { + throw new MissingInfoError({ name, options, key }) + } const configSrc = await readConfigFile(root) const prettierConfig = await prettier.resolveConfig(root) @@ -358,13 +385,13 @@ const schema = { } const validate = resource => { - if (REQUIRES_KEYS.includes(resource.name) && !resource.key) { + if (REQUIRES_KEYS.includes(resource.name) && !resource._key) { return { error: `${resource.name} requires a key to be set`, } } - if (resource.key && resource.key === resource.name) { + if (resource._key && resource._key === resource.name) { return { error: `${resource.name} requires a key to be different than the plugin name`, } @@ -395,6 +422,7 @@ module.exports.plan = async ({ root }, { id, key, name, options }) => { ...prettierConfig, parser: `babel`, }) + const diff = await getDiff(configSrc, newContents) return { diff --git a/packages/gatsby-recipes/src/providers/gatsby/plugin.test.js b/packages/gatsby-recipes/src/providers/gatsby/plugin.test.js index dad936630ebd3..a34d116bb86ac 100644 --- a/packages/gatsby-recipes/src/providers/gatsby/plugin.test.js +++ b/packages/gatsby-recipes/src/providers/gatsby/plugin.test.js @@ -139,7 +139,7 @@ describe(`gatsby-plugin resource`, () => { test(`validates the gatsby-source-filesystem specifies a key that isn't equal to the name`, async () => { const result = plugin.validate({ name: `gatsby-source-filesystem`, - key: `gatsby-source-filesystem`, + _key: `gatsby-source-filesystem`, }) expect(result.error).toEqual( diff --git a/packages/gatsby-recipes/src/providers/gatsby/utils/build-plugin-node.js b/packages/gatsby-recipes/src/providers/gatsby/utils/build-plugin-node.js index 9ef055ca4711b..95bc19de6efc9 100644 --- a/packages/gatsby-recipes/src/providers/gatsby/utils/build-plugin-node.js +++ b/packages/gatsby-recipes/src/providers/gatsby/utils/build-plugin-node.js @@ -6,13 +6,16 @@ module.exports = ({ name, options, key }) => { return t.stringLiteral(name) } - const pluginWithOptions = template(` + const pluginWithOptions = template( + ` const foo = { resolve: '${name}', options: ${JSON.stringify(options, null, 2)}, ${key ? `__key: "` + key + `"` : ``} } - `)() + `, + { placeholderPattern: false } + )() return pluginWithOptions.declarations[0].init } diff --git a/packages/gatsby-recipes/src/providers/npm/__snapshots__/script.test.js.snap b/packages/gatsby-recipes/src/providers/npm/__snapshots__/script.test.js.snap index 0d0a5883178ca..5a10ce5a8dbd6 100644 --- a/packages/gatsby-recipes/src/providers/npm/__snapshots__/script.test.js.snap +++ b/packages/gatsby-recipes/src/providers/npm/__snapshots__/script.test.js.snap @@ -2,7 +2,7 @@ exports[`npm script resource e2e script resource test: NPMScript create 1`] = ` Object { - "_message": "Wrote script apple to your package.json", + "_message": "Added script \\"apple\\" to your package.json", "command": "foot", "id": "apple", "name": "apple", @@ -12,7 +12,7 @@ Object { exports[`npm script resource e2e script resource test: NPMScript create plan 1`] = ` Object { "currentState": "", - "describe": "Add new command to your package.json", + "describe": "Add script \\"apple\\" to your package.json", "diff": "- Original - 1 + Modified + 3 @@ -31,7 +31,7 @@ exports[`npm script resource e2e script resource test: NPMScript destroy 1`] = ` exports[`npm script resource e2e script resource test: NPMScript update 1`] = ` Object { - "_message": "Wrote script apple to your package.json", + "_message": "Added script \\"apple\\" to your package.json", "command": "foot2", "id": "apple", "name": "apple", @@ -41,7 +41,7 @@ Object { exports[`npm script resource e2e script resource test: NPMScript update plan 1`] = ` Object { "currentState": "\\"apple\\": \\"foot\\"", - "describe": "Add new command to your package.json", + "describe": "Add script \\"apple\\" to your package.json", "diff": "- Original - 1 + Modified + 1 diff --git a/packages/gatsby-recipes/src/providers/npm/script.js b/packages/gatsby-recipes/src/providers/npm/script.js index 1fa55c28e5f75..31c699a3fadc2 100644 --- a/packages/gatsby-recipes/src/providers/npm/script.js +++ b/packages/gatsby-recipes/src/providers/npm/script.js @@ -34,7 +34,7 @@ const read = async ({ root }, id) => { id, name: id, command: pkg.scripts[id], - _message: `Wrote script ${id} to your package.json`, + _message: `Added script "${id}" to your package.json`, } } @@ -89,7 +89,7 @@ module.exports.plan = async ({ root }, { name, command }) => { currentState, newState: scriptDescription(name, command), diff, - describe: `Add new command to your package.json`, + describe: `Add script "${name}" to your package.json`, } } diff --git a/packages/gatsby-recipes/src/providers/resource-schema.js b/packages/gatsby-recipes/src/providers/resource-schema.js index 3d7f6a9de542d..12d44937d42bc 100644 --- a/packages/gatsby-recipes/src/providers/resource-schema.js +++ b/packages/gatsby-recipes/src/providers/resource-schema.js @@ -3,5 +3,6 @@ const Joi = require(`@hapi/joi`) module.exports = { id: Joi.string(), key: Joi.string(), + _key: Joi.string(), _message: Joi.string(), } diff --git a/packages/gatsby-recipes/src/providers/utils/get-diff.js b/packages/gatsby-recipes/src/providers/utils/get-diff.js index 5e282cd54f957..7b027aa7904b6 100644 --- a/packages/gatsby-recipes/src/providers/utils/get-diff.js +++ b/packages/gatsby-recipes/src/providers/utils/get-diff.js @@ -2,7 +2,7 @@ const diff = require(`jest-diff`).default const chalk = require(`chalk`) const stripAnsi = require(`strip-ansi`) -module.exports = async (oldVal, newVal) => { +module.exports = (oldVal, newVal) => { const options = { aAnnotation: `Original`, bAnnotation: `Modified`, diff --git a/packages/gatsby-recipes/src/providers/utils/get-graphql-fields.js b/packages/gatsby-recipes/src/providers/utils/get-graphql-fields.js index 20b4040d0ac6b..55b8a37275df8 100644 --- a/packages/gatsby-recipes/src/providers/utils/get-graphql-fields.js +++ b/packages/gatsby-recipes/src/providers/utils/get-graphql-fields.js @@ -1,14 +1,18 @@ const { makeExecutableSchema } = require(`@graphql-tools/schema`) const { SchemaDirectiveVisitor } = require(`@graphql-tools/utils`) -const gqlFieldsToObject = fields => +const gqlFieldsToArray = fields => Object.entries(fields).reduce((acc, [key, value]) => { - acc[key] = { + const metadata = value.metadata || {} + const field = { + id: key, type: value.type, - metadata: value.metadata, + name: key, + ...metadata, } - return acc - }, {}) + + return [...acc, field] + }, []) class MetadataDirective extends SchemaDirectiveVisitor { visitFieldDefinition(field) { @@ -53,7 +57,7 @@ module.exports = (typeDefs, { metadata } = {}) => { .map(([key, value]) => { return { name: key, - fields: gqlFieldsToObject(value._fields), + fields: gqlFieldsToArray(value._fields), } }) } diff --git a/packages/gatsby-recipes/src/providers/utils/get-graphql-fields.test.js b/packages/gatsby-recipes/src/providers/utils/get-graphql-fields.test.js index 5670bc99024ef..02743fbea5d1d 100644 --- a/packages/gatsby-recipes/src/providers/utils/get-graphql-fields.test.js +++ b/packages/gatsby-recipes/src/providers/utils/get-graphql-fields.test.js @@ -17,19 +17,19 @@ test(`get-graphql-fields returns an array of fields`, () => { expect(result).toMatchInlineSnapshot(` Array [ Object { - "fields": Object { - "body": Object { - "metadata": Object { - "title": "Content", - "type": "Text", - }, + "fields": Array [ + Object { + "id": "title", + "name": "title", "type": "String", }, - "title": Object { - "metadata": undefined, - "type": "String", + Object { + "id": "body", + "name": "body", + "title": "Content", + "type": "Text", }, - }, + ], "name": "BlogPost", }, ] diff --git a/packages/gatsby-recipes/src/recipe-machine/__snapshots__/index.test.js.snap b/packages/gatsby-recipes/src/recipe-machine/__snapshots__/index.test.js.snap deleted file mode 100644 index 00e629826bab8..0000000000000 --- a/packages/gatsby-recipes/src/recipe-machine/__snapshots__/index.test.js.snap +++ /dev/null @@ -1,18 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`recipe-machine stores created/changed/deleted resources on the context after applying plan 1`] = ` -Array [ - Object { - "_currentStep": 1, - "_message": "Wrote file ./hi.md", - }, - Object { - "_currentStep": 1, - "_message": "Wrote file ./hi2.md", - }, - Object { - "_currentStep": 2, - "_message": "Wrote file ./hi3.md", - }, -] -`; diff --git a/packages/gatsby-recipes/src/recipe-machine/index.js b/packages/gatsby-recipes/src/recipe-machine/index.js index df30d42067c16..9fbdc107c2b10 100644 --- a/packages/gatsby-recipes/src/recipe-machine/index.js +++ b/packages/gatsby-recipes/src/recipe-machine/index.js @@ -1,4 +1,6 @@ -const { Machine, assign } = require(`xstate`) +const { Machine, assign, send } = require(`xstate`) + +const debug = require(`debug`)(`recipes-machine`) const createPlan = require(`../create-plan`) const applyPlan = require(`../apply-plan`) @@ -14,10 +16,13 @@ const recipeMachine = Machine( projectRoot: null, currentStep: 0, steps: [], + exports: [], plan: [], commands: [], stepResources: [], stepsAsMdx: [], + exportsAsMdx: [], + inputs: {}, }, states: { parsingRecipe: { @@ -26,6 +31,8 @@ const recipeMachine = Machine( src: async (context, _event) => { let parsed + debug(`parsingRecipe`) + if (context.src) { parsed = await parser.parse(context.src) } else if (context.recipePath && context.projectRoot) { @@ -38,17 +45,22 @@ const recipeMachine = Machine( ) } + debug(`parsedRecipe`) + return parsed }, onError: { target: `doneError`, actions: assign({ error: (context, event) => { + debug(`error parsing recipes`) + let msg try { msg = JSON.parse(event.data.message) return msg } catch (e) { + console.log(e) return { error: `Could not parse recipe ${context.recipePath}`, e, @@ -61,6 +73,7 @@ const recipeMachine = Machine( target: `validateSteps`, actions: assign({ steps: (context, event) => event.data.stepsAsMdx, + exports: (context, event) => event.data.exportsAsMdx, }), }, }, @@ -69,8 +82,10 @@ const recipeMachine = Machine( invoke: { id: `validateSteps`, src: async (context, event) => { + debug(`validatingSteps`) const result = await validateSteps(context.steps) if (result.length > 0) { + debug(`errors found in validation`) throw new Error(JSON.stringify(result)) } @@ -89,11 +104,12 @@ const recipeMachine = Machine( entry: [`deleteOldPlan`], invoke: { id: `createPlan`, - src: async (context, event) => { + src: (context, event) => async (cb, onReceive) => { try { - const result = await createPlan(context) + const result = await createPlan(context, cb) return result } catch (e) { + console.log(e) throw e } }, @@ -106,14 +122,41 @@ const recipeMachine = Machine( onError: { target: `doneError`, actions: assign({ - error: (context, event) => event.data.errors || event.data, + error: (context, event) => event.data?.errors || event.data, + }), + }, + }, + on: { + INVALID_PROPS: { + target: `doneError`, + actions: assign({ + error: (context, event) => event.data, }), }, }, }, presentPlan: { + invoke: { + id: `presentingPlan`, + src: (context, event) => (cb, onReceive) => { + onReceive(async e => { + context.inputs = context.inputs || {} + context.inputs[e.data.key] = e.data + const result = await createPlan(context, cb) + cb({ type: `onUpdatePlan`, data: result }) + }) + }, + }, on: { CONTINUE: `applyingPlan`, + INPUT_ADDED: { + actions: send((context, event) => event, { to: `presentingPlan` }), + }, + onUpdatePlan: { + actions: assign({ + plan: (context, event) => event.data, + }), + }, }, }, applyingPlan: { @@ -122,6 +165,7 @@ const recipeMachine = Machine( invoke: { id: `applyPlan`, src: (context, event) => cb => { + debug(`applying plan`) cb(`RESET`) if (context.plan.length === 0) { return cb(`onDone`) @@ -131,11 +175,16 @@ const recipeMachine = Machine( cb(`TICK`) }, 10000) - applyPlan(context.plan) + applyPlan(context, cb) .then(result => { + debug(`applied plan`) cb({ type: `onDone`, data: result }) }) - .catch(error => cb({ type: `onError`, data: error })) + .catch(error => { + debug(`error applying plan`) + debug(error) + cb({ type: `onError`, data: error }) + }) return () => clearInterval(interval) }, @@ -200,25 +249,32 @@ const recipeMachine = Machine( }), addResourcesToContext: assign((context, event) => { if (event.data) { - const stepResources = context.stepResources || [] - const messages = event.data.map(e => { - return { - _message: e._message, - _currentStep: context.currentStep, - } + let plan = context.plan || [] + plan = plan.map(p => { + const changedResource = event.data.find(c => { + if (c._uuid) { + return c._uuid === p._uuid + } else { + return c.resourceDefinitions._key === p.resourceDefinitions._key + } + }) + if (!changedResource) return p + p._message = changedResource._message + p.isDone = true + return p }) return { - stepResources: stepResources.concat(messages), + plan, } } return undefined }), }, guards: { - hasNextStep: (context, event) => - context.currentStep < context.steps.length, - atLastStep: (context, event) => - context.currentStep === context.steps.length, + hasNextStep: (context, event) => false, + // false || context.currentStep < context.steps.length, + atLastStep: (context, event) => true, + // true || context.currentStep === context.steps.length, }, } ) diff --git a/packages/gatsby-recipes/src/recipe-machine/index.test.js b/packages/gatsby-recipes/src/recipe-machine/index.test.js index 044030c4c0dd5..8feba8ceb1a9d 100644 --- a/packages/gatsby-recipes/src/recipe-machine/index.test.js +++ b/packages/gatsby-recipes/src/recipe-machine/index.test.js @@ -40,13 +40,9 @@ describe(`recipe-machine`, () => { recipeMachine.withContext(initialContext) ).onTransition(state => { if (state.value === `presentPlan`) { - if (state.context.currentStep === 0) { - service.send(`CONTINUE`) - } else { - expect(state.context.plan).toBeTruthy() - service.stop() - done() - } + expect(state.context.plan).toBeTruthy() + service.stop() + done() } }) @@ -84,47 +80,4 @@ describe(`recipe-machine`, () => { service.start() }) - - it(`stores created/changed/deleted resources on the context after applying plan`, done => { - const filePath = `./hi.md` - const filePath2 = `./hi2.md` - const filePath3 = `./hi3.md` - const initialContext = { - src: ` -# File! - ---- - - - - ---- - - - `, - currentStep: 0, - } - const service = interpret( - recipeMachine.withContext(initialContext) - ).onTransition(state => { - // Keep simulating moving onto the next step - if (state.value === `presentPlan`) { - service.send(`CONTINUE`) - } - if (state.value === `done`) { - // Clean up files - fs.unlinkSync(path.join(process.cwd(), filePath)) - fs.unlinkSync(path.join(process.cwd(), filePath2)) - fs.unlinkSync(path.join(process.cwd(), filePath3)) - - expect(state.context.stepResources).toHaveLength(3) - expect(state.context.stepResources).toMatchSnapshot() - expect(state.context.stepResources[0]._message).toBeTruthy() - expect(state.context.stepResources[0]._currentStep).toBeTruthy() - done() - } - }) - - service.start() - }) }) diff --git a/packages/gatsby-recipes/src/renderer/babel-plugin-copy-key-prop.js b/packages/gatsby-recipes/src/renderer/babel-plugin-copy-key-prop.js new file mode 100644 index 0000000000000..8473fcec22fa8 --- /dev/null +++ b/packages/gatsby-recipes/src/renderer/babel-plugin-copy-key-prop.js @@ -0,0 +1,17 @@ +module.exports = api => { + const { types: t } = api + + return { + visitor: { + JSXIdentifier(path) { + if (path.node.name === `key`) { + const clonePath = t.cloneNode(path.node) + const cloneParent = t.cloneNode(path.parent) + clonePath.name = `_key` + cloneParent.name = clonePath + path.parentPath.container.push(cloneParent) + } + }, + }, + } +} diff --git a/packages/gatsby-recipes/src/renderer/babel-plugin-move-export-keywords.js b/packages/gatsby-recipes/src/renderer/babel-plugin-move-export-keywords.js new file mode 100644 index 0000000000000..26e89760ffd56 --- /dev/null +++ b/packages/gatsby-recipes/src/renderer/babel-plugin-move-export-keywords.js @@ -0,0 +1,56 @@ +const _ = require(`lodash`) + +const isMDXLayout = element => element.name && element.name.name === `MDXLayout` +const isLayoutProps = declaration => declaration.id.name === `layoutProps` +const shouldRemoveDeclaration = declaration => + isLayoutProps(declaration) || isMDXLayout(declaration) + +module.exports = api => { + const { types: t } = api + let exportsToMove = [] + return { + visitor: { + ExportNamedDeclaration(path) { + const declaration = path.node.declaration + + // Ignore "export { Foo as default }" syntax + if (declaration) { + path.replaceWith(declaration) + exportsToMove.push(t.cloneNode(path.node)) + path.remove() + } + }, + VariableDeclaration(path) { + const declaration = path.node.declarations[0] + if (!declaration) { + return + } + + if (shouldRemoveDeclaration(declaration)) { + path.remove() + } + }, + FunctionDeclaration(path) { + if (path.node.id.name == `MDXContent`) { + exportsToMove = _.uniqBy( + exportsToMove, + e => e.declarations[0].id.name + ) + exportsToMove.forEach(node => + path.get(`body`).unshiftContainer(`body`, node) + ) + } + }, + // MDXLayout => div + JSXElement(path) { + const { openingElement, closingElement } = path.node + + if (isMDXLayout(openingElement)) { + openingElement.name = t.JSXIdentifier(`div`) + openingElement.attributes = [] + closingElement.name = t.JSXIdentifier(`div`) + } + }, + }, + } +} diff --git a/packages/gatsby-recipes/src/renderer/babel-plugin-remove-shortcodes.js b/packages/gatsby-recipes/src/renderer/babel-plugin-remove-shortcodes.js new file mode 100644 index 0000000000000..0b65b93419882 --- /dev/null +++ b/packages/gatsby-recipes/src/renderer/babel-plugin-remove-shortcodes.js @@ -0,0 +1,74 @@ +const isShortcode = declaration => + declaration.init?.callee?.name === `makeShortcode` +const isShortcodeFunction = declaration => + declaration.id.name === `makeShortcode` +const isMDXLayout = element => element.name && element.name.name === `MDXLayout` +const isMDXContent = declaration => declaration.id.name === `MDXContent` +const isLayoutProps = declaration => declaration.id.name === `layoutProps` +const isMDXContentStaticProperty = node => { + if (node.object.name !== `MDXContent`) { + return false + } + + return node.property.name === `isMDXComponent` +} + +const shouldRemoveDeclaration = declaration => + isShortcode(declaration) || + isShortcodeFunction(declaration) || + isMDXLayout(declaration) || + isLayoutProps(declaration) + +module.exports = api => { + const { types: t } = api + + return { + visitor: { + // Remove unneeded variables that MDX outputs but we won't use + VariableDeclaration(path) { + const declaration = path.node.declarations[0] + if (!declaration) { + return + } + + if (shouldRemoveDeclaration(declaration)) { + path.remove() + } + }, + + // Unwrap the MDXContent component instantiation because we will + // evaluate the function directly. This ensures that React properly + // handles rendering by not re-mounting the component every render. + FunctionDeclaration(path) { + if (!isMDXContent(path.node)) { + return + } + + // path.traverse({ + // ReturnStatement(innerPath) { + // path.replaceWith(innerPath.node) + // }, + // }) + }, + + // MDXLayout => doc + JSXElement(path) { + const { openingElement, closingElement } = path.node + + if (isMDXLayout(openingElement)) { + openingElement.name = t.JSXIdentifier(`doc`) + openingElement.attributes = [] + closingElement.name = t.JSXIdentifier(`doc`) + } + }, + + // Remove the MDXContent.isMDXContent = true declaration since + // we've removed MDXContent entirely + MemberExpression(path) { + if (isMDXContentStaticProperty(path.node)) { + path.parentPath.remove() + } + }, + }, + } +} diff --git a/packages/gatsby-recipes/src/renderer/index.js b/packages/gatsby-recipes/src/renderer/index.js index 575eaa4fb279a..32487ad8a2573 100644 --- a/packages/gatsby-recipes/src/renderer/index.js +++ b/packages/gatsby-recipes/src/renderer/index.js @@ -1,55 +1,50 @@ const React = require(`react`) -const mdx = require(`@mdx-js/mdx`) -const { transform } = require(`@babel/standalone`) -const babelPluginTransformReactJsx = require(`@babel/plugin-transform-react-jsx`) const { render } = require(`./render`) -const resourceComponents = require(`./resource-components`) +const { resourceComponents } = require(`./resource-components`) +const { RecipeStep, RecipeIntroduction } = require(`./step-component`) +const Input = require(`./input`).default +const { useInput, useInputByKey } = require(`./input-provider`) +const { useResource } = require(`./resource-provider`) +const { useProvider } = require(`./provider-provider`) + +const transformRecipeMDX = require(`../transform-recipe-mdx`).default const scope = { React, + RecipeStep, + RecipeIntroduction, + Input, + useInput, + useInputByKey, + useResource, + useProvider, Config: `div`, // Keep this as a noop for now ...resourceComponents, + mdx: React.createElement, + MDXContent: React.createElement, } -// We want to call the function constructor with our resulting -// transformed JS so we need to turn it into a "function body" const transformCodeForEval = code => { - const newCode = code.replace(/;$/, ``) - - return `return (${newCode})` -} - -// TODO: Release MDX v2 canary so we can avoid the hacks -const stripMdxLayout = str => { - const newJsx = str - .replace(/^.*mdxType="MDXLayout">/ms, ``) - .replace(/<\/MDXLayout>.*/ms, ``) - - return `${newJsx}` -} + // Remove the trailing semicolons so we can turn the component + // into a return statement. + let newCode = code.replace(/;\n;$/, ``) -const transformJsx = jsx => { - const { code } = transform(jsx, { - plugins: [[babelPluginTransformReactJsx, { useBuiltIns: true }]], - }) + newCode = newCode + `\nreturn React.createElement(MDXContent)` - return code + return newCode } -// This is overloaded to handle MDX input, JSX input -// or MDX's JSX output as input. -module.exports = jsx => { +module.exports = (mdxSrc, cb, context, isApply) => { const scopeKeys = Object.keys(scope) const scopeValues = Object.values(scope) - const jsxFromMdx = mdx.sync(jsx, { skipExport: true }) - const srcCode = transformJsx(stripMdxLayout(jsxFromMdx)) + const srcCode = transformRecipeMDX(mdxSrc, true) const component = new Function(...scopeKeys, transformCodeForEval(srcCode)) try { - const result = render(component(...scopeValues)) + const result = render(component(...scopeValues), cb, context, isApply) return result } catch (e) { throw e diff --git a/packages/gatsby-recipes/src/renderer/index.test.js b/packages/gatsby-recipes/src/renderer/index.test.js index f60524114c384..128126f2bc8fe 100644 --- a/packages/gatsby-recipes/src/renderer/index.test.js +++ b/packages/gatsby-recipes/src/renderer/index.test.js @@ -1,33 +1,48 @@ const render = require(`.`) +const { parse } = require(`../parser`) const mdxFixture = ` # Hello, world! - +--- + +export const fooContent = 'hiiiiii!' + + ` describe(`renderer`, () => { test(`handles MDX as input`, async () => { - const result = await render(mdxFixture) + const { stepsAsMdx, exportsAsMdx } = await parse(mdxFixture) + const result = await render([...stepsAsMdx, ...exportsAsMdx].join(`\n`)) // Gatsby latest version is ever changing so we use regex matcher for currentState property. // Unfortunately jest property matchers work weirdly on arrays so instead // of snapshotting entitre result array it's split into few pieces. expect(result.length).toEqual(3) + delete result[0]._uuid + delete result[1]._uuid + delete result[2]._uuid expect(result[0]).toMatchInlineSnapshot(` Object { + "_stepMetadata": Object { + "step": "1", + "totalSteps": "1", + }, + "_type": "File", "currentState": "", "describe": "Write foo.js", "diff": "- Original - 0 + Modified + 1 - + /** foo */", - "newState": "/** foo */", + + hiiiiii!", + "newState": "hiiiiii!", "resourceDefinitions": Object { - "content": "/** foo */", + "content": "hiiiiii!", + "mdxType": "File", "path": "foo.js", }, "resourceName": "File", @@ -35,6 +50,11 @@ describe(`renderer`, () => { `) expect(result[1]).toMatchInlineSnapshot(` Object { + "_stepMetadata": Object { + "step": "1", + "totalSteps": "1", + }, + "_type": "File", "currentState": "", "describe": "Write foo2.js", "diff": "- Original - 0 @@ -44,6 +64,7 @@ describe(`renderer`, () => { "newState": "/** foo2 */", "resourceDefinitions": Object { "content": "/** foo2 */", + "mdxType": "File", "path": "foo2.js", }, "resourceName": "File", @@ -55,10 +76,16 @@ describe(`renderer`, () => { }, ` Object { + "_stepMetadata": Object { + "step": "1", + "totalSteps": "1", + }, + "_type": "NPMPackage", "currentState": StringMatching /gatsby@\\[0-9\\.\\]\\+/, "describe": "Install gatsby@latest", "newState": "gatsby@latest", "resourceDefinitions": Object { + "mdxType": "NPMPackage", "name": "gatsby", }, "resourceName": "NPMPackage", @@ -73,6 +100,7 @@ describe(`renderer`, () => { expect(result).toMatchInlineSnapshot(` Array [ Object { + "_stepMetadata": Object {}, "currentState": "", "describe": "Write hi.md", "diff": "- Original - 0 @@ -82,6 +110,7 @@ describe(`renderer`, () => { "newState": "hi", "resourceDefinitions": Object { "content": "hi", + "mdxType": "File", "path": "hi.md", }, "resourceName": "File", @@ -90,6 +119,46 @@ describe(`renderer`, () => { `) }) + test(`handles exports and allows them to be used as local variables`, async () => { + const { stepsAsMdx, exportsAsMdx } = await parse(` +# Hello, world! + +--- + +export const myVar = 'hi.mdx' + + + `) + + const result = await render([...stepsAsMdx, ...exportsAsMdx].join(`\n`)) + result.forEach(r => delete r._uuid) + + expect(result).toMatchInlineSnapshot(` + Array [ + Object { + "_stepMetadata": Object { + "step": "1", + "totalSteps": "1", + }, + "_type": "File", + "currentState": "", + "describe": "Write hi.mdx", + "diff": "- Original - 0 + + Modified + 1 + + + hello", + "newState": "hello", + "resourceDefinitions": Object { + "content": "hello", + "mdxType": "File", + "path": "hi.mdx", + }, + "resourceName": "File", + }, + ] + `) + }) + test(`returns a plan for nested JSX`, async () => { const result = await render(`
@@ -99,6 +168,7 @@ describe(`renderer`, () => { expect(result).toMatchInlineSnapshot(` Array [ Object { + "_stepMetadata": Object {}, "currentState": "", "describe": "Write foo.js", "diff": "- Original - 0 @@ -108,6 +178,7 @@ describe(`renderer`, () => { "newState": "/** foo */", "resourceDefinitions": Object { "content": "/** foo */", + "mdxType": "File", "path": "foo.js", }, "resourceName": "File", diff --git a/packages/gatsby-recipes/src/renderer/input-provider.js b/packages/gatsby-recipes/src/renderer/input-provider.js new file mode 100644 index 0000000000000..c5a29e50575da --- /dev/null +++ b/packages/gatsby-recipes/src/renderer/input-provider.js @@ -0,0 +1,30 @@ +import React, { useContext, useState } from "react" + +const InputContext = React.createContext({}) + +export const useInputByKey = key => { + const context = useContext(InputContext) || {} + const result = context[key] + return result?.value +} + +export const useInput = ({ type = `text`, label, key = `123` }) => { + const contextVal = useInputByKey(key) || `` + const [val, setVal] = useState(contextVal) + + const Input = props => ( +
+ + setVal(e.target.value)} + /> +
+ ) + + return [Input, val] +} + +export const InputProvider = InputContext.Provider diff --git a/packages/gatsby-recipes/src/renderer/input.js b/packages/gatsby-recipes/src/renderer/input.js new file mode 100644 index 0000000000000..4d40be5911cd6 --- /dev/null +++ b/packages/gatsby-recipes/src/renderer/input.js @@ -0,0 +1,15 @@ +// eslint-disable-next-line no-unused-vars +import React from "react" +import { useRecipeStep } from "./step-component" + +function Input(props) { + const step = useRecipeStep() + + return JSON.stringify({ + ...props, + describe: props.label, + _stepMetadata: { step: step.step }, + }) +} + +export default Input diff --git a/packages/gatsby-recipes/src/renderer/parent-resource-provider.js b/packages/gatsby-recipes/src/renderer/parent-resource-provider.js new file mode 100644 index 0000000000000..9767d3f916a1a --- /dev/null +++ b/packages/gatsby-recipes/src/renderer/parent-resource-provider.js @@ -0,0 +1,19 @@ +import React, { useContext } from "react" + +const ParentResourceContext = React.createContext({}) + +export const useParentResourceContext = () => { + const context = useContext(ParentResourceContext) + return context +} + +export const ParentResourceProvider = ({ data: providedData, children }) => { + const parentData = useParentResourceContext() + const data = { ...parentData, ...providedData } + + return ( + + {children} + + ) +} diff --git a/packages/gatsby-recipes/src/renderer/provider-provider.js b/packages/gatsby-recipes/src/renderer/provider-provider.js new file mode 100644 index 0000000000000..58c82f2efbf2f --- /dev/null +++ b/packages/gatsby-recipes/src/renderer/provider-provider.js @@ -0,0 +1,18 @@ +// this file has the best name +// eslint-disable-next-line +import React from "react" + +export const useProvider = provider => { + // const context = useContext(ResourceContext) + // const result = context.find(c => c.resourceDefinitions._key === key) + // return result + const providers = { + contentful: { + accessToken: process.env.CONTENTFUL_ACCESS_TOKEN, + }, + } + + return providers[provider] +} + +// export const ResourceProvider = ResourceContext.Provider diff --git a/packages/gatsby-recipes/src/renderer/reconciler.js b/packages/gatsby-recipes/src/renderer/reconciler.js index 489f0a655c556..6c5190b5781c9 100644 --- a/packages/gatsby-recipes/src/renderer/reconciler.js +++ b/packages/gatsby-recipes/src/renderer/reconciler.js @@ -1,6 +1,12 @@ const ReactReconciler = require(`react-reconciler`) -const debug = require(`debug`)(`recipes-reconciler`) +// const debugInner = require(`debug`)(`recipes-reconciler`) +const debug = (title, data) => { + if (process.env.DEBUG) { + console.log(title, data) + } + // debugInner(title, JSON.stringify(data, null, 2)) +} const reconciler = ReactReconciler({ finalizeInitialChildren(element, type, props) {}, @@ -37,10 +43,19 @@ const reconciler = ReactReconciler({ debug(`creating text instance`, text) return { text } }, + commitTextUpdate(textInstance, oldText, newText) { + debug(`updating text instance`, newText) + textInstance.text = newText + return textInstance + }, appendChildToContainer(container, child) { - debug(`appending child to container`, { container, child }) container.children = container.children || [] - const index = container.children.findIndex(c => c.key === child.key) + const propName = child.key ? `key` : `_uuid` + const index = container.children.findIndex( + c => c[propName] === child[propName] + ) + + debug(`appending child to container at index ${index}`) if (index === -1) { container.children.push(child) @@ -94,8 +109,6 @@ const RecipesRenderer = { let container = reconciler.createContainer(currState, false, false) reconciler.updateContainer(whatToRender, container, null, null) - debug(`render result`, JSON.stringify(currState, null, 2)) - return currState }, } diff --git a/packages/gatsby-recipes/src/renderer/render.js b/packages/gatsby-recipes/src/renderer/render.js index 3c37cd0595d0b..61a320626165d 100644 --- a/packages/gatsby-recipes/src/renderer/render.js +++ b/packages/gatsby-recipes/src/renderer/render.js @@ -1,15 +1,38 @@ -const React = require(`react`) -const { Suspense } = require(`react`) +import React, { Suspense, useContext, useState } from "react" +import Queue from "p-queue" +import lodash from "lodash" -const resources = require(`../resources`) +import resources from "../resources" -const RecipesReconciler = require(`./reconciler`) -const ErrorBoundary = require(`./error-boundary`) -const transformToPlan = require(`./transform-to-plan-structure`) +import RecipesReconciler from "./reconciler" +import ErrorBoundary from "./error-boundary" +import transformToPlan from "./transform-to-plan-structure" +import { + ParentResourceProvider, + useParentResourceContext, +} from "./parent-resource-provider" +import { useRecipeStep } from "./step-component" +import { InputProvider } from "./input-provider" +import { ResourceProvider, useResourceContext } from "./resource-provider" -const promises = [] -const errors = [] -const cache = new Map() +const queue = new Queue({ concurrency: 5, autoStart: false }) + +let errors = [] +const resultCache = new Map() +const inFlightCache = new Map() + +const ModeContext = React.createContext({}) +const useMode = () => useContext(ModeContext) +const ModeProvider = ModeContext.Provider + +const getInvalidProps = errors => { + const invalidProps = errors.filter(e => { + const details = e.details + const unknownProp = details.find(e => e.type === `object.allowUnknown`) + return unknownProp + }) + return invalidProps +} const getUserProps = props => { // eslint-disable-next-line @@ -17,80 +40,224 @@ const getUserProps = props => { return userProps } -const Wrapper = ({ children }) => ( - - Loading recipe...

}>{children}
-
-) +const SetResourcesProvider = React.createContext() -const ResourceComponent = ({ _resourceName: Resource, ...props }) => { - const userProps = getUserProps(props) +let resourcesCache + +const Wrapper = ({ children, inputs, isApply }) => { + const [resourcesList, setResources] = useState(resourcesCache || []) + resourcesCache = resourcesList return ( - Reading resource...

}> + + + + + + Loading recipe...

}> + {children} +
+
+
+
+
+
+ ) +} + +const ResourceComponent = ({ + _resourceName: Resource, + _uuid, + _type, + children, + ...props +}) => { + const { mode } = useMode() + const step = useRecipeStep() + const parentResourceContext = useParentResourceContext() + const allResources = useResourceContext() + + const setResources = useContext(SetResourcesProvider) + // TODO add provider onto context + const resourceData = handleResource( + Resource, + { + ...parentResourceContext, + root: process.cwd(), + _uuid, + mode, + }, + props, + allResources, + setResources + ) + + return ( + {JSON.stringify({ - ...readResource(Resource, { root: process.cwd() }, props), - _props: userProps, + ...resourceData, + _props: props, + _stepMetadata: step, + _uuid, + _type, })} + {children} -
+ ) } -const validateResource = (resourceName, _context, props) => { +const validateResource = (resourceName, context, props) => { const userProps = getUserProps(props) const { error } = resources[resourceName].validate(userProps) + if (error) { + error.resourceUuid = context._uuid + } return error } -const readResource = (resourceName, context, props) => { +const handleResource = ( + resourceName, + context, + props, + allResources, + setResources +) => { const error = validateResource(resourceName, context, props) if (error) { errors.push(error) return null } - const key = JSON.stringify({ resourceName, ...props }) - const cachedResult = cache.get(key) + const { mode } = context + + let key + // Only run apply once per resource + if (mode === `apply`) { + key = mode + ` ` + resourceName + ` ` + props._key + } else { + key = JSON.stringify({ resourceName, ...props, mode }) + } + + const updateResource = result => { + allResources = allResources.filter(a => a.resourceDefinitions._key) + const resourceMap = new Map() + + allResources.forEach(r => resourceMap.set(r.resourceDefinitions._key, r)) + const newResource = { + resourceName, + resourceDefinitions: props, + ...result, + } + + if ( + props._key && + !lodash.isEqual(newResource, resourceMap.get(props._key)) + ) { + resourceMap.set(props._key, newResource) + setResources([...resourceMap.values()]) + } + } + + const cachedResult = resultCache.get(key) + const inFlightPromise = inFlightCache.get(key) if (cachedResult) { + updateResource(cachedResult) return cachedResult } + if (inFlightPromise) { + throw inFlightPromise + } + + const fn = mode === `apply` ? `create` : `plan` + let promise try { - promise = resources[resourceName] - .plan(context, props) - .then(result => cache.set(key, result)) - .catch(e => console.log(e)) + promise = new Promise((resolve, reject) => { + // Multiple of the same promises can be queued due to re-rendering + // so this first checks for the cached result again before executing + // the request. + const cachedValue = resultCache.get(key) + if (cachedValue) { + resolve(cachedValue) + updateResource(cachedValue) + } else { + resources[resourceName][fn](context, props) + .then(result => { + updateResource(result) + inFlightCache.set(key, false) + return result + }) + .then(result => resultCache.set(key, result)) + .then(resolve) + .catch(e => { + console.log(e) + if (e.name === `MissingInfoError`) { + inFlightCache.delete(key) + } + reject(e) + }) + } + }) } catch (e) { throw e } - promises.push(promise) + inFlightCache.set(key, promise) + + queue.add(() => promise) throw promise } -const render = async recipe => { +const render = async (recipe, cb, inputs = {}, isApply) => { const plan = {} - const recipeWithWrapper = {recipe} + const recipeWithWrapper = ( + + {recipe} + + ) + + const renderResources = async () => { + queue.pause() - try { - // Run the first pass of the render to queue up all the promises and suspend RecipesReconciler.render(recipeWithWrapper, plan) if (errors.length) { - const error = new Error(`Unable to validate resources`) - error.errors = errors - throw error + const invalidProps = getInvalidProps(errors) + + if (invalidProps.length) { + return cb({ type: `INVALID_PROPS`, data: invalidProps }) + } else { + errors = [] + } + } + + // If there aren't any new resources that need to be fetched, or errors, we're done! + if (!queue.size && !errors.length) { + return undefined + } + + queue.start() + await queue.onIdle() + return await renderResources() + } + + try { + // Begin the "render loop" until there are no more resources being queued. + await renderResources() + + if (errors.length) { + // We found errors that were emitted back to the state machine, so + // we don't need to re-render + return null } - // Await all promises for resources and cache results - await Promise.all(promises) - // Rerender with the resources and resolve the data + // Rerender with the resources and resolve the data from the cache const result = RecipesReconciler.render(recipeWithWrapper, plan) return transformToPlan(result) } catch (e) { diff --git a/packages/gatsby-recipes/src/renderer/render.test.js b/packages/gatsby-recipes/src/renderer/render.test.js index 72a7e5fa60f8e..e7ce7c361e826 100644 --- a/packages/gatsby-recipes/src/renderer/render.test.js +++ b/packages/gatsby-recipes/src/renderer/render.test.js @@ -1,7 +1,10 @@ -const React = require(`react`) +import React from "react" -const { render } = require(`./render`) -const { File, NPMPackage } = require(`./resource-components`) +import { render } from "./render" +import { resourceComponents } from "./resource-components" +import { RecipeStep } from "./step-component" + +const { File, NPMPackage } = resourceComponents const fixture = ( @@ -10,6 +13,127 @@ const fixture = ( ) +test(`handles nested rendering`, async () => { + const result = await render( + + + + + + + , + {} + ) + + expect(result).toMatchInlineSnapshot(` + Array [ + Object { + "_stepMetadata": Object {}, + "currentState": "", + "describe": "Write red.js", + "diff": "- Original - 0 + + Modified + 1 + + + red!", + "newState": "red!", + "resourceChildren": Array [ + Object { + "_stepMetadata": Object {}, + "currentState": "", + "describe": "Write blue.js", + "diff": "- Original - 0 + + Modified + 1 + + + blue!", + "newState": "blue!", + "resourceChildren": Array [ + Object { + "_stepMetadata": Object {}, + "currentState": "", + "describe": "Write yellow.js", + "diff": "- Original - 0 + + Modified + 1 + + + yellow!", + "newState": "yellow!", + "resourceDefinitions": Object { + "content": "yellow!", + "path": "yellow.js", + }, + "resourceName": "File", + }, + ], + "resourceDefinitions": Object { + "content": "blue!", + "path": "blue.js", + }, + "resourceName": "File", + }, + ], + "resourceDefinitions": Object { + "content": "red!", + "path": "red.js", + }, + "resourceName": "File", + }, + ] + `) +}) + +test(`includes step metadata`, async () => { + const result = await render( + + + + + + + + + ) + + expect(result).toMatchInlineSnapshot(` + Array [ + Object { + "_stepMetadata": Object { + "step": 1, + "totalSteps": 2, + }, + "currentState": "", + "describe": "Write red.js", + "diff": "- Original - 0 + + Modified + 1 + + + red!", + "newState": "red!", + "resourceDefinitions": Object { + "content": "red!", + "path": "red.js", + }, + "resourceName": "File", + }, + Object { + "_stepMetadata": Object { + "step": 2, + "totalSteps": 2, + }, + "currentState": "", + "describe": "Write blue.js", + "diff": "- Original - 0 + + Modified + 1 + + + blue!", + "newState": "blue!", + "resourceDefinitions": Object { + "content": "blue!", + "path": "blue.js", + }, + "resourceName": "File", + }, + ] + `) +}) + test(`renders to a plan`, async () => { const result = await render(fixture, {}) @@ -20,6 +144,7 @@ test(`renders to a plan`, async () => { expect(result.length).toEqual(2) expect(result[0]).toMatchInlineSnapshot(` Object { + "_stepMetadata": Object {}, "currentState": "", "describe": "Write red.js", "diff": "- Original - 0 @@ -34,12 +159,14 @@ test(`renders to a plan`, async () => { "resourceName": "File", } `) + expect(result[1]).toMatchInlineSnapshot( { currentState: expect.stringMatching(/gatsby@[0-9.]+/), }, ` Object { + "_stepMetadata": Object {}, "currentState": StringMatching /gatsby@\\[0-9\\.\\]\\+/, "describe": "Install gatsby@latest", "newState": "gatsby@latest", diff --git a/packages/gatsby-recipes/src/renderer/resource-components.js b/packages/gatsby-recipes/src/renderer/resource-components.js index b82d10bda3e8b..0d3ef21e79d0d 100644 --- a/packages/gatsby-recipes/src/renderer/resource-components.js +++ b/packages/gatsby-recipes/src/renderer/resource-components.js @@ -1,13 +1,15 @@ -const React = require(`react`) +import React, { Suspense } from "react" -const resources = require(`../resources`) +import resources from "../resources" -const { ResourceComponent } = require(`./render`) +import { ResourceComponent } from "./render" -const resourceComponents = Object.keys(resources).reduce( +export const resourceComponents = Object.keys(resources).reduce( (acc, resourceName) => { acc[resourceName] = props => ( - + Reading {resourceName}...

}> + +
) // Make sure the component is pretty printed in reconciler output @@ -17,5 +19,3 @@ const resourceComponents = Object.keys(resources).reduce( }, {} ) - -module.exports = resourceComponents diff --git a/packages/gatsby-recipes/src/renderer/resource-provider.js b/packages/gatsby-recipes/src/renderer/resource-provider.js new file mode 100644 index 0000000000000..c03441662184c --- /dev/null +++ b/packages/gatsby-recipes/src/renderer/resource-provider.js @@ -0,0 +1,22 @@ +import React, { useContext } from "react" + +const ResourceContext = React.createContext([]) + +export const useResourceContext = () => { + const context = useContext(ResourceContext) + return context +} + +export const useResource = key => { + const context = useContext(ResourceContext) + const result = context.find(c => c.resourceDefinitions._key === key) + return result || {} +} + +export const useResourceByUUID = uuid => { + const context = useContext(ResourceContext) + const result = context.find(c => c._uuid === uuid) + return result +} + +export const ResourceProvider = ResourceContext.Provider diff --git a/packages/gatsby-recipes/src/renderer/step-component.js b/packages/gatsby-recipes/src/renderer/step-component.js new file mode 100644 index 0000000000000..3c04c8a1a9228 --- /dev/null +++ b/packages/gatsby-recipes/src/renderer/step-component.js @@ -0,0 +1,22 @@ +import React, { useContext } from "react" + +const StepContext = React.createContext({}) + +export const useRecipeStep = () => { + const context = useContext(StepContext) + return context +} + +export const StepProvider = ({ step, totalSteps, children }) => ( + + {children} + +) + +export const RecipeStep = ({ step, totalSteps, children }) => ( + + {children} + +) + +export const RecipeIntroduction = `div` diff --git a/packages/gatsby-recipes/src/renderer/transform-to-plan-structure.js b/packages/gatsby-recipes/src/renderer/transform-to-plan-structure.js index e1a0d9325eac4..06856857b6b5b 100644 --- a/packages/gatsby-recipes/src/renderer/transform-to-plan-structure.js +++ b/packages/gatsby-recipes/src/renderer/transform-to-plan-structure.js @@ -1,25 +1,70 @@ const providedResources = require(`../resources`) +const isResource = type => type && (type === `Input` || providedResources[type]) -const transform = (props = {}) => { +const extractPlan = (node, type) => { + if (!isResource(type)) { + return null + } + + let text = {} + if (node.text) { + try { + text = JSON.parse(node.text) + } catch { + return null + } + } + + const { _props: props, ...plan } = text + + return { + resourceName: type, + resourceDefinitions: props, + ...plan, + } +} + +const transform = (props = {}, type) => { if (!props.children) { - return [] + const plan = extractPlan(props, type) + return plan ? [plan] : [] } - const plan = props.children.reduce((acc, curr) => { - const childResourcePlans = transform(curr) + const plan = props.children.filter(Boolean).reduce((acc, curr) => { + const childType = curr.type || type + + let currText = {} + if (curr.text) { + try { + currText = JSON.parse(curr.text) + } catch {} // eslint-disable-line + } - if (!providedResources[curr.type]) { - return [...acc, ...childResourcePlans] + if (childType === `Input`) { + currText.resourceName = `Input` + return [...acc, currText] } - const { _props, ...plan } = JSON.parse(curr.children[0].text) + if (!providedResources[childType]) { + return [...acc, ...transform(curr, childType)] + } + + const [rawResource, ...resourceChildren] = curr.children || [] + const { _props, ...plan } = JSON.parse(rawResource.text) const resourcePlan = { - resourceName: curr.type, + resourceName: childType, resourceDefinitions: _props, ...plan, } + if (resourceChildren.length) { + resourcePlan.resourceChildren = transform( + { children: resourceChildren }, + childType + ) + } + return [...acc, resourcePlan] }, []) diff --git a/packages/gatsby-recipes/src/resources.js b/packages/gatsby-recipes/src/resources.js index 72ef0f29d43fe..bc3d6da92534e 100644 --- a/packages/gatsby-recipes/src/resources.js +++ b/packages/gatsby-recipes/src/resources.js @@ -7,6 +7,10 @@ const npmPackageResource = require(`./providers/npm/package`) const npmPackageScriptResource = require(`./providers/npm/script`) const npmPackageJsonResource = require(`./providers/npm/package-json`) const gitIgnoreResource = require(`./providers/git/ignore`) +const contentfulSpace = require(`./providers/contentful/space`) +const contentfulEnvironment = require(`./providers/contentful/environment`) +const contentfulType = require(`./providers/contentful/type`) +const contentfulEntry = require(`./providers/contentful/entry`) const componentResourceMapping = { File: fileResource, @@ -18,6 +22,10 @@ const componentResourceMapping = { NPMScript: npmPackageScriptResource, NPMPackageJson: npmPackageJsonResource, GitIgnore: gitIgnoreResource, + ContentfulSpace: contentfulSpace, + ContentfulEnvironment: contentfulEnvironment, + ContentfulType: contentfulType, + ContentfulEntry: contentfulEntry, } module.exports = componentResourceMapping diff --git a/packages/gatsby-recipes/src/transform-recipe-mdx.js b/packages/gatsby-recipes/src/transform-recipe-mdx.js new file mode 100644 index 0000000000000..a7afff82b5409 --- /dev/null +++ b/packages/gatsby-recipes/src/transform-recipe-mdx.js @@ -0,0 +1,59 @@ +import babelPluginTransformReactJsx from "@babel/plugin-transform-react-jsx" +import babelChainingPlugin from "@babel/plugin-proposal-optional-chaining" +import mdx from "@mdx-js/mdx" +import babelPluginRemoveShortcodes from "./renderer/babel-plugin-remove-shortcodes" +import babelPluginCopyKeyProp from "./renderer/babel-plugin-copy-key-prop" +import babelPluginMoveExportKeywords from "./renderer/babel-plugin-move-export-keywords" + +const mdxCache = new Map() +const jsxCache = new Map() + +const transformJsx = (jsx, isRenderer) => { + delete require.cache[require.resolve(`@babel/standalone`)] + const { transform } = require(`@babel/standalone`) + const options = { + parserOpts: { + // We want to return outside of a function because the output from + // Babel will be evaluated inline as part of the render process. + allowReturnOutsideFunction: true, + }, + plugins: [ + babelPluginCopyKeyProp, + babelPluginMoveExportKeywords, + // TODO figure out how to use preset-env + babelChainingPlugin, + [babelPluginTransformReactJsx, { useBuiltIns: true }], + ], + } + + if (isRenderer) { + options.plugins.push(babelPluginRemoveShortcodes) + } + + const { code } = transform(jsx, options) + + return code +} + +export default (mdxSrc, isRenderer = false) => { + let jsxFromMdx + if (mdxCache.has(mdxSrc)) { + jsxFromMdx = mdxCache.get(mdxSrc) + } else { + jsxFromMdx = mdx.sync(mdxSrc, { + skipExport: true, + commonmark: true, + }) + mdxCache.set(mdxSrc, jsxFromMdx) + } + + let srcCode + if (jsxCache.has(jsxFromMdx)) { + srcCode = jsxCache.get(jsxFromMdx) + } else { + srcCode = transformJsx(jsxFromMdx, isRenderer) + jsxCache.set(jsxFromMdx, srcCode) + } + + return srcCode +} diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index 9ad56735e4729..983203674aa8a 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -219,7 +219,12 @@ "url": "git+https://github.com/gatsbyjs/gatsby.git" }, "resolutions": { - "graphql": "^14.6.0" + "graphql": "^14.6.0", + "@mdx-js/mdx": "^2.0.0-next.3", + "@mdx-js/react": "^2.0.0-next.3", + "@mdx-js/runtime": "^2.0.0-next.3", + "remark-mdx": "^2.0.0-next.3", + "remark-mdxjs": "^2.0.0-next.3" }, "scripts": { "build": "npm run build:types && npm run build:src && npm run build:internal-plugins && npm run build:rawfiles && npm run build:cjs", diff --git a/scripts/e2e-test.sh b/scripts/e2e-test.sh index debf03b636a25..52a96eea0a54e 100755 --- a/scripts/e2e-test.sh +++ b/scripts/e2e-test.sh @@ -9,7 +9,7 @@ command -v gatsby-dev || command -v sudo && sudo npm install -g gatsby-dev-cli | # setting up child integration test link to gatsby packages cd "$SRC_PATH" && gatsby-dev --set-path-to-repo "$GATSBY_PATH" && -gatsby-dev --scan-once --quiet && # copies _all_ files in gatsby/packages +gatsby-dev --scan-once && # copies _all_ files in gatsby/packages chmod +x ./node_modules/.bin/gatsby && # this is sometimes necessary to ensure executable sh -c "$CUSTOM_COMMAND" && echo "e2e test run succeeded" diff --git a/yarn.lock b/yarn.lock index e9915eb413fdb..9c6cfc300fddd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -120,6 +120,28 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.9.6": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.0.tgz#73b9c33f1658506887f767c26dae07798b30df76" + integrity sha512-mkLq8nwaXmDtFmRkQ8ED/eA2CnVw4zr7dCztKalZXBvdK5EeNUAesrrwUqjQEzFgomJssayzB0aqlOsP1vGLqg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/generator@^7.0.0", "@babel/generator@^7.10.3", "@babel/generator@^7.10.4", "@babel/generator@^7.9.4", "@babel/generator@^7.9.6": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243" @@ -139,6 +161,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== + dependencies: + "@babel/types" "^7.11.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.10.1", "@babel/helper-annotate-as-pure@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" @@ -163,6 +194,15 @@ "@babel/helper-module-imports" "^7.10.1" "@babel/types" "^7.10.1" +"@babel/helper-builder-react-jsx-experimental@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz#f35e956a19955ff08c1258e44a515a6d6248646b" + integrity sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/types" "^7.10.5" + "@babel/helper-builder-react-jsx@^7.10.3": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.3.tgz#62c4b7bb381153a0a5f8d83189b94b9fb5384fc5" @@ -171,6 +211,14 @@ "@babel/helper-annotate-as-pure" "^7.10.1" "@babel/types" "^7.10.3" +"@babel/helper-builder-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" + integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-compilation-targets@^7.10.2": version "7.10.2" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz#a17d9723b6e2c750299d2a14d4637c76936d8285" @@ -283,6 +331,19 @@ "@babel/types" "^7.10.5" lodash "^4.17.19" +"@babel/helper-module-transforms@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" + "@babel/helper-optimise-call-expression@^7.10.3", "@babel/helper-optimise-call-expression@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" @@ -336,6 +397,13 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" + integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== + dependencies: + "@babel/types" "^7.11.0" + "@babel/helper-split-export-declaration@^7.10.1", "@babel/helper-split-export-declaration@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" @@ -343,6 +411,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" + "@babel/helper-validator-identifier@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" @@ -414,6 +489,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== +"@babel/parser@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.0.tgz#a9d7e11aead25d3b422d17b2c6502c8dddef6a5d" + integrity sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw== + "@babel/plugin-proposal-async-generator-functions@^7.10.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz#4b65abb3d9bacc6c657aaa413e56696f9f170fc6" @@ -563,6 +643,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-chaining" "^7.8.0" +"@babel/plugin-proposal-optional-chaining@^7.9.4": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" + integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-proposal-pipeline-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-pipeline-operator/-/plugin-proposal-pipeline-operator-7.8.3.tgz#c3569228e7466f91bfff7f1c1ae18fb5d36b3097" @@ -679,7 +768,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@7.10.4": +"@babel/plugin-syntax-jsx@7.10.4", "@babel/plugin-syntax-jsx@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== @@ -995,7 +1084,7 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-jsx" "^7.10.1" -"@babel/plugin-transform-react-jsx@^7.10.1", "@babel/plugin-transform-react-jsx@^7.10.3", "@babel/plugin-transform-react-jsx@^7.3.0": +"@babel/plugin-transform-react-jsx@^7.10.1", "@babel/plugin-transform-react-jsx@^7.3.0": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.3.tgz#c07ad86b7c159287c89b643f201f59536231048e" integrity sha512-Y21E3rZmWICRJnvbGVmDLDZ8HfNDIwjGF3DXYHx1le0v0mIHCs0Gv5SavyW5Z/jgAHLaAoJPiwt+Dr7/zZKcOQ== @@ -1005,6 +1094,16 @@ "@babel/helper-plugin-utils" "^7.10.3" "@babel/plugin-syntax-jsx" "^7.10.1" +"@babel/plugin-transform-react-jsx@^7.9.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" + integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A== + dependencies: + "@babel/helper-builder-react-jsx" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" + "@babel/plugin-transform-react-pure-annotations@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.1.tgz#f5e7c755d3e7614d4c926e144f501648a5277b70" @@ -1027,6 +1126,16 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-runtime@^7.0.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz#e27f78eb36f19448636e05c33c90fd9ad9b8bccf" + integrity sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + resolve "^1.8.1" + semver "^5.5.1" + "@babel/plugin-transform-runtime@^7.10.3": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.3.tgz#3b287b06acc534a7cb6e6c71d6b1d88b1922dd6c" @@ -1254,10 +1363,10 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/standalone@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.10.3.tgz#aaabbf0fcfc82d595d3e1b9467b201d1a33a6e64" - integrity sha512-pGqfFo2VXa/Ei40T9kSpe8i87MzsOfAQJMpHRABTAjLZrH5IwskSqfAzBP5o2VJbpA4S34LMxOTZ26lirCCVFQ== +"@babel/standalone@^7.10.2": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.11.0.tgz#c8882afdb737306cb127f58f0befec4def31beb5" + integrity sha512-Cf4WggQ4vPsGsVU8DbbWtzI/AEQ/oyYE6XFqGnAAadBT5kro0YfDfJhtcLdtye9C6RkOfV0DxcQ3eoZ1Bv6yrA== "@babel/template@^7.0.0", "@babel/template@^7.10.1", "@babel/template@^7.10.3", "@babel/template@^7.10.4", "@babel/template@^7.8.6": version "7.10.4" @@ -1313,6 +1422,21 @@ globals "^11.1.0" lodash "^4.17.19" +"@babel/traverse@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" + integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.0" + "@babel/types" "^7.11.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.1", "@babel/types@^7.10.3", "@babel/types@^7.10.4", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0", "@babel/types@^7.9.6": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee" @@ -1331,6 +1455,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" + integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@cnakazawa/watch@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" @@ -1371,7 +1504,7 @@ "@emotion/utils" "0.11.3" "@emotion/weak-memoize" "0.2.5" -"@emotion/core@^10.0.0", "@emotion/core@^10.0.28": +"@emotion/core@^10.0.0", "@emotion/core@^10.0.14", "@emotion/core@^10.0.28": version "10.0.28" resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.28.tgz#bb65af7262a234593a9e952c041d0f1c9b9bef3d" integrity sha512-pH8UueKYO5jgg0Iq+AmCLxBsvuGtvlmiDCOuv8fGNYn3cowFpLN98L8zO56U0H1PjDIyAlXymgL3Wu7u7v6hbA== @@ -1435,7 +1568,7 @@ "@emotion/serialize" "^0.11.15" "@emotion/utils" "0.11.3" -"@emotion/styled@*", "@emotion/styled@^10.0.0", "@emotion/styled@^10.0.27": +"@emotion/styled@*", "@emotion/styled@^10.0.0", "@emotion/styled@^10.0.14", "@emotion/styled@^10.0.27": version "10.0.27" resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.27.tgz#12cb67e91f7ad7431e1875b1d83a94b814133eaf" integrity sha512-iK/8Sh7+NLJzyp9a5+vIQIXTYxfT4yB/OJbjzQanB2RZpvmzBQOHZWhpAMZWYEKRNNbsD6WfBw5sVWkb6WzS/Q== @@ -1566,18 +1699,18 @@ "@graphql-tools/utils" "6.0.9" tslib "~2.0.0" -"@graphql-tools/schema@^6.0.11": - version "6.0.11" - resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-6.0.11.tgz#4623c3662a8843822e36139855504ef8d7d89088" - integrity sha512-Zl9LTwOnkMaNtgs1+LJEYtklywtn602kRbxkRFeA7nFGaDmFPFHZnfQqcLsfhaPA8S0jNCQnbucHERCz8pRUYA== +"@graphql-tools/schema@^6.0.14": + version "6.0.15" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-6.0.15.tgz#b016f9f36820342982887a291baa7e7d11b039ae" + integrity sha512-Wo+d6/OPjeXjwB1pcqsWmqLdweGH+BVhvKe/YPQA/uiWr8ikgShvNLNiuF03gc/1AMR487A09XcPEyabRKJLew== dependencies: - "@graphql-tools/utils" "6.0.11" + "@graphql-tools/utils" "6.0.15" tslib "~2.0.0" -"@graphql-tools/utils@6.0.11", "@graphql-tools/utils@^6.0.11": - version "6.0.11" - resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-6.0.11.tgz#c394201c992dbc8f3644b9ad71411fdd55832f2d" - integrity sha512-BK6HO73FbB/Ufac6XX5H0O2q4tEZi//HaQ7DgmHFoda53GZSZ/ZckJ59wh/tUvHykEaSFUSmMBVQxKbXBhGhyg== +"@graphql-tools/utils@6.0.15", "@graphql-tools/utils@^6.0.14": + version "6.0.15" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-6.0.15.tgz#6d54d383285bea3c22797531933b62a408e78e49" + integrity sha512-VG5cMLPgh9RDLGHamGpXVnBrNw7bZGT46LrxK7IIqDZI9H0GPsRCo8+p+CfDkw0IlDiEECb624WVCpm9IYNecA== dependencies: "@ardatan/aggregate-error" "0.0.1" camel-case "4.1.1" @@ -1619,7 +1752,7 @@ resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-6.2.4.tgz#4b95fbaccbfba90185690890bdf1a2fbbda10595" integrity sha512-HOJ20Kc93DkDVvjwHyHawPwPkX44sIrbXazAUDiUXaY2R9JwQGo2PhFfnQtdrsIe4igjG2fPgMra7NYw7qhy0A== -"@hapi/hoek@8.x", "@hapi/hoek@8.x.x": +"@hapi/hoek@8.x.x": version "8.5.1" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06" integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow== @@ -2799,32 +2932,34 @@ unist-builder "2.0.3" unist-util-visit "2.0.3" -"@mdx-js/mdx@^1.6.6": - version "1.6.6" - resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.6.tgz#6e235f0ca47c8652f4c744cf7bc46a1015bcaeaa" - integrity sha512-Q1j/RtjNbRZRC/ciaOqQLplsJ9lb0jJhDSvkusmzCsCX+NZH7YTUvccWf7l6zKW1CAiofJfqZdZtXkeJUDZiMw== +"@mdx-js/mdx@^2.0.0-next.4", "@mdx-js/mdx@^2.0.0-next.7": + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-2.0.0-next.7.tgz#3f27449e6a78ac0a9cc682f98e1c93442e93f166" + integrity sha512-GcdHQ+YTlIaNpsMPlw32kEp+GCrb+2GLeDDf2AFtJiRoTelgCinjYp1twxY42WF6A4K80ZYgpr0/A6PDQbKNyw== dependencies: - "@babel/core" "7.9.6" - "@babel/plugin-syntax-jsx" "7.8.3" + "@babel/core" "7.10.5" + "@babel/plugin-syntax-jsx" "7.10.4" "@babel/plugin-syntax-object-rest-spread" "7.8.3" - "@mdx-js/util" "^1.6.6" - babel-plugin-apply-mdx-type-prop "^1.6.6" - babel-plugin-extract-import-names "^1.6.6" + "@mdx-js/util" "^2.0.0-next.7" + babel-plugin-apply-mdx-type-prop "^2.0.0-next.7" + babel-plugin-extract-export-names "^2.0.0-next.7" + babel-plugin-extract-import-names "^2.0.0-next.7" camelcase-css "2.0.1" detab "2.0.3" - hast-util-raw "5.0.2" + hast-to-hyperscript "9.0.0" + hast-util-raw "6.0.0" lodash.uniq "4.5.0" mdast-util-to-hast "9.1.0" remark-footnotes "1.0.0" - remark-mdx "^1.6.6" + remark-mdx "^2.0.0-next.7" + remark-mdxjs "^2.0.0-next.7" remark-parse "8.0.2" remark-squeeze-paragraphs "4.0.0" - style-to-object "0.3.0" unified "9.0.0" unist-builder "2.0.3" - unist-util-visit "2.0.2" + unist-util-visit "2.0.3" -"@mdx-js/react@^1.0.0", "@mdx-js/react@^1.5.2", "@mdx-js/react@^1.6.6": +"@mdx-js/react@^1.0.0", "@mdx-js/react@^1.5.2": version "1.6.6" resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.6.tgz#71ece2a24261eed0e184c0ef9814fcb77b1a4aee" integrity sha512-zOOdNreHUNSFQ0dg3wYYg9sOGg2csf7Sk8JGBigeBq+4Xk4LO0QdycGAmgKNfeme+SyBV5LBIPjt1NNsScyWEQ== @@ -2834,13 +2969,18 @@ resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.16.tgz#538eb14473194d0b3c54020cb230e426174315cd" integrity sha512-+FhuSVOPo7+4fZaRwWuCSRUcZkJOkZu0rfAbBKvoCg1LWb1Td8Vzi0DTLORdSvgWNbU6+EL40HIgwTOs00x2Jw== -"@mdx-js/runtime@^1.6.6": - version "1.6.6" - resolved "https://registry.yarnpkg.com/@mdx-js/runtime/-/runtime-1.6.6.tgz#2100a4da17f18dcbc9b59bf279b0f064df0a1377" - integrity sha512-JNt/dqIFMQ87Gp6oIZUn4oJZQOOk0rqc7JkIv/xYyTtUMaNCXWZ/ylRLoFbQCyfONxayOz4w4e8Bd4ruxScOGQ== +"@mdx-js/react@^2.0.0-next.4", "@mdx-js/react@^2.0.0-next.7": + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-2.0.0-next.7.tgz#33d3a2a961d5f2ebf36d096642c2a306111feae4" + integrity sha512-VugV3o0zOD6pABtQEDDWNxiU8f+tS4KMiOgnwNiyxxOEwEZgBnXfMhZYDtHfrnhHxS59ValJ5zITnbdBwPbJkA== + +"@mdx-js/runtime@^2.0.0-next.4": + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/@mdx-js/runtime/-/runtime-2.0.0-next.7.tgz#6efd063bc9bec85a16e38fddab02d12812c05d43" + integrity sha512-+Nnjjs1LsdxkkdLODnFE0gz0B69uYJ+eUxScUBDoOY61jnm1NTvq/Axu3/Ax4YMtNwVCQMqBXXeOgLBDku1ISg== dependencies: - "@mdx-js/mdx" "^1.6.6" - "@mdx-js/react" "^1.6.6" + "@mdx-js/mdx" "^2.0.0-next.7" + "@mdx-js/react" "^2.0.0-next.7" buble-jsx-only "^0.19.8" "@mdx-js/util@1.6.16": @@ -2853,6 +2993,11 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.6.tgz#9c70eb7e7e4abc1083c8edf7151d35a19e442c00" integrity sha512-PKTHVgMHnK5p+kcMWWNnZuoR7O19VmHiOujmVcyN50hya7qIdDb5vvsYC+dwLxApEXiABhLozq0dlIwFeS3yjg== +"@mdx-js/util@^2.0.0-next.7": + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-2.0.0-next.7.tgz#b1c52e7622917d7601b2c9ba2f132aaf8d4224fc" + integrity sha512-gsid2rh63B7/U1gPLXz9N5bfWR+n5GYxAcVCJDf8H+XfCC7NHsEX9ZHL9IdmXndOPT4ZTSW6V/jD8VeQdvnzLQ== + "@mikaelkristiansson/domready@^1.0.10": version "1.0.10" resolved "https://registry.yarnpkg.com/@mikaelkristiansson/domready/-/domready-1.0.10.tgz#f6d69866c0857664e70690d7a0bfedb72143adb5" @@ -3152,6 +3297,14 @@ "@babel/helper-module-imports" "^7.7.4" "@rollup/pluginutils" "^3.0.8" +"@rollup/plugin-babel@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.1.0.tgz#ad8b5803fa6e1feb0f168984edc040b90d966450" + integrity sha512-zXBEYmfiLAMvB+ZBa6m/q9hsQYAq1sUFdjuP1F6C2pf6uQcpHwAWQveZgzS63zXdKPUYHD3Dr7BhjCqcr0bbLw== + dependencies: + "@babel/helper-module-imports" "^7.7.4" + "@rollup/pluginutils" "^3.0.8" + "@rollup/plugin-commonjs@^13.0.0": version "13.0.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-13.0.0.tgz#8a1d684ba6848afe8b9e3d85649d4b2f6f7217ec" @@ -3165,6 +3318,19 @@ magic-string "^0.25.2" resolve "^1.11.0" +"@rollup/plugin-commonjs@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-14.0.0.tgz#4285f9ec2db686a31129e5a2b415c94aa1f836f0" + integrity sha512-+PSmD9ePwTAeU106i9FRdc+Zb3XUWyW26mo5Atr2mk82hor8+nPwkztEjFo8/B1fJKfaQDg9aM2bzQkjhi7zOw== + dependencies: + "@rollup/pluginutils" "^3.0.8" + commondir "^1.0.1" + estree-walker "^1.0.1" + glob "^7.1.2" + is-reference "^1.1.2" + magic-string "^0.25.2" + resolve "^1.11.0" + "@rollup/plugin-json@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3" @@ -3183,6 +3349,19 @@ is-module "^1.0.0" resolve "^1.11.1" +"@rollup/plugin-node-resolve@^8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz#261d79a680e9dc3d86761c14462f24126ba83575" + integrity sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ== + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + builtin-modules "^3.1.0" + deep-freeze "^0.0.1" + deepmerge "^4.2.2" + is-module "^1.0.0" + resolve "^1.17.0" + "@rollup/pluginutils@^3.0.0", "@rollup/pluginutils@^3.0.8": version "3.0.10" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.0.10.tgz#a659b9025920378494cd8f8c59fbf9b3a50d5f12" @@ -3192,6 +3371,15 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + "@rtsao/csstype@2.6.5-forked.0": version "2.6.5-forked.0" resolved "https://registry.yarnpkg.com/@rtsao/csstype/-/csstype-2.6.5-forked.0.tgz#b5b4e2a07ad83a91874ebf5fabdb73dc8c1632f6" @@ -3854,6 +4042,14 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/react@^16.9.38": + version "16.9.43" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.43.tgz#c287f23f6189666ee3bebc2eb8d0f84bcb6cdb6b" + integrity sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + "@types/reflexbox@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/reflexbox/-/reflexbox-4.0.1.tgz#dfe91aace3c931766507cfd1cce65498a4d052a0" @@ -3870,6 +4066,13 @@ dependencies: "@types/node" "*" +"@types/resolve@1.17.1": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" + integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== + dependencies: + "@types/node" "*" + "@types/rimraf@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.3.tgz#0199a46af106729ba14213fda7b981278d8c84f2" @@ -4069,6 +4272,11 @@ dependencies: "@types/node" "*" +"@types/yoga-layout@1.9.2": + version "1.9.2" + resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.2.tgz#efaf9e991a7390dc081a0b679185979a83a9639a" + integrity sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw== + "@typescript-eslint/eslint-plugin@^2.24.0", "@typescript-eslint/eslint-plugin@^2.28.0": version "2.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.28.0.tgz#4431bc6d3af41903e5255770703d4e55a0ccbdec" @@ -4119,6 +4327,13 @@ dependencies: wonka "^4.0.14" +"@urql/core@^1.12.3": + version "1.12.3" + resolved "https://registry.yarnpkg.com/@urql/core/-/core-1.12.3.tgz#74f7b8e073cf706380bb3dd28484b8136cc96905" + integrity sha512-e4IXXQ4nes3KyusgYV925DuzfDAfo4ex7Ls3tZfOExkxEcXh0i0XnizXp0rvZmWRch69YCkc+Lh1Gy2aY49HTQ== + dependencies: + wonka "^4.0.14" + "@verdaccio/commons-api@9.6.1", "@verdaccio/commons-api@^9.6.1": version "9.6.1" resolved "https://registry.yarnpkg.com/@verdaccio/commons-api/-/commons-api-9.6.1.tgz#f62d1e0d7e55f19c483989f718ed2df2bf55ae3a" @@ -4440,7 +4655,7 @@ acorn@^6.0.1, acorn@^6.0.4, acorn@^6.0.7, acorn@^6.1.1, acorn@^6.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.0.0, acorn@^7.1.0, acorn@^7.3.1: +acorn@^7.0.0, acorn@^7.1.0, acorn@^7.2.0: version "7.3.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== @@ -5165,7 +5380,7 @@ atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" -auto-bind@^4.0.0: +auto-bind@4.0.0, auto-bind@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ== @@ -5331,13 +5546,13 @@ babel-plugin-apply-mdx-type-prop@1.6.16: "@babel/helper-plugin-utils" "7.10.4" "@mdx-js/util" "1.6.16" -babel-plugin-apply-mdx-type-prop@^1.6.6: - version "1.6.6" - resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.6.tgz#f72d7ff9f40620c51280a1acb4964c55bc07ba02" - integrity sha512-rUzVvkQa8/9M63OZT6qQQ1bS8P0ozhXp9e5uJ3RwRJF5Me7s4nZK5SYhyNHYc0BkAflWnCOGMP3oPQUfuyB8tg== +babel-plugin-apply-mdx-type-prop@^2.0.0-next.7: + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-2.0.0-next.7.tgz#6a2eeac3b0c281515c69cbc08d5163856e288e50" + integrity sha512-JhT3sMNjNRzrMxpgkVUN5s3UvDpDCcUTsqsgZvIC2OXtQqNR8ZJxMHckbAJRWmz0YqyuVbFgLUQKpDGHAAB6GA== dependencies: - "@babel/helper-plugin-utils" "7.8.3" - "@mdx-js/util" "^1.6.6" + "@babel/helper-plugin-utils" "7.10.4" + "@mdx-js/util" "^2.0.0-next.7" babel-plugin-codegen@^4.0.0: version "4.0.1" @@ -5376,6 +5591,13 @@ babel-plugin-emotion@^10.0.27: find-root "^1.1.0" source-map "^0.5.7" +babel-plugin-extract-export-names@^2.0.0-next.7: + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/babel-plugin-extract-export-names/-/babel-plugin-extract-export-names-2.0.0-next.7.tgz#26be2512f8535a92c47fc727ce2de873313658cd" + integrity sha512-CTsKh5l99oBd5jemej5BHdzxwaXDYNi3zryGEHaCcO6h3H6OAx7sQyHV76yO7eWHXFBc+t30YSuubpwJQwLHhg== + dependencies: + "@babel/helper-plugin-utils" "7.10.4" + babel-plugin-extract-import-names@1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.16.tgz#b964004e794bdd62534c525db67d9e890d5cc079" @@ -5383,12 +5605,12 @@ babel-plugin-extract-import-names@1.6.16: dependencies: "@babel/helper-plugin-utils" "7.10.4" -babel-plugin-extract-import-names@^1.6.6: - version "1.6.6" - resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.6.tgz#70e39a46f1b2a08fbd061336a322d1ddd81a2f44" - integrity sha512-UtMuiQJnhVPAGE2+pDe7Nc9NVEmDdqGTN74BtRALgH+7oag88RpxFLOSiA+u5mFkFg741wW9Ut5KiyJpksEj/g== +babel-plugin-extract-import-names@^2.0.0-next.7: + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-2.0.0-next.7.tgz#e55b24fd2c86b2a7e55af279953c4a1bb6bc7b60" + integrity sha512-WSYLKKC9a3nLbfnrrbXoEeC8LS3jCn1wBWOcc4Tlwl7n97EBuvCEEMQCHnV7rEDQFl9impbAKr9kLH0QEa8IXg== dependencies: - "@babel/helper-plugin-utils" "7.8.3" + "@babel/helper-plugin-utils" "7.10.4" babel-plugin-istanbul@^4.1.6: version "4.1.6" @@ -5465,6 +5687,11 @@ babel-plugin-react-css-modules@^3.4.2: postcss-modules-scope "^1.1.0" postcss-modules-values "^1.3.0" +babel-plugin-remove-export-keywords@^1.6.5: + version "1.6.16" + resolved "https://registry.yarnpkg.com/babel-plugin-remove-export-keywords/-/babel-plugin-remove-export-keywords-1.6.16.tgz#e764b42e3c8e4a5ce3e2c996dc43b6348d5d94cf" + integrity sha512-JrB9ZASlMAfkRF+5NdgoQxgenhJxzXFEO1vrqsSDJdzLrC38L2wrvXF9mm1YLbrehkZxcrNz9UYDyARP4jaY9g== + babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -6131,6 +6358,13 @@ builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" +builtins@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-2.0.1.tgz#42a4d6fe38973a7c185b435970d13e5e70f70f3c" + integrity sha512-XkkVe5QAb6guWPXTzpSrYpSlN3nqEmrrE2TkAr/tp7idSF6+MONh9WvKrAuR3HiKLvoSgmbs8l1U9IPmMrIoLw== + dependencies: + semver "^6.0.0" + bunyan@1.8.13: version "1.8.13" resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.13.tgz#dde6bacd9ebccaedb110f1319f88db3f415ccfeb" @@ -6440,6 +6674,14 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + change-case@^3.0.1, change-case@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.1.0.tgz#0e611b7edc9952df2e8513b27b42de72647dd17e" @@ -6676,6 +6918,11 @@ cli-spinners@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" +cli-spinners@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f" + integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA== + cli-table3@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" @@ -6815,6 +7062,13 @@ coa@~1.0.1: dependencies: q "^1.1.2" +code-excerpt@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-3.0.0.tgz#fcfb6748c03dba8431c19f5474747fad3f250f10" + integrity sha512-VHNTVhd7KsLGOqfX3SyeO8RyYPMp1GJOg194VITk04WMYCv4plV68YWe6TJZxd9MhobjtpMRnVky01gqZsalaw== + dependencies: + convert-to-spaces "^1.0.1" + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -7087,6 +7341,21 @@ concat-with-sourcemaps@^1.1.0: dependencies: source-map "^0.6.1" +concurrently@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-5.2.0.tgz#ead55121d08a0fc817085584c123cedec2e08975" + integrity sha512-XxcDbQ4/43d6CxR7+iV8IZXhur4KbmEJk1CetVMUqCy34z9l0DkszbY+/9wvmSnToTej0SYomc2WSRH+L0zVJw== + dependencies: + chalk "^2.4.2" + date-fns "^2.0.1" + lodash "^4.17.15" + read-pkg "^4.0.1" + rxjs "^6.5.2" + spawn-command "^0.0.2-1" + supports-color "^6.1.0" + tree-kill "^1.2.2" + yargs "^13.3.0" + config-chain@^1.1.11: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" @@ -7188,6 +7457,16 @@ content-type@^1.0.4, content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" +contentful-management@^5.26.3: + version "5.28.0" + resolved "https://registry.yarnpkg.com/contentful-management/-/contentful-management-5.28.0.tgz#f3b58d60400d66e42439bbd9085cecb0e486f0bb" + integrity sha512-o+qihN3zrD6+/BT/e8n26jl/zQvmV6+9S6NY5QDmzM+IaiSeCk6yvPMq74s+IZT9mOS54igl6qFTbeIpdJ9FDA== + dependencies: + axios "^0.19.0" + contentful-sdk-core "^6.4.0" + lodash "^4.17.11" + type-fest "0.15.1" + contentful-resolve-response@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/contentful-resolve-response/-/contentful-resolve-response-1.2.2.tgz#3f83a5f4742854de740e250a11020b4fb646da91" @@ -7195,7 +7474,7 @@ contentful-resolve-response@^1.2.2: dependencies: lodash "^4.17.15" -contentful-sdk-core@^6.4.5: +contentful-sdk-core@^6.4.0, contentful-sdk-core@^6.4.5: version "6.4.5" resolved "https://registry.yarnpkg.com/contentful-sdk-core/-/contentful-sdk-core-6.4.5.tgz#e73f4c5426f354608543fc73e46c17c6730180e9" integrity sha512-rygNuiwbG6UKrJg6EDlaKewayTeLWrjA2wJwVmq7rV/DYo0cic6t28y0EMhRQ4pgJDV5HyUQFoFeBm2lwLfG2Q== @@ -7320,6 +7599,11 @@ convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, dependencies: safe-buffer "~5.1.1" +convert-to-spaces@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz#7e3e48bbe6d997b1417ddca2868204b4d3d85715" + integrity sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU= + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -8011,6 +8295,11 @@ date-fns@^1.27.2, date-fns@^1.30.1: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== +date-fns@^2.0.1: + version "2.15.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.15.0.tgz#424de6b3778e4e69d3ff27046ec136af58ae5d5f" + integrity sha512-ZCPzAMJZn3rNUvvQIMlXhDr4A+Ar07eLeGsGREoWU19a3Pqf5oYa+ccd+B3F6XVtQY6HANMFdOQ8A+ipFnvJdQ== + date-fns@^2.14.0, date-fns@^2.8.1: version "2.14.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.14.0.tgz#359a87a265bb34ef2e38f93ecf63ac453f9bc7ba" @@ -8159,6 +8448,11 @@ deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" +deep-freeze@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84" + integrity sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ= + deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -9175,6 +9469,11 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -9638,6 +9937,11 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== +eventemitter3@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + events@^1.1.0, events@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -10110,6 +10414,13 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" +figures@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" @@ -10380,6 +10691,11 @@ flatted@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" +flatted@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.0.4.tgz#f75ed043c803c8ca43a4d0bbc05f2bf20b5d9656" + integrity sha512-4gZhsMc26tSiMgQ+0gRN818ST2KCkX/4EvqocCkE1+SRb7mapNk4KLSP+XAj02jc8rxuyD3DrmI3a0BQ/TNOpg== + flow-parser@0.*: version "0.105.2" resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.105.2.tgz#7ba3ab7718c0519979c2f061e89c7b3c3624ee96" @@ -10523,6 +10839,20 @@ format@^0.2.0, format@^0.2.2: resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= +formik@^2.0.8: + version "2.1.5" + resolved "https://registry.yarnpkg.com/formik/-/formik-2.1.5.tgz#de5bbbe35543fa6d049fe96b8ee329d6cd6892b8" + integrity sha512-bWpo3PiqVDYslvrRjTq0Isrm0mFXHiO33D8MS6t6dWcqSFGeYF52nlpCM2xwOJ6tRVRznDkL+zz/iHPL4LDuvQ== + dependencies: + deepmerge "^2.1.1" + hoist-non-react-statics "^3.3.0" + lodash "^4.17.14" + lodash-es "^4.17.14" + react-fast-compare "^2.0.1" + scheduler "^0.18.0" + tiny-warning "^1.0.2" + tslib "^1.10.0" + formik@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/formik/-/formik-2.1.4.tgz#8deef07ec845ea98f75e03da4aad7aab4ac46570" @@ -10722,6 +11052,26 @@ gatsby-interface@0.0.183: lodash.sample "^4.2.1" theme-ui "^0.2.49" +gatsby-interface@^0.0.166: + version "0.0.166" + resolved "https://registry.yarnpkg.com/gatsby-interface/-/gatsby-interface-0.0.166.tgz#ce970498fa0b36767595d423a30ed16a4832ac1e" + integrity sha512-PN0lTVOKu50zfY7kfjgHvT5jsYZIOdSxuWrV/WVxDXo4O3oifLiWUyfFy8zg9T8S1G+TwRyfzhWT9Pfj1CZ2Dg== + dependencies: + "@mdx-js/react" "^1.5.2" + "@reach/alert" "0.10.3" + "@reach/combobox" "0.10.3" + "@reach/dialog" "0.10.3" + "@reach/menu-button" "0.10.3" + "@reach/popover" "0.10.3" + "@reach/tabs" "0.10.3" + "@reach/tooltip" "0.10.3" + "@types/lodash.sample" "^4.2.6" + case "^1.6.2" + date-fns "^2.8.1" + gatsby-design-tokens "^2.0.2" + lodash.sample "^4.2.1" + theme-ui "^0.2.49" + gatsby-node-helpers@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/gatsby-node-helpers/-/gatsby-node-helpers-0.3.0.tgz#3bdca3b7902a702a5834fef280ad66d51099d57c" @@ -11746,30 +12096,7 @@ hasha@^5.2.0: is-stream "^2.0.0" type-fest "^0.8.0" -hast-to-hyperscript@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-5.0.0.tgz#5106cbba78edb7c95e2e8a49079371eb196c1ced" - dependencies: - comma-separated-tokens "^1.0.0" - property-information "^4.0.0" - space-separated-tokens "^1.0.0" - style-to-object "^0.2.1" - unist-util-is "^2.0.0" - web-namespaces "^1.1.2" - -hast-to-hyperscript@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-7.0.2.tgz#e9237c88c6069999ad38aec847fefc296f484c4c" - integrity sha512-NBMMst0hkDR21uSH75m9W2DkljBrLoMQEhGiLMLNij4HIzEDJMC1UG+CFR6EAjHi2zs3NHBoaAHJOHxftoIN2g== - dependencies: - comma-separated-tokens "^1.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" - style-to-object "^0.2.1" - unist-util-is "^3.0.0" - web-namespaces "^1.1.2" - -hast-to-hyperscript@^9.0.0: +hast-to-hyperscript@9.0.0, hast-to-hyperscript@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.0.tgz#768fb557765fe28749169c885056417342d71e83" integrity sha512-NJvMYU3GlMLs7hN3CRbsNlMzusVNkYBogVWDGybsuuVQ336gFLiD+q9qtFZT2meSHzln3pNISZWTASWothMSMg== @@ -11782,6 +12109,17 @@ hast-to-hyperscript@^9.0.0: unist-util-is "^4.0.0" web-namespaces "^1.0.0" +hast-to-hyperscript@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-5.0.0.tgz#5106cbba78edb7c95e2e8a49079371eb196c1ced" + dependencies: + comma-separated-tokens "^1.0.0" + property-information "^4.0.0" + space-separated-tokens "^1.0.0" + style-to-object "^0.2.1" + unist-util-is "^2.0.0" + web-namespaces "^1.1.2" + hast-util-from-parse5@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-4.0.2.tgz#b7164a7ffc88da4f751dc7c2f801ff8d7c143bab" @@ -11792,17 +12130,6 @@ hast-util-from-parse5@^4.0.2: web-namespaces "^1.1.2" xtend "^4.0.1" -hast-util-from-parse5@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.1.tgz#7da8841d707dcf7be73715f7f3b14e021c4e469a" - integrity sha512-UfPzdl6fbxGAxqGYNThRUhRlDYY7sXu6XU9nQeX4fFZtV+IHbyEJtd+DUuwOqNV4z3K05E/1rIkoVr/JHmeWWA== - dependencies: - ccount "^1.0.3" - hastscript "^5.0.0" - property-information "^5.0.0" - web-namespaces "^1.1.2" - xtend "^4.0.1" - hast-util-from-parse5@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.0.tgz#b38793c81e1a99f5fd592a4a88fc2731dccd0f30" @@ -11823,20 +12150,6 @@ hast-util-parse-selector@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.0.tgz#2175f18cdd697308fc3431d5c29a9e48dfa4817a" -hast-util-raw@5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-5.0.2.tgz#62288f311ec2f35e066a30d5e0277f963ad43a67" - integrity sha512-3ReYQcIHmzSgMq8UrDZHFL0oGlbuVGdLKs8s/Fe8BfHFAyZDrdv1fy/AGn+Fim8ZuvAHcJ61NQhVMtyfHviT/g== - dependencies: - hast-util-from-parse5 "^5.0.0" - hast-util-to-parse5 "^5.0.0" - html-void-elements "^1.0.0" - parse5 "^5.0.0" - unist-util-position "^3.0.0" - web-namespaces "^1.0.0" - xtend "^4.0.0" - zwitch "^1.0.0" - hast-util-raw@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-6.0.0.tgz#49a38f5107d483f83a139709f2f705f22e7e7d32" @@ -11913,17 +12226,6 @@ hast-util-to-parse5@^4.0.1: xtend "^4.0.1" zwitch "^1.0.0" -hast-util-to-parse5@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-5.1.1.tgz#cabf2dbe9ed988a5128fc708457b37cdf535a2e8" - integrity sha512-ivCeAd5FCXr7bapJIVsWMnx/EmbjkkW2TU2hd1prq+jGwiaUoK+FcpjyPNwsC5ogzCwWO669tOqIovGeLc/ntg== - dependencies: - hast-to-hyperscript "^7.0.0" - property-information "^5.0.0" - web-namespaces "^1.0.0" - xtend "^4.0.1" - zwitch "^1.0.0" - hast-util-to-parse5@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" @@ -12610,31 +12912,15 @@ init-package-json@^1.10.3: validate-npm-package-license "^3.0.1" validate-npm-package-name "^3.0.0" -ink-box@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ink-box/-/ink-box-1.0.0.tgz#8cbcb5541d32787d08d43acf1a9907e86e3572f3" - integrity sha512-wD2ldWX9lcE/6+flKbAJ0TZF7gKbTH8CRdhEor6DD8d+V0hPITrrGeST2reDBpCia8wiqHrdxrqTyafwtmVanA== - dependencies: - boxen "^3.0.0" - prop-types "^15.7.2" - -ink-link@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ink-link/-/ink-link-1.1.0.tgz#e00bd68dfd163a9392baecc0808391fd07e6cfbb" - integrity sha512-a716nYz4YDPu8UOA2PwabTZgTvZa3SYB/70yeXVmTOKFAEdMbJyGSVeNuB7P+aM2olzDj9AGVchA7W5QytF9uA== - dependencies: - prop-types "^15.7.2" - terminal-link "^2.1.1" - -ink-select-input@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/ink-select-input/-/ink-select-input-3.1.2.tgz#fd53f2f0946bc43989899522b013a2c10a60f722" - integrity sha512-PaLraGx8A54GhSkTNzZI8bgY0elAoa1jSPPe5Q52B5VutcBoJc4HE3ICDwsEGJ88l1Hw6AWjpeoqrq82a8uQPA== +ink-select-input@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ink-select-input/-/ink-select-input-4.0.0.tgz#ff642302b4ffea53227e96fa9152709de8a3de54" + integrity sha512-LwvsWqJh64ARY/4WxhC9B0+Dcb+BiTm9lzwTW5XH8OT5ng7drs7J7C23ZQdt25ZETCPvzg5BSZf2w6fhdg/SXw== dependencies: arr-rotate "^1.0.0" - figures "^2.0.0" + figures "^3.2.0" + lodash "^4.17.19" lodash.isequal "^4.5.0" - prop-types "^15.5.10" ink-spinner@^3.1.0: version "3.1.0" @@ -12644,6 +12930,14 @@ ink-spinner@^3.1.0: cli-spinners "^1.0.0" prop-types "^15.5.10" +ink-spinner@^4.0.0-0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ink-spinner/-/ink-spinner-4.0.0.tgz#a233df86e17b76a28ba5c76c412b30d43ef96fa7" + integrity sha512-Oq2u5SY1qZ61LbzyQReJxpoRmruLcWw3lRb7cq8t3fj9484Eo5HggayyX5OVEcCGURWyyH8kJmFZJgrSGtJqkA== + dependencies: + "@types/react" "^16.9.38" + cli-spinners "^2.3.0" + ink@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/ink/-/ink-2.7.1.tgz#ff1c75b4b022924e2993af62297fa0e48e85618b" @@ -12668,6 +12962,35 @@ ink@^2.7.1: wrap-ansi "^6.2.0" yoga-layout-prebuilt "^1.9.3" +ink@next: + version "3.0.0-7" + resolved "https://registry.yarnpkg.com/ink/-/ink-3.0.0-7.tgz#e64a7f8ca462f1d07bc371906871c3c2b24c141c" + integrity sha512-Faw3KSntkySygliO5auyn6F1QfuT4lxc77zssuTNcW4I7AL1w1UxZJrhAE6NwaRFLxdHG8eEcvRXjr7V/ZmHmg== + dependencies: + ansi-escapes "^4.2.1" + auto-bind "4.0.0" + chalk "^4.1.0" + cli-boxes "^2.2.0" + cli-cursor "^3.1.0" + cli-truncate "^2.1.0" + code-excerpt "^3.0.0" + indent-string "^4.0.0" + is-ci "^2.0.0" + lodash.throttle "^4.1.1" + patch-console "^1.0.0" + react-devtools-core "^4.6.0" + react-reconciler "^0.24.0" + scheduler "^0.18.0" + signal-exit "^3.0.2" + slice-ansi "^3.0.0" + stack-utils "^2.0.2" + string-length "^3.1.0" + type-fest "^0.12.0" + widest-line "^3.1.0" + wrap-ansi "^6.2.0" + ws "^7.2.5" + yoga-layout-prebuilt "^1.9.6" + inline-style-parser@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" @@ -13449,6 +13772,14 @@ isobject@^4.0.0: resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== +isomorphic-fetch@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -16663,7 +16994,7 @@ node-fetch@2.6.0, node-fetch@^2.3.0, node-fetch@^2.5.0, node-fetch@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" -node-fetch@^1.7.3: +node-fetch@^1.0.1, node-fetch@^1.7.3: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" dependencies: @@ -16889,6 +17220,11 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== +normalize.css@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" + integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg== + normalizeurl@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/normalizeurl/-/normalizeurl-1.0.0.tgz#4b1a458cd0c7d0856436f69c6b51047ab6855317" @@ -17548,6 +17884,14 @@ p-queue@^6.3.0: eventemitter3 "^4.0.0" p-timeout "^3.1.0" +p-queue@^6.4.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.0.tgz#263f2b73add4cefca81d8d6b2696ee74b326de2f" + integrity sha512-zPHXPNy9jZsiym0PpJjvnHQysx1fSd/QdaNVwiDRLU2KFChD6h9CkCB6b8i3U8lBwJyA+mHgNZCzcy77glUssQ== + dependencies: + eventemitter3 "^4.0.4" + p-timeout "^3.1.0" + p-reduce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" @@ -17888,6 +18232,11 @@ password-prompt@^1.0.4: ansi-escapes "^3.1.0" cross-spawn "^6.0.5" +patch-console@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/patch-console/-/patch-console-1.0.0.tgz#19b9f028713feb8a3c023702a8cc8cb9f7466f9d" + integrity sha512-nxl9nrnLQmh64iTzMfyylSlRozL7kAXIaxw1fVcLYdyhNkJCRUzirRZTikXGJsg+hc4fqpneTK6iU2H1Q8THSA== + path-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" @@ -18840,6 +19189,13 @@ property-expr@^2.0.2: resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.2.tgz#fff2a43919135553a3bc2fdd94bdb841965b2330" integrity sha512-bc/5ggaYZxNkFKj374aLbEDqVADdYaLcFo8XBkishUWbaAdjlphaBFns9TvRA2pUseVL/wMFmui9X3IdNDU37g== +property-information@5.5.0, property-information@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.5.0.tgz#4dc075d493061a82e2b7d096f406e076ed859943" + integrity sha512-RgEbCx2HLa1chNgvChcx+rrCWD0ctBmGSE0M7lVm1yyv4UbvbrWoXp/BkVLZefzjrRBGW8/Js6uh/BnlHXFyjA== + dependencies: + xtend "^4.0.0" + property-information@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-4.2.0.tgz#f0e66e07cbd6fed31d96844d958d153ad3eb486e" @@ -18853,13 +19209,6 @@ property-information@^5.0.0, property-information@^5.0.1, property-information@^ dependencies: xtend "^4.0.1" -property-information@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.5.0.tgz#4dc075d493061a82e2b7d096f406e076ed859943" - integrity sha512-RgEbCx2HLa1chNgvChcx+rrCWD0ctBmGSE0M7lVm1yyv4UbvbrWoXp/BkVLZefzjrRBGW8/Js6uh/BnlHXFyjA== - dependencies: - xtend "^4.0.0" - proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" @@ -19145,6 +19494,11 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-circular-progressbar@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/react-circular-progressbar/-/react-circular-progressbar-2.0.3.tgz#fa8eb59f8db168d2904bae4590641792c80f5991" + integrity sha512-YKN+xAShXA3gYihevbQZbavfiJxo83Dt1cUxqg/cltj4VVsRQpDr7Fg1mvjDG3x1KHGtd9NmYKvJ2mMrPwbKyw== + react-clientside-effect@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz#6212fb0e07b204e714581dd51992603d1accc837" @@ -19176,6 +19530,14 @@ react-dev-utils@^4.2.3: strip-ansi "3.0.1" text-table "0.2.0" +react-devtools-core@^4.6.0: + version "4.8.2" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.8.2.tgz#4465f2e8de7795564aa20f28b2f3a9737586db23" + integrity sha512-3Lv3nI8FPAwKqUco35oOlgf+4j8mgYNnIcDv2QTfxEqg2G69q17ZJ8ScU9aBnymS28YC1OW+kTxLmdIQeTN8yg== + dependencies: + shell-quote "^1.6.1" + ws "^7" + react-docgen@^5.0.0: version "5.3.0" resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-5.3.0.tgz#9aabde5e69f1993c8ba839fd9a86696504654589" @@ -19250,7 +19612,7 @@ react-hot-loader@^4.12.21: shallowequal "^1.1.0" source-map "^0.7.3" -react-icons@^3.10.0: +react-icons@^3.0.1, react-icons@^3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-3.10.0.tgz#6c217a2dde2e8fa8d293210023914b123f317297" integrity sha512-WsQ5n1JToG9VixWilSo1bHv842Cj5aZqTGiS3Ud47myF6aK7S/IUY2+dHcBdmkQcCFRuHsJ9OMUI0kTDfjyZXQ== @@ -19511,6 +19873,15 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" +read-pkg@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237" + integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc= + dependencies: + normalize-package-data "^2.3.2" + parse-json "^4.0.0" + pify "^3.0.0" + read-pkg@^5.1.1, read-pkg@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" @@ -20435,6 +20806,28 @@ remark-mdx@^1.6.6: remark-parse "8.0.2" unified "9.0.0" +remark-mdx@^2.0.0-next.4, remark-mdx@^2.0.0-next.7: + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-2.0.0-next.7.tgz#e8d4e4fe2c2a98bb34e10304c6e6f2823ba56dfb" + integrity sha512-JHYCfxJzvjTw8h5y10f+mCvbfIt5klAkWlULqPu1nM/r6ghF3tzJl0AFQFj5b/m/7U553+yYb/y4n0julMERYA== + dependencies: + parse-entities "^2.0.0" + remark-stringify "^8.1.0" + stringify-entities "^3.0.1" + strip-indent "^3.0.0" + unist-util-stringify-position "^2.0.3" + +remark-mdxjs@^2.0.0-next.4, remark-mdxjs@^2.0.0-next.7: + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/remark-mdxjs/-/remark-mdxjs-2.0.0-next.7.tgz#32db2b04abb19ee8e7e383103b16f4f555e198dc" + integrity sha512-ixa9jEQ1mB65NYJaBq+Hv91DIqQ7B3wk+L9Agwa31NkIzvt6zcgx6TKwavr0zZG69I2n1gZzekhp51AeVCzU1Q== + dependencies: + "@babel/core" "7.10.5" + "@babel/helper-plugin-utils" "7.10.4" + "@babel/plugin-proposal-object-rest-spread" "7.10.4" + "@babel/plugin-syntax-jsx" "7.10.4" + "@mdx-js/util" "^2.0.0-next.7" + remark-message-control@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/remark-message-control/-/remark-message-control-6.0.0.tgz#955b054b38c197c9f2e35b1d88a4912949db7fc5" @@ -21273,6 +21666,16 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rollup-plugin-auto-external@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-auto-external/-/rollup-plugin-auto-external-2.0.0.tgz#98fd137d66c1cbe0f4e245b31560a72dbde896aa" + integrity sha512-HQM3ZkZYfSam1uoZtAB9sK26EiAsfs1phrkf91c/YX+S07wugyRXSigBxrIwiLr5EPPilKYmoMxsrnlGBsXnuQ== + dependencies: + builtins "^2.0.0" + read-pkg "^3.0.0" + safe-resolve "^1.0.0" + semver "^5.5.0" + rollup-plugin-bundle-size@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/rollup-plugin-bundle-size/-/rollup-plugin-bundle-size-1.0.3.tgz#d245cd988486b4040279f9fd33f357f61673e90f" @@ -21292,6 +21695,14 @@ rollup-plugin-hypothetical@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/rollup-plugin-hypothetical/-/rollup-plugin-hypothetical-2.1.0.tgz#7fec9a865ed7d0eac14ca6ee2b2c4088acdb1955" +rollup-plugin-internal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/rollup-plugin-internal/-/rollup-plugin-internal-1.0.4.tgz#3b2f221e4cda5eed51742a0f81617e3840473450" + integrity sha512-abFOORRqps1dICHgLqasbVG+Kt45BDifUj5XuLSGQm/UBnrLuj9ctKxw8388B4YS9Gk6pv3YRjNIsJ/SJKBE9w== + dependencies: + safe-resolve "^1.0.0" + tslib "^1.10.0" + rollup-plugin-postcss@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/rollup-plugin-postcss/-/rollup-plugin-postcss-2.9.0.tgz#e6ea0a1b8fdc4a49fc0385da58804e332750c282" @@ -21377,6 +21788,13 @@ rollup@^2.0.0: optionalDependencies: fsevents "~2.1.2" +rollup@^2.23.0: + version "2.23.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.23.0.tgz#b7ab1fee0c0e60132fd0553c4df1e9cdacfada9d" + integrity sha512-vLNmZFUGVwrnqNAJ/BvuLk1MtWzu4IuoqsH9UWK5AIdO3rt8/CSiJNvPvCIvfzrbNsqKbNzPAG1V2O4eTe2XZg== + optionalDependencies: + fsevents "~2.1.2" + rss@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/rss/-/rss-1.2.2.tgz#50a1698876138133a74f9a05d2bdc8db8d27a921" @@ -21426,6 +21844,13 @@ rxjs@^6.1.0, rxjs@^6.4.0: dependencies: tslib "^1.9.0" +rxjs@^6.5.2: + version "6.6.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" + integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== + dependencies: + tslib "^1.9.0" + sade@^1.7.3: version "1.7.3" resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.3.tgz#a217ccc4fb4abb2d271648bf48f6628b2636fa1b" @@ -21461,6 +21886,11 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" +safe-resolve@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-resolve/-/safe-resolve-1.0.0.tgz#fe34f8d29d7a3becfd249d0aa8a799b5c3cf6559" + integrity sha1-/jT40p16O+z9JJ0KqKeZtcPPZVk= + "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -22179,6 +22609,11 @@ sparse-bitfield@^3.0.3: dependencies: memory-pager "^1.0.2" +spawn-command@^0.0.2-1: + version "0.0.2-1" + resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" + integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= + spdx-correct@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" @@ -22333,6 +22768,13 @@ stack-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" +stack-utils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593" + integrity sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg== + dependencies: + escape-string-regexp "^2.0.0" + stackframe@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.1.1.tgz#ffef0a3318b1b60c3b58564989aca5660729ec71" @@ -22637,6 +23079,17 @@ stringify-entities@^3.0.0: is-decimal "^1.0.2" is-hexadecimal "^1.0.0" +stringify-entities@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-3.0.1.tgz#32154b91286ab0869ab2c07696223bd23b6dbfc0" + integrity sha512-Lsk3ISA2++eJYqBMPKcr/8eby1I6L0gP0NlxF8Zja6c05yr/yCYyb2c9PwXjd08Ib3If1vn1rbs1H5ZtVuOfvQ== + dependencies: + character-entities-html4 "^1.0.0" + character-entities-legacy "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.2" + is-hexadecimal "^1.0.0" + stringify-object@^3.2.2, stringify-object@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" @@ -23187,7 +23640,7 @@ term-size@^2.1.0: resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.1.0.tgz#3aec444c07a7cf936e157c1dc224b590c3c7eef2" integrity sha512-I42EWhJ+2aeNQawGx1VtpO0DFI9YcfuvAMNIdKyf/6sRbHJ4P+ZQ/zIT87tE+ln1ymAGcCJds4dolfSAS0AcNg== -terminal-link@^2.1.1: +terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== @@ -23563,6 +24016,11 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + trim-lines@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.1.tgz#da738ff58fa74817588455e30b11b85289f2a396" @@ -23697,6 +24155,16 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-fest@0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.15.1.tgz#d2c4e73d3e4a53cf1a906396dd460a1c5178ca00" + integrity sha512-n+UXrN8i5ioo7kqT/nF8xsEzLaqFra7k32SEsSPwvXVGyAcRgV/FUQN/sgfptJTR1oRmmq7z4IXMFSM7im7C9A== + +type-fest@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.12.0.tgz#f57a27ab81c68d136a51fd71467eff94157fa1ee" + integrity sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg== + type-fest@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" @@ -24162,6 +24630,13 @@ unist-util-stringify-position@^2.0.0: dependencies: "@types/unist" "^2.0.2" +unist-util-stringify-position@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + dependencies: + "@types/unist" "^2.0.2" + unist-util-visit-children@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/unist-util-visit-children/-/unist-util-visit-children-1.1.2.tgz#bd78b53db9644b9c339ac502854f15471f964f5b" @@ -24181,15 +24656,6 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.3" unist-util-is "^4.0.0" -unist-util-visit@2.0.2, unist-util-visit@^2.0.0, unist-util-visit@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.2.tgz#3843782a517de3d2357b4c193b24af2d9366afb7" - integrity sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" - unist-util-visit@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" @@ -24206,6 +24672,15 @@ unist-util-visit@^1.0.0, unist-util-visit@^1.1.0, unist-util-visit@^1.3.0, unist dependencies: unist-util-visit-parents "^2.0.0" +unist-util-visit@^2.0.0, unist-util-visit@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.2.tgz#3843782a517de3d2357b4c193b24af2d9366afb7" + integrity sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + universal-url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universal-url/-/universal-url-2.0.0.tgz#35e7fc2c3374804905cee67ea289ed3a47669809" @@ -24408,6 +24883,14 @@ urltools@^0.4.1: underscore "^1.8.3" urijs "^1.18.2" +urql@^1.9.7: + version "1.10.0" + resolved "https://registry.yarnpkg.com/urql/-/urql-1.10.0.tgz#609f13891d3c5345635764b71b072edd88a1ae7e" + integrity sha512-Cxx1INTWNUMg9A2gyltqNqukOLFVtztkHxFGfv01OvsFAtR+wCmLyJqIzGUZRKVbKepTLocGbelS7QDxtjcqtg== + dependencies: + "@urql/core" "^1.12.3" + wonka "^4.0.14" + urql@^1.9.8: version "1.9.8" resolved "https://registry.yarnpkg.com/urql/-/urql-1.9.8.tgz#07d76efdc698205a55724a2acd2640f7706a036d" @@ -24504,6 +24987,11 @@ uuid@^7.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== +uuid@^8.2.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" + integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== + v8-compile-cache@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz#8d32e4f16974654657e676e0e467a348e89b0dc4" @@ -25024,6 +25512,11 @@ whatwg-fetch@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" +whatwg-fetch@>=0.10.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.2.0.tgz#8e134f701f0a4ab5fda82626f113e2b647fd16dc" + integrity sha512-SdGPoQMMnzVYThUbSrEvqTlkvC1Ux27NehaJ/GUHBfNrh5Mjg+1/uRyFMwVnxO2MrikMWvWAqUGgQOfVU4hT7w== + whatwg-fetch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.1.0.tgz#49d630cdfa308dba7f2819d49d09364f540dbcc6" @@ -25401,6 +25894,11 @@ ws@^6.1.0, ws@^6.1.2, ws@^6.2.1: dependencies: async-limiter "~1.0.0" +ws@^7, ws@^7.2.5: + version "7.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" + integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== + ws@^7.0.0, ws@^7.1.2, ws@^7.2.3, ws@^7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd" @@ -25512,7 +26010,7 @@ xss@^1.0.6: commander "^2.20.3" cssfilter "0.0.10" -xstate@^4.11.0: +xstate@^4.11.0, xstate@^4.9.1: version "4.11.0" resolved "https://registry.yarnpkg.com/xstate/-/xstate-4.11.0.tgz#dc0bd31079fe22918c2c27c118d6310bef3dcd9e" integrity sha512-v+S3jF2YrM2tFOit8o7+4N3FuFd9IIGcIKHyfHeeNjMlmNmwuiv/IbY9uw7ECifx7H/A9aGLcxPSr0jdjTGDww== @@ -25723,6 +26221,13 @@ yoga-layout-prebuilt@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.9.3.tgz#11e3be29096afe3c284e5d963cc2d628148c1372" +yoga-layout-prebuilt@^1.9.6: + version "1.9.6" + resolved "https://registry.yarnpkg.com/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.9.6.tgz#98dde95bbf8e6e12835876e9305f1e995c4bb801" + integrity sha512-Wursw6uqLXLMjBAO4SEShuzj8+EJXhCF71/rJ7YndHTkRAYSU0GY3OghRqfAk9HPUAAFMuqp3U1Wl+01vmGRQQ== + dependencies: + "@types/yoga-layout" "1.9.2" + yup@^0.27.0: version "0.27.0" resolved "https://registry.yarnpkg.com/yup/-/yup-0.27.0.tgz#f8cb198c8e7dd2124beddc2457571329096b06e7"