From ee07aaa01dc25481247a8ae4539333c43f5ee8c8 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 2 Mar 2022 09:06:31 +0000 Subject: [PATCH 001/171] Don't set explicit height of tables when total row count is equal or less than the desired rows, to avoid tiny overflow due to horizontal scrollbars --- packages/bbui/src/Table/Table.svelte | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/bbui/src/Table/Table.svelte b/packages/bbui/src/Table/Table.svelte index c9d7f12339..1d957b3f30 100644 --- a/packages/bbui/src/Table/Table.svelte +++ b/packages/bbui/src/Table/Table.svelte @@ -56,6 +56,7 @@ $: if (!loading) loaded = true $: fields = getFields(schema, showAutoColumns, autoSortColumns) $: rows = fields?.length ? data || [] : [] + $: totalRowCount = rows?.length || 0 $: visibleRowCount = getVisibleRowCount( loaded, height, @@ -63,7 +64,12 @@ rowCount, rowHeight ) - $: contentStyle = getContentStyle(visibleRowCount, rowCount, rowHeight) + $: heightStyle = getHeightStyle( + visibleRowCount, + rowCount, + totalRowCount, + rowHeight + ) $: sortedRows = sortRows(rows, sortColumn, sortOrder) $: gridStyle = getGridStyle(fields, schema, showEditColumn) $: showEditColumn = allowEditRows || allowSelectRows @@ -107,11 +113,16 @@ return Math.min(allRows, Math.ceil(height / rowHeight)) } - const getContentStyle = (visibleRows, rowCount, rowHeight) => { - if (!rowCount || !visibleRows) { + const getHeightStyle = ( + visibleRowCount, + rowCount, + totalRowCount, + rowHeight + ) => { + if (!rowCount || !visibleRowCount || totalRowCount <= rowCount) { return "" } - return `height: ${headerHeight + visibleRows * rowHeight}px;` + return `height: ${headerHeight + visibleRowCount * rowHeight}px;` } const getGridStyle = (fields, schema, showEditColumn) => { @@ -264,11 +275,11 @@ style={`--row-height: ${rowHeight}px; --header-height: ${headerHeight}px;`} > {#if !loaded} -
+
{:else} -
+
{#if fields.length}
{#if showEditColumn} From e411354538c2098e9e86954680fdb661724d6e3c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 2 Mar 2022 17:45:01 +0000 Subject: [PATCH 002/171] Improve copy and paste to support keeping all data bindings valid --- .../src/builderStore/componentUtils.js | 61 +++++++++++++++++++ .../src/builderStore/store/frontend.js | 23 ++----- .../ComponentDropdownMenu.svelte | 6 +- packages/string-templates/src/index.cjs | 1 + packages/string-templates/src/index.js | 9 +++ packages/string-templates/src/index.mjs | 1 + 6 files changed, 79 insertions(+), 22 deletions(-) diff --git a/packages/builder/src/builderStore/componentUtils.js b/packages/builder/src/builderStore/componentUtils.js index 04a87998fe..557d83a00c 100644 --- a/packages/builder/src/builderStore/componentUtils.js +++ b/packages/builder/src/builderStore/componentUtils.js @@ -1,4 +1,10 @@ import { store } from "./index" +import { Helpers } from "@budibase/bbui" +import { + decodeJSBinding, + encodeJSBinding, + findAllBindings, +} from "@budibase/string-templates" /** * Recursively searches for a specific component ID @@ -161,3 +167,58 @@ export const getComponentSettings = componentType => { return settings } + +/** + * Randomises a components ID's, including all child component IDs, and also + * updates all data bindings to still be valid. + * This mutates the object in place. + * @param component the component to randomise + */ +export const makeComponentUnique = component => { + if (!component) { + return + } + + // Replace component ID + const oldId = component._id + const newId = Helpers.uuid() + component._id = newId + + if (component._children?.length) { + let children = JSON.stringify(component._children) + + // Replace all instances of this ID in child HBS bindings + children = children.replace(new RegExp(oldId, "g"), newId) + + // Replace all instances of this ID in child JS bindings + const bindings = findAllBindings(children) + bindings.forEach(binding => { + // JSON.stringify will have escaped double quotes, so we need + // to account for that + let sanitizedBinding = binding.replace(/\\"/g, '"') + + // Check if this is a valid JS binding + let js = decodeJSBinding(sanitizedBinding) + if (js != null) { + // Replace ID inside JS binding + js = js.replace(new RegExp(oldId, "g"), newId) + + // Create new valid JS binding + let newBinding = encodeJSBinding(js) + + // Replace escaped double quotes + newBinding = newBinding.replace(/"/g, '\\"') + + // Insert new JS back into binding. + // A single string replace here is better than a regex as + // the binding contains special characters, and we only need + // to replace a single instance. + children = children.replace(binding, newBinding) + } + }) + + // Recurse on all children + component._children = JSON.parse(children) + component._children.forEach(makeComponentUnique) + } +} diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index d8118c9c60..c8e4c85b06 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -24,9 +24,9 @@ import { findAllMatchingComponents, findComponent, getComponentSettings, + makeComponentUnique, } from "../componentUtils" import { Helpers } from "@budibase/bbui" -import { removeBindings } from "../dataBinding" const INITIAL_FRONTEND_STATE = { apps: [], @@ -490,37 +490,22 @@ export const getFrontendStore = () => { } } }, - paste: async (targetComponent, mode, preserveBindings = false) => { + paste: async (targetComponent, mode) => { let promises = [] store.update(state => { // Stop if we have nothing to paste if (!state.componentToPaste) { return state } - - // defines if this is a copy or a cut const cut = state.componentToPaste.isCut - // immediately need to remove bindings, currently these aren't valid when pasted - if (!cut && !preserveBindings) { - state.componentToPaste = removeBindings(state.componentToPaste, "") - } - - // Clone the component to paste - // Retain the same ID if cutting as things may be referencing this component + // Clone the component to paste and make unique if copying delete state.componentToPaste.isCut let componentToPaste = cloneDeep(state.componentToPaste) if (cut) { state.componentToPaste = null } else { - const randomizeIds = component => { - if (!component) { - return - } - component._id = Helpers.uuid() - component._children?.forEach(randomizeIds) - } - randomizeIds(componentToPaste) + makeComponentUnique(componentToPaste) } if (mode === "inside") { diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte index 0fcd43b58e..c8796fab25 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte @@ -61,7 +61,7 @@ const duplicateComponent = () => { storeComponentForCopy(false) - pasteComponent("below", true) + pasteComponent("below") } const deleteComponent = async () => { @@ -77,10 +77,10 @@ store.actions.components.copy(component, cut) } - const pasteComponent = (mode, preserveBindings = false) => { + const pasteComponent = mode => { try { // lives in store - also used by drag drop - store.actions.components.paste(component, mode, preserveBindings) + store.actions.components.paste(component, mode) } catch (error) { notifications.error("Error saving component") } diff --git a/packages/string-templates/src/index.cjs b/packages/string-templates/src/index.cjs index 5a84c45d78..9584374880 100644 --- a/packages/string-templates/src/index.cjs +++ b/packages/string-templates/src/index.cjs @@ -18,6 +18,7 @@ module.exports.processObject = templates.processObject module.exports.doesContainStrings = templates.doesContainStrings module.exports.doesContainString = templates.doesContainString module.exports.disableEscaping = templates.disableEscaping +module.exports.findAllBindings = templates.findAllBindings /** * Use vm2 to run JS scripts in a node env diff --git a/packages/string-templates/src/index.js b/packages/string-templates/src/index.js index eedd9423ee..76ad979670 100644 --- a/packages/string-templates/src/index.js +++ b/packages/string-templates/src/index.js @@ -322,3 +322,12 @@ module.exports.doesContainStrings = (template, strings) => { module.exports.doesContainString = (template, string) => { return exports.doesContainStrings(template, [string]) } + +/** + * Finds all regular (double bracketed) expressions inside a string. + * @param string the string to search + * @return {[]} all matching bindings + */ +module.exports.findAllBindings = string => { + return findDoubleHbsInstances(string) +} diff --git a/packages/string-templates/src/index.mjs b/packages/string-templates/src/index.mjs index f2cffdf378..a9745b3a34 100644 --- a/packages/string-templates/src/index.mjs +++ b/packages/string-templates/src/index.mjs @@ -18,6 +18,7 @@ export const processObject = templates.processObject export const doesContainStrings = templates.doesContainStrings export const doesContainString = templates.doesContainString export const disableEscaping = templates.disableEscaping +export const findAllBindings = templates.findAllBindings /** * Use polyfilled vm to run JS scripts in a browser Env From f2fbd3d1d0bb930c70f79c99f92718a65437eb46 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 2 Mar 2022 19:10:18 +0000 Subject: [PATCH 003/171] Rewrite screen wizard to make modals reusable and fix some edge case URL bugs --- .../store/screenTemplates/index.js | 7 +- .../ComponentDropdownMenu.svelte | 2 - .../ScreenDropdownMenu.svelte | 5 + .../NavigationPanel/NewScreenModal.svelte | 48 ++--- .../NavigationPanel/ScreenDetailsModal.svelte | 43 ++-- .../NavigationPanel/ScreenWizard.svelte | 200 +++++++++--------- 6 files changed, 143 insertions(+), 162 deletions(-) diff --git a/packages/builder/src/builderStore/store/screenTemplates/index.js b/packages/builder/src/builderStore/store/screenTemplates/index.js index 38ae434753..51496bdeb3 100644 --- a/packages/builder/src/builderStore/store/screenTemplates/index.js +++ b/packages/builder/src/builderStore/store/screenTemplates/index.js @@ -10,17 +10,18 @@ const allTemplates = tables => [ ] // Allows us to apply common behaviour to all create() functions -const createTemplateOverride = (frontendState, create) => () => { - const screen = create() +const createTemplateOverride = (frontendState, template) => () => { + const screen = template.create() screen.name = screen.props._id screen.routing.route = screen.routing.route.toLowerCase() + screen.template = template.id return screen } export default (frontendState, tables) => { const enrichTemplate = template => ({ ...template, - create: createTemplateOverride(frontendState, template.create), + create: createTemplateOverride(frontendState, template), }) const fromScratch = enrichTemplate(createFromScratchScreen) diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte index c8796fab25..df6be7e88f 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte @@ -73,13 +73,11 @@ } const storeComponentForCopy = (cut = false) => { - // lives in store - also used by drag drop store.actions.components.copy(component, cut) } const pasteComponent = mode => { try { - // lives in store - also used by drag drop store.actions.components.paste(component, mode) } catch (error) { notifications.error("Error saving component") diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 38ed79649e..47c9fb65b1 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -10,6 +10,8 @@ $: screen = $allScreens.find(screen => screen._id === screenId) + const duplicateScreen = () => {} + const deleteScreen = async () => { try { await store.actions.screens.delete(screen) @@ -25,6 +27,9 @@
+ + Duplicate + Delete diff --git a/packages/builder/src/components/design/NavigationPanel/NewScreenModal.svelte b/packages/builder/src/components/design/NavigationPanel/NewScreenModal.svelte index c48ba33efa..cd83d81235 100644 --- a/packages/builder/src/components/design/NavigationPanel/NewScreenModal.svelte +++ b/packages/builder/src/components/design/NavigationPanel/NewScreenModal.svelte @@ -10,39 +10,19 @@ ProgressCircle, } from "@budibase/bbui" import getTemplates from "builderStore/store/screenTemplates" - import { onDestroy } from "svelte" - import { createEventDispatcher } from "svelte" - - export let chooseModal - export let save + export let onConfirm + export let onCancel export let showProgressCircle = false - let selectedScreens = [] - const blankScreen = "createFromScratch" - const dispatch = createEventDispatcher() - function setScreens() { - dispatch("save", { - screens: selectedScreens, - }) - } + let selectedScreens = [] + let templates = getTemplates($store, $tables.list) $: blankSelected = selectedScreens?.length === 1 $: autoSelected = selectedScreens?.length > 0 && !blankSelected - let templates = getTemplates($store, $tables.list) - - const confirm = async () => { - if (autoSelected) { - setScreens() - await save() - } else { - setScreens() - chooseModal(1) - } - } const toggleScreenSelection = table => { if (selectedScreens.find(s => s.table === table.name)) { selectedScreens = selectedScreens.filter( @@ -56,25 +36,25 @@ } } - onDestroy(() => { - selectedScreens = [] - }) + const confirmScreenSelection = async () => { + await onConfirm(selectedScreens) + }
confirm()} + onConfirm={confirmScreenSelection} + {onCancel} disabled={!selectedScreens.length} size="L" > - Please select the screens you would like to add to your application. - Autogenerated screens come with CRUD functionality. - + + Please select the screens you would like to add to your application. + Autogenerated screens come with CRUD functionality. + Blank screen
{ if (!event.detail.startsWith("/")) { - url = "/" + event.detail + screenUrl = "/" + event.detail } - url = sanitizeUrl(url) - - if (routeExists(url, roleId)) { + screenUrl = sanitizeUrl(screenUrl) + if (routeExists(screenUrl)) { routeError = "This URL is already taken for this access role" } else { - routeError = "" + routeError = null } } - const routeExists = (url, roleId) => { - return $allScreens.some( + const routeExists = url => { + const roleId = get(selectedAccessRole) || "BASIC" + return get(allScreens).some( screen => screen.routing.route.toLowerCase() === url.toLowerCase() && screen.routing.roleId === roleId ) } - onDestroy(() => { - screenName = "" - url = "" - }) + const confirmScreenDetails = async () => { + await onConfirm({ + screenName, + screenUrl, + }) + } chooseModal(0)} - onConfirm={() => save()} + onConfirm={confirmScreenDetails} + {onCancel} cancelText={"Back"} - disabled={!screenName || !url || routeError} + disabled={!screenName || !screenUrl || routeError} >
diff --git a/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte b/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte index 144592035c..fd37490c53 100644 --- a/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte @@ -3,141 +3,137 @@ import NewScreenModal from "components/design/NavigationPanel/NewScreenModal.svelte" import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl" import { Modal, notifications } from "@budibase/bbui" - import { store, selectedAccessRole, allScreens } from "builderStore" + import { store, selectedAccessRole } from "builderStore" import analytics, { Events } from "analytics" + import { get } from "svelte/store" - let newScreenModal - let navigationSelectionModal - let screenDetailsModal - let screenName = "" - let url = "" - let selectedScreens = [] + let pendingScreen let showProgressCircle = false - let routeError - let createdScreens = [] - $: roleId = $selectedAccessRole || "BASIC" + // Modal refs + let newScreenModal + let screenDetailsModal - const createScreens = async () => { - for (let screen of selectedScreens) { - let test = screen.create() - createdScreens.push(test) - analytics.captureEvent(Events.SCREEN.CREATED, { - template: screen.id || screen.name, - }) - } - } + // External handler to show the screen wizard + export const showModal = () => { + newScreenModal.show() - const save = async () => { - showProgressCircle = true - try { - await createScreens() - for (let screen of createdScreens) { - await saveScreens(screen) - } - await store.actions.routing.fetch() - selectedScreens = [] - createdScreens = [] - screenName = "" - url = "" - } catch (error) { - notifications.error("Error creating screens") - } + // Reset state when showing modal again + pendingScreen = null showProgressCircle = false } - const saveScreens = async draftScreen => { - let existingScreenCount = $store.screens.filter( - s => s.props._instanceName == draftScreen.props._instanceName - ).length - if (existingScreenCount > 0) { - let oldUrlArr = draftScreen.routing.route.split("/") - oldUrlArr[1] = `${oldUrlArr[1]}-${existingScreenCount + 1}` - draftScreen.routing.route = oldUrlArr.join("/") + // Creates an array of screens, checking and sanitising their URLs + const createScreens = async screens => { + if (!screens?.length) { + return } + showProgressCircle = true - let route = url ? sanitizeUrl(`${url}`) : draftScreen.routing.route - if (draftScreen) { - if (!route) { - routeError = "URL is required" - } else { - if (routeExists(route, roleId)) { - routeError = "This URL is already taken for this access role" - } else { - routeError = "" + try { + for (let screen of screens) { + // Check we aren't clashing with an existing URL + if (hasExistingUrl(screen.routing.route)) { + let suffix = 2 + let candidateUrl = makeCandidateUrl(screen, suffix) + while (hasExistingUrl(candidateUrl)) { + candidateUrl = makeCandidateUrl(screen, ++suffix) + } + screen.routing.route = candidateUrl } - } - if (routeError) return false + // Sanitise URL + screen.routing.route = sanitizeUrl(screen.routing.route) - if (screenName) { - draftScreen.props._instanceName = screenName - } + // Use the currently selected role + screen.routing.roleId = get(selectedAccessRole) || "BASIC" - draftScreen.routing.route = route - draftScreen.routing.roleId = roleId + // Create the screen + await store.actions.screens.save(screen) - await store.actions.screens.save(draftScreen) - if (draftScreen.props._instanceName.endsWith("List")) { - try { + // Analytics + if (screen.template) { + analytics.captureEvent(Events.SCREEN.CREATED, { + template: screen.template, + }) + } + + // Add link in layout for list screens + if (screen.props._instanceName.endsWith("List")) { await store.actions.components.links.save( - draftScreen.routing.route, - draftScreen.routing.route.split("/")[1] + screen.routing.route, + screen.routing.route.split("/")[1] ) - } catch (error) { - notifications.error("Error creating link to screen") } } + + // Refresh routing info since we have new screens + await store.actions.routing.fetch() + } catch (error) { + console.log(error) + notifications.error("Error creating screens") + } + + showProgressCircle = false + } + + // Checks if any screens exist in the store with the given route and + // currently selected role + const hasExistingUrl = url => { + const roleId = get(selectedAccessRole) || "BASIC" + const screens = get(store).screens.filter(s => s.routing.roleId === roleId) + return !!screens.find(s => s.routing?.route === url) + } + + // Constructs a candidate URL for a new screen, suffixing the base of the + // screen's URL with a given suffix. + // e.g. "/sales/:id" => "/sales-1/:id" + const makeCandidateUrl = (screen, suffix) => { + let url = screen.routing?.route || "" + if (url.startsWith("/")) { + url = url.slice(1) + } + if (!url.includes("/")) { + return `/${url}-${suffix}` + } else { + const split = url.split("/") + return `/${split[0]}-${suffix}/${split.join("/")}` } } - const routeExists = (route, roleId) => { - return $allScreens.some( - screen => - screen.routing.route.toLowerCase() === route.toLowerCase() && - screen.routing.roleId === roleId - ) - } - - export const showModal = () => { - newScreenModal.show() - } - - const setScreens = evt => { - selectedScreens = evt.detail.screens - } - - const chooseModal = index => { - /* - 0 = newScreenModal - 1 = screenDetailsModal - 2 = navigationSelectionModal - */ - if (index === 0) { - newScreenModal.show() - } else if (index === 1) { + // Handler for NewScreenModal + const confirmScreenSelection = async templates => { + // Handle template selection + if (templates?.length > 1) { + // Autoscreens, so create immediately + const screens = templates.map(template => template.create()) + await createScreens(screens) + } else { + // Empty screen, so proceed to the next modal + pendingScreen = templates[0].create() screenDetailsModal.show() - } else if (index === 2) { - navigationSelectionModal.show() } } + + // Handler for ScreenDetailsModal + const confirmScreenDetails = async ({ screenName, screenUrl }) => { + if (!pendingScreen) { + return + } + pendingScreen.props._instanceName = screenName + pendingScreen.routing.route = screenUrl + await createScreens([pendingScreen]) + } - + newScreenModal.show()} /> From f5ff71f9d1a41b53e5c78108073a22519bbc6c56 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 2 Mar 2022 19:26:43 +0000 Subject: [PATCH 004/171] Allow duplication of screens --- .../ScreenDropdownMenu.svelte | 57 +++++++++++++++++-- .../NavigationPanel/ScreenDetailsModal.svelte | 8 ++- .../NavigationPanel/ScreenWizard.svelte | 4 -- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 47c9fb65b1..33e4d89dda 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -2,15 +2,56 @@ import { goto } from "@roxi/routify" import { store, allScreens } from "builderStore" import ConfirmDialog from "components/common/ConfirmDialog.svelte" - import { ActionMenu, MenuItem, Icon, notifications } from "@budibase/bbui" + import { + ActionMenu, + MenuItem, + Icon, + Modal, + Helpers, + notifications, + } from "@budibase/bbui" + import ScreenDetailsModal from "../ScreenDetailsModal.svelte" + import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl" + import analytics, { Events } from "analytics" + import { makeComponentUnique } from "builderStore/componentUtils" export let screenId let confirmDeleteDialog + let screenDetailsModal $: screen = $allScreens.find(screen => screen._id === screenId) - const duplicateScreen = () => {} + const duplicateScreen = () => { + screenDetailsModal.show() + } + + const createDuplicateScreen = async ({ screenName, screenUrl }) => { + // Create a dupe and ensure it is unique + let duplicateScreen = Helpers.cloneDeep(screen) + delete duplicateScreen._id + delete duplicateScreen._rev + makeComponentUnique(duplicateScreen.props) + + // Attach the new name and URL + duplicateScreen.routing.route = sanitizeUrl(screenUrl) + duplicateScreen.props._instanceName = screenName + + try { + // Create the screen + await store.actions.screens.save(duplicateScreen) + + // Analytics + if (screen.template) { + analytics.captureEvent(Events.SCREEN.CREATED, { + template: "createFromScratch", + }) + } + } catch (error) { + notifications.error("Error duplicating screen") + console.log(error) + } + } const deleteScreen = async () => { try { @@ -27,9 +68,7 @@
- - Duplicate - + Duplicate Delete @@ -40,3 +79,11 @@ okText="Delete Screen" onOk={deleteScreen} /> + + + + diff --git a/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte b/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte index 0fae114268..82b90be6a6 100644 --- a/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte @@ -7,15 +7,17 @@ export let onConfirm export let onCancel export let showProgressCircle = false + export let screenName + export let screenUrl - let screenName - let screenUrl let routeError + let touched = false const routeChanged = event => { if (!event.detail.startsWith("/")) { screenUrl = "/" + event.detail } + touched = true screenUrl = sanitizeUrl(screenUrl) if (routeExists(screenUrl)) { routeError = "This URL is already taken for this access role" @@ -48,7 +50,7 @@ onConfirm={confirmScreenDetails} {onCancel} cancelText={"Back"} - disabled={!screenName || !screenUrl || routeError} + disabled={!screenName || !screenUrl || routeError || !touched} > Date: Wed, 2 Mar 2022 19:52:10 +0000 Subject: [PATCH 005/171] Allow bulk deleting all screens under a route --- .../ComponentDropdownMenu.svelte | 0 .../ComponentTree.svelte | 2 +- .../LayoutDropdownMenu.svelte | 2 +- .../PathDropdownMenu.svelte | 78 +++++++++++++++++++ .../ComponentNavigationTree/PathTree.svelte | 5 +- .../ScreenDropdownMenu.svelte | 2 +- 6 files changed, 85 insertions(+), 4 deletions(-) rename packages/builder/src/components/design/NavigationPanel/{ => ComponentNavigationTree}/ComponentDropdownMenu.svelte (100%) create mode 100644 packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathDropdownMenu.svelte diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte similarity index 100% rename from packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte rename to packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte index c5dfd63cf9..d0095b2c0d 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte @@ -1,7 +1,7 @@ + + +
+ +
+ + Delete all screens + +
+ + + +
+ Are you sure you want to delete all screens under the {path} route? +
+
The following screens will be deleted:
+
+ {#each screens as screen} +
{screen.route}
+ {/each} +
+
+
+ + diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte index 841d8970f4..ee6de5c797 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte @@ -8,6 +8,7 @@ import instantiateStore from "./dragDropStore" import ComponentTree from "./ComponentTree.svelte" import NavItem from "components/common/NavItem.svelte" + import PathDropdownMenu from "./PathDropdownMenu.svelte" import ScreenDropdownMenu from "./ScreenDropdownMenu.svelte" import { get } from "svelte/store" @@ -73,7 +74,9 @@ opened={routeOpened} {border} withArrow={route.subpaths} - /> + > + + {#if routeOpened} {#each filteredScreens as screen (screen.id)} diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 33e4d89dda..7d0b88c235 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -76,7 +76,7 @@ bind:this={confirmDeleteDialog} title="Confirm Deletion" body={"Are you sure you wish to delete this screen?"} - okText="Delete Screen" + okText="Delete screen" onOk={deleteScreen} /> From 97509b561b83cd5a76ca120ce0f163dec93f913e Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Thu, 3 Mar 2022 00:18:15 +0100 Subject: [PATCH 006/171] initial implementation of openapi 3 --- .../src/api/controllers/query/import/index.ts | 5 +- .../query/import/sources/openapi3.ts | 194 +++ .../tests/openapi3/data/crud/crud.json | 231 ++++ .../tests/openapi3/data/crud/crud.yaml | 156 +++ .../openapi3/data/petstore/petstore.json | 1225 +++++++++++++++++ .../openapi3/data/petstore/petstore.yaml | 804 +++++++++++ .../sources/tests/openapi3/openapi3.spec.js | 256 ++++ 7 files changed, 2869 insertions(+), 2 deletions(-) create mode 100644 packages/server/src/api/controllers/query/import/sources/openapi3.ts create mode 100644 packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json create mode 100644 packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.yaml create mode 100644 packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.json create mode 100644 packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.yaml create mode 100644 packages/server/src/api/controllers/query/import/sources/tests/openapi3/openapi3.spec.js diff --git a/packages/server/src/api/controllers/query/import/index.ts b/packages/server/src/api/controllers/query/import/index.ts index 593fb05fd3..4573fd27f7 100644 --- a/packages/server/src/api/controllers/query/import/index.ts +++ b/packages/server/src/api/controllers/query/import/index.ts @@ -1,7 +1,8 @@ import { queryValidation } from "../validation" import { generateQueryID } from "../../../../db/utils" import { ImportInfo, ImportSource } from "./sources/base" -import { OpenAPI2 } from "./sources/openapi2" +import { OpenAPI3 } from "./sources/openapi2" +import { OpenAPI3 } from "./sources/openapi3" import { Query } from "./../../../../definitions/common" import { Curl } from "./sources/curl" // @ts-ignore @@ -18,7 +19,7 @@ export class RestImporter { constructor(data: string) { this.data = data - this.sources = [new OpenAPI2(), new Curl()] + this.sources = [new OpenAPI3(), new OpenAPI3(), new Curl()] } init = async () => { diff --git a/packages/server/src/api/controllers/query/import/sources/openapi3.ts b/packages/server/src/api/controllers/query/import/sources/openapi3.ts new file mode 100644 index 0000000000..8c40c49c9d --- /dev/null +++ b/packages/server/src/api/controllers/query/import/sources/openapi3.ts @@ -0,0 +1,194 @@ +import { ImportInfo } from "./base" +import { Query, QueryParameter } from "../../../../../definitions/datasource" +import { OpenAPIV3 } from "openapi-types" +import { OpenAPISource } from "./base/openapi" +import { URL } from "url" +import { + getGlobalDB, + getTenantId, + isMultiTenant, +} from "@budibase/backend-core/tenancy" +import { getScopedConfig } from "@budibase/backend-core/db" + +const jsonMimeType = "application/json" +const parameterNotRef = ( + param: OpenAPIV3.ParameterObject | OpenAPIV3.ReferenceObject +): param is OpenAPIV3.ParameterObject => { + // all refs are deferenced by parser library + return true +} + +const requestBodyNotRef = ( + param: OpenAPIV3.RequestBodyObject | OpenAPIV3.ReferenceObject | undefined +): param is OpenAPIV3.RequestBodyObject => { + // all refs are deferenced by parser library + return param !== undefined +} + +const isOpenAPI3 = (document: any): document is OpenAPIV3.Document => { + return document.openapi.includes("3") +} + +const methods: string[] = Object.values(OpenAPIV3.HttpMethods) + +const isOperation = ( + key: string, + pathItem: any +): pathItem is OpenAPIV3.OperationObject => { + return methods.includes(key) +} + +const isParameter = ( + key: string, + pathItem: any +): pathItem is OpenAPIV3.ParameterObject => { + return !isOperation(key, pathItem) +} + +const getRequestBody = (operation: OpenAPIV3.OperationObject) => { + if (requestBodyNotRef(operation.requestBody)) { + const request: OpenAPIV3.RequestBodyObject = + operation.requestBody as OpenAPIV3.RequestBodyObject + return request.content[jsonMimeType]?.example + } + return null +} + +/** + * OpenAPI Version 3.1 - aka "Swagger" + * https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md + */ +export class OpenAPI3 extends OpenAPISource { + document!: OpenAPIV3.Document + + isSupported = async (data: string): Promise => { + try { + const document: any = await this.parseData(data) + if (isOpenAPI3(document)) { + this.document = document + return true + } else { + return false + } + } catch (err) { + return false + } + } + + getPlatformUrl = async (): Promise => { + const db = getGlobalDB() + const publicConfig = await getScopedConfig(db, { + type: "settings", + }) + + let url = publicConfig.platformUrl + if (isMultiTenant()) { + url += `/${getTenantId()}` + } + return url + } + + getUrl = async (): Promise => { + const platformUrl = await this.getPlatformUrl() + let url = this.document.servers ? this.document.servers[0].url : null + if (url) { + // check if url is relative or absolute + if (url.includes("http") || url.includes("https")) { + return new URL(url) + } + + return new URL(`${platformUrl}${url}`) + } + // if the specification doesn't contain a servers object, return the PLATFORM_URM environment variable + return new URL(platformUrl) + } + + getInfo = async (): Promise => { + const name = this.document.info.title || "Swagger Import" + return { + name, + } + } + + getQueries = async (datasourceId: string): Promise => { + const url: URL = await this.getUrl() + const queries: Query[] = [] + + for (let [path, pathItemObject] of Object.entries(this.document.paths)) { + // parameters that apply to every operation in the path + let pathParams: OpenAPIV3.ParameterObject[] = [] + + // pathItemObject can be undefined + if (!pathItemObject) { + continue + } + + for (let [key, opOrParams] of Object.entries(pathItemObject)) { + if (isParameter(key, opOrParams)) { + const pathParameters = opOrParams as OpenAPIV3.ParameterObject[] + pathParams.push(...pathParameters) + continue + } + // can not be a parameter, must be an operation + const operation = opOrParams as OpenAPIV3.OperationObject + + const methodName = key + const name = operation.operationId || path + let queryString = "" + const headers: any = {} + let requestBody = getRequestBody(operation) + const parameters: QueryParameter[] = [] + + // combine the path parameters with the operation parameters + const operationParams = operation.parameters || [] + const allParams = [...pathParams, ...operationParams] + + for (let param of allParams) { + if (parameterNotRef(param)) { + switch (param.in) { + case "query": + let prefix = "" + if (queryString) { + prefix = "&" + } + queryString = `${queryString}${prefix}${param.name}={{${param.name}}}` + break + case "header": + headers[param.name] = `{{${param.name}}}` + break + case "path": + // do nothing: param is already in the path + break + case "formData": + // future enhancement + break + } + + // add the parameter if it can be bound in our config + if (["query", "header", "path"].includes(param.in)) { + parameters.push({ + name: param.name, + default: "", + }) + } + } + } + + const query = this.constructQuery( + datasourceId, + name, + methodName, + path, + url, + queryString, + headers, + parameters, + requestBody + ) + queries.push(query) + } + } + + return queries + } +} diff --git a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json new file mode 100644 index 0000000000..c1cf4c2b18 --- /dev/null +++ b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json @@ -0,0 +1,231 @@ +{ + "openapi": "3.0.2", + "info": { + "description": "A basic swagger file", + "version": "1.0.0", + "title": "CRUD" + }, + "tags": [ + { + "name": "entity" + } + ], + "paths": { + "/entities": { + "post": { + "tags": [ + "entity" + ], + "operationId": "createEntity", + "parameters": [ + { + "$ref": "#/components/schemas/CreateEntityParameter" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/components/schemas/Entity" + } + } + } + }, + "get": { + "tags": [ + "entity" + ], + "operationId": "getEntities", + "produces": [ + "application/json" + ], + "parameters": [ + { + "$ref": "#/components/schemas/PageParameter" + }, + { + "$ref": "#/components/schemas/SizeParameter" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/components/schemas/Entities" + } + } + } + } + }, + "/entities/{entityId}": { + "parameters": [ + { + "$ref": "#/components/schemas/EntityIdParameter" + } + ], + "get": { + "tags": [ + "entity" + ], + "operationId": "getEntity", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/components/schemas/Entity" + } + } + } + }, + "put": { + "tags": [ + "entity" + ], + "operationId": "updateEntity", + "parameters": [ + { + "$ref": "#/components/schemas/EntityParameter" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/components/schemas/Entity" + } + } + } + }, + "patch": { + "tags": [ + "entity" + ], + "operationId": "patchEntity", + "parameters": [ + { + "$ref": "#/components/schemas/EntityParameter" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/components/schemas/Entity" + } + } + } + }, + "delete": { + "tags": [ + "entity" + ], + "parameters": [ + { + "type": "string", + "name": "x-api-key", + "in": "header", + "required": false + } + ], + "operationId": "deleteEntity", + "responses": { + "204": { + "description": "successful operation" + } + } + } + } + }, + "components": { + "schemas": { + "EntityIdParameter": { + "type": "integer", + "format": "int64", + "name": "entityId", + "in": "path", + "required": true + }, + "CreateEntityParameter": { + "name": "entity", + "in": "body", + "required": true, + "schema": { + "$ref": "#/components/schemas/CreateEntity" + } + }, + "EntityParameter": { + "name": "entity", + "in": "body", + "required": true, + "schema": { + "$ref": "#/components/schemas/Entity" + } + }, + "PageParameter": { + "type": "integer", + "format": "int32", + "name": "page", + "in": "query", + "required": false + }, + "SizeParameter": { + "type": "integer", + "format": "int32", + "name": "size", + "in": "query", + "required": false + }, + "APIKeyParameter": { + "type": "string", + "name": "x-api-key", + "in": "header", + "required": false + }, + "CreateEntity": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "example": { + "name": "name", + "type": "type" + } + }, + "Entity": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + } + } + }, + { + "$ref": "#/components/schemas/CreateEntity" + } + ], + "example": { + "id": 1, + "name": "name", + "type": "type" + } + }, + "Entities" : { + "type": "array", + "items": { + "$ref": "#/components/schemas/Entity" + } + } + } + } +} diff --git a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.yaml b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.yaml new file mode 100644 index 0000000000..f87b3e347c --- /dev/null +++ b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.yaml @@ -0,0 +1,156 @@ +--- +openapi: "3.0.2" +info: + description: A basic swagger file + version: 1.0.0 + title: CRUD +host: example.com +tags: + - name: entity +paths: + "/entities": + post: + tags: + - entity + operationId: createEntity + produces: + - application/json + parameters: + - "$ref": "#/parameters/CreateEntity" + responses: + "200": + description: successful operation + schema: + "$ref": "#/definitions/Entity" + get: + tags: + - entity + operationId: getEntities + produces: + - application/json + parameters: + - "$ref": "#/parameters/Page" + - "$ref": "#/parameters/Size" + responses: + "200": + description: successful operation + schema: + "$ref": "#/definitions/Entities" + "/entities/{entityId}": + parameters: + - "$ref": "#/parameters/EntityId" + get: + tags: + - entity + operationId: getEntity + produces: + - application/json + responses: + "200": + description: successful operation + schema: + "$ref": "#/definitions/Entity" + put: + tags: + - entity + operationId: updateEntity + consumes: + - application/json + produces: + - application/json + parameters: + - "$ref": "#/parameters/Entity" + responses: + "200": + description: successful operation + schema: + "$ref": "#/definitions/Entity" + patch: + tags: + - entity + operationId: patchEntity + consumes: + - application/json + produces: + - application/json + parameters: + - "$ref": "#/parameters/Entity" + responses: + "200": + description: successful operation + schema: + "$ref": "#/definitions/Entity" + delete: + tags: + - entity + parameters: + - "$ref": "#/parameters/APIKey" + operationId: deleteEntity + produces: + - application/json + responses: + "204": + description: successful operation +parameters: + EntityId: + type: integer + format: int64 + name: entityId + in: path + required: true + CreateEntity: + name: entity + in: body + required: true + schema: + "$ref": "#/definitions/CreateEntity" + Entity: + name: entity + in: body + required: true + schema: + "$ref": "#/definitions/Entity" + Page: + type: integer + format: int32 + name: page + in: query + required: false + Size: + type: integer + format: int32 + name: size + in: query + required: false + APIKey: + type: string + name: x-api-key + in: header + required: false +definitions: + CreateEntity: + type: object + properties: + name: + type: string + type: + type: string + example: + name: name + type: type + Entity: + allOf: + - type: object + properties: + id: + type: integer + format: int64 + - "$ref": "#/definitions/CreateEntity" + example: + id: 1 + name: name + type: type + Entities: + type: array + items: + "$ref": "#/definitions/Entity" diff --git a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.json b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.json new file mode 100644 index 0000000000..14115066d6 --- /dev/null +++ b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.json @@ -0,0 +1,1225 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "Swagger Petstore - OpenAPI 3.0", + "description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.11" + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + }, + "servers": [ + { + "url": "/api/v3" + } + ], + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Access to Petstore orders", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + }, + { + "name": "user", + "description": "Operations about user" + } + ], + "paths": { + "/pet": { + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "Update an existing pet by Id", + "operationId": "updatePet", + "requestBody": { + "description": "Update an existent pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "Add a new pet to the store", + "operationId": "addPet", + "requestBody": { + "description": "Create a new pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": false, + "explode": true, + "schema": { + "type": "string", + "default": "available", + "enum": [ + "available", + "pending", + "sold" + ] + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": false, + "explode": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetById", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to return", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + }, + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "name", + "in": "query", + "description": "Name of pet that needs to be updated", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "description": "Status of pet that needs to be updated", + "schema": { + "type": "string" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "parameters": [ + { + "name": "api_key", + "in": "header", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid pet value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to update", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "additionalMetadata", + "in": "query", + "description": "Additional Metadata", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/store/inventory": { + "get": { + "tags": [ + "store" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/store/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "Place a new order in the store", + "operationId": "placeOrder", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "405": { + "description": "Invalid input" + } + } + } + }, + "/store/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.", + "operationId": "getOrderById", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of order that needs to be fetched", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "operationId": "deleteOrder", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "requestBody": { + "description": "Created user object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + }, + "/user/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "Creates list of users with given input array", + "operationId": "createUsersWithListInput", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "default": { + "description": "successful operation" + } + } + } + }, + "/user/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "description": "", + "operationId": "loginUser", + "parameters": [ + { + "name": "username", + "in": "query", + "description": "The user name for login", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "password", + "in": "query", + "description": "The password for login in clear text", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "headers": { + "X-Rate-Limit": { + "description": "calls per hour allowed by the user", + "schema": { + "type": "integer", + "format": "int32" + } + }, + "X-Expires-After": { + "description": "date in UTC when token expires", + "schema": { + "type": "string", + "format": "date-time" + } + } + }, + "content": { + "application/xml": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "Invalid username/password supplied" + } + } + } + }, + "/user/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "description": "", + "operationId": "logoutUser", + "parameters": [], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "description": "", + "operationId": "getUserByName", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be fetched. Use user1 for testing. ", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "put": { + "tags": [ + "user" + ], + "summary": "Update user", + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "name that need to be deleted", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "Update an existent user in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation" + } + } + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be deleted", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + } + } + }, + "components": { + "schemas": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "petId": { + "type": "integer", + "format": "int64", + "example": 198772 + }, + "quantity": { + "type": "integer", + "format": "int32", + "example": 7 + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "example": "approved", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean" + } + }, + "xml": { + "name": "order" + } + }, + "Customer": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 100000 + }, + "username": { + "type": "string", + "example": "fehguy" + }, + "address": { + "type": "array", + "xml": { + "name": "addresses", + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Address" + } + } + }, + "xml": { + "name": "customer" + } + }, + "Address": { + "type": "object", + "properties": { + "street": { + "type": "string", + "example": "437 Lytton" + }, + "city": { + "type": "string", + "example": "Palo Alto" + }, + "state": { + "type": "string", + "example": "CA" + }, + "zip": { + "type": "string", + "example": "94301" + } + }, + "xml": { + "name": "address" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "Dogs" + } + }, + "xml": { + "name": "category" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "username": { + "type": "string", + "example": "theUser" + }, + "firstName": { + "type": "string", + "example": "John" + }, + "lastName": { + "type": "string", + "example": "James" + }, + "email": { + "type": "string", + "example": "john@email.com" + }, + "password": { + "type": "string", + "example": "12345" + }, + "phone": { + "type": "string", + "example": "12345" + }, + "userStatus": { + "type": "integer", + "description": "User Status", + "format": "int32", + "example": 1 + } + }, + "xml": { + "name": "user" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "tag" + } + }, + "Pet": { + "required": [ + "name", + "photoUrls" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "doggie" + }, + "category": { + "$ref": "#/components/schemas/Category" + }, + "photoUrls": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "string", + "xml": { + "name": "photoUrl" + } + } + }, + "tags": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "pet" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "xml": { + "name": "##default" + } + } + }, + "requestBodies": { + "Pet": { + "description": "Pet object that needs to be added to the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "UserArray": { + "description": "List of user object", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + }, + "securitySchemes": { + "petstore_auth": { + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://petstore3.swagger.io/oauth/authorize", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + } + } +} diff --git a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.yaml b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.yaml new file mode 100644 index 0000000000..0f39b90c16 --- /dev/null +++ b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.yaml @@ -0,0 +1,804 @@ +--- +openapi: 3.0.2 +info: + title: Swagger Petstore - OpenAPI 3.0 + description: |- + This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about + Swagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach! + You can now help us improve the API whether it's by making changes to the definition itself or to the code. + That way, with time, we can improve the API in general, and expose some of the new features in OAS3. + + Some useful links: + - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore) + - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml) + termsOfService: http://swagger.io/terms/ + contact: + email: apiteam@swagger.io + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.11 +externalDocs: + description: Find out more about Swagger + url: http://swagger.io +servers: + - url: "/api/v3" +tags: + - name: pet + description: Everything about your Pets + externalDocs: + description: Find out more + url: http://swagger.io + - name: store + description: Access to Petstore orders + externalDocs: + description: Find out more about our store + url: http://swagger.io + - name: user + description: Operations about user +paths: + "/pet": + put: + tags: + - pet + summary: Update an existing pet + description: Update an existing pet by Id + operationId: updatePet + requestBody: + description: Update an existent pet in the store + content: + application/json: + schema: + "$ref": "#/components/schemas/Pet" + application/xml: + schema: + "$ref": "#/components/schemas/Pet" + application/x-www-form-urlencoded: + schema: + "$ref": "#/components/schemas/Pet" + required: true + responses: + '200': + description: Successful operation + content: + application/xml: + schema: + "$ref": "#/components/schemas/Pet" + application/json: + schema: + "$ref": "#/components/schemas/Pet" + '400': + description: Invalid ID supplied + '404': + description: Pet not found + '405': + description: Validation exception + security: + - petstore_auth: + - write:pets + - read:pets + post: + tags: + - pet + summary: Add a new pet to the store + description: Add a new pet to the store + operationId: addPet + requestBody: + description: Create a new pet in the store + content: + application/json: + schema: + "$ref": "#/components/schemas/Pet" + application/xml: + schema: + "$ref": "#/components/schemas/Pet" + application/x-www-form-urlencoded: + schema: + "$ref": "#/components/schemas/Pet" + required: true + responses: + '200': + description: Successful operation + content: + application/xml: + schema: + "$ref": "#/components/schemas/Pet" + application/json: + schema: + "$ref": "#/components/schemas/Pet" + '405': + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + "/pet/findByStatus": + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: false + explode: true + schema: + type: string + default: available + enum: + - available + - pending + - sold + responses: + '200': + description: successful operation + content: + application/xml: + schema: + type: array + items: + "$ref": "#/components/schemas/Pet" + application/json: + schema: + type: array + items: + "$ref": "#/components/schemas/Pet" + '400': + description: Invalid status value + security: + - petstore_auth: + - write:pets + - read:pets + "/pet/findByTags": + get: + tags: + - pet + summary: Finds Pets by tags + description: Multiple tags can be provided with comma separated strings. Use + tag1, tag2, tag3 for testing. + operationId: findPetsByTags + parameters: + - name: tags + in: query + description: Tags to filter by + required: false + explode: true + schema: + type: array + items: + type: string + responses: + '200': + description: successful operation + content: + application/xml: + schema: + type: array + items: + "$ref": "#/components/schemas/Pet" + application/json: + schema: + type: array + items: + "$ref": "#/components/schemas/Pet" + '400': + description: Invalid tag value + security: + - petstore_auth: + - write:pets + - read:pets + "/pet/{petId}": + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/xml: + schema: + "$ref": "#/components/schemas/Pet" + application/json: + schema: + "$ref": "#/components/schemas/Pet" + '400': + description: Invalid ID supplied + '404': + description: Pet not found + security: + - api_key: [] + - petstore_auth: + - write:pets + - read:pets + post: + tags: + - pet + summary: Updates a pet in the store with form data + description: '' + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: integer + format: int64 + - name: name + in: query + description: Name of pet that needs to be updated + schema: + type: string + - name: status + in: query + description: Status of pet that needs to be updated + schema: + type: string + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + delete: + tags: + - pet + summary: Deletes a pet + description: '' + operationId: deletePet + parameters: + - name: api_key + in: header + description: '' + required: false + schema: + type: string + - name: petId + in: path + description: Pet id to delete + required: true + schema: + type: integer + format: int64 + responses: + '400': + description: Invalid pet value + security: + - petstore_auth: + - write:pets + - read:pets + "/pet/{petId}/uploadImage": + post: + tags: + - pet + summary: uploads an image + description: '' + operationId: uploadFile + parameters: + - name: petId + in: path + description: ID of pet to update + required: true + schema: + type: integer + format: int64 + - name: additionalMetadata + in: query + description: Additional Metadata + required: false + schema: + type: string + requestBody: + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + '200': + description: successful operation + content: + application/json: + schema: + "$ref": "#/components/schemas/ApiResponse" + security: + - petstore_auth: + - write:pets + - read:pets + "/store/inventory": + get: + tags: + - store + summary: Returns pet inventories by status + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + additionalProperties: + type: integer + format: int32 + security: + - api_key: [] + "/store/order": + post: + tags: + - store + summary: Place an order for a pet + description: Place a new order in the store + operationId: placeOrder + requestBody: + content: + application/json: + schema: + "$ref": "#/components/schemas/Order" + application/xml: + schema: + "$ref": "#/components/schemas/Order" + application/x-www-form-urlencoded: + schema: + "$ref": "#/components/schemas/Order" + responses: + '200': + description: successful operation + content: + application/json: + schema: + "$ref": "#/components/schemas/Order" + '405': + description: Invalid input + "/store/order/{orderId}": + get: + tags: + - store + summary: Find purchase order by ID + description: For valid response try integer IDs with value <= 5 or > 10. Other + values will generate exceptions. + operationId: getOrderById + parameters: + - name: orderId + in: path + description: ID of order that needs to be fetched + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/xml: + schema: + "$ref": "#/components/schemas/Order" + application/json: + schema: + "$ref": "#/components/schemas/Order" + '400': + description: Invalid ID supplied + '404': + description: Order not found + delete: + tags: + - store + summary: Delete purchase order by ID + description: For valid response try integer IDs with value < 1000. Anything + above 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - name: orderId + in: path + description: ID of the order that needs to be deleted + required: true + schema: + type: integer + format: int64 + responses: + '400': + description: Invalid ID supplied + '404': + description: Order not found + "/user": + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + requestBody: + description: Created user object + content: + application/json: + schema: + "$ref": "#/components/schemas/User" + application/xml: + schema: + "$ref": "#/components/schemas/User" + application/x-www-form-urlencoded: + schema: + "$ref": "#/components/schemas/User" + responses: + default: + description: successful operation + content: + application/json: + schema: + "$ref": "#/components/schemas/User" + application/xml: + schema: + "$ref": "#/components/schemas/User" + "/user/createWithList": + post: + tags: + - user + summary: Creates list of users with given input array + description: Creates list of users with given input array + operationId: createUsersWithListInput + requestBody: + content: + application/json: + schema: + type: array + items: + "$ref": "#/components/schemas/User" + responses: + '200': + description: Successful operation + content: + application/xml: + schema: + "$ref": "#/components/schemas/User" + application/json: + schema: + "$ref": "#/components/schemas/User" + default: + description: successful operation + "/user/login": + get: + tags: + - user + summary: Logs user into the system + description: '' + operationId: loginUser + parameters: + - name: username + in: query + description: The user name for login + required: false + schema: + type: string + - name: password + in: query + description: The password for login in clear text + required: false + schema: + type: string + responses: + '200': + description: successful operation + headers: + X-Rate-Limit: + description: calls per hour allowed by the user + schema: + type: integer + format: int32 + X-Expires-After: + description: date in UTC when token expires + schema: + type: string + format: date-time + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + '400': + description: Invalid username/password supplied + "/user/logout": + get: + tags: + - user + summary: Logs out current logged in user session + description: '' + operationId: logoutUser + parameters: [] + responses: + default: + description: successful operation + "/user/{username}": + get: + tags: + - user + summary: Get user by user name + description: '' + operationId: getUserByName + parameters: + - name: username + in: path + description: 'The name that needs to be fetched. Use user1 for testing. ' + required: true + schema: + type: string + responses: + '200': + description: successful operation + content: + application/xml: + schema: + "$ref": "#/components/schemas/User" + application/json: + schema: + "$ref": "#/components/schemas/User" + '400': + description: Invalid username supplied + '404': + description: User not found + put: + tags: + - user + summary: Update user + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - name: username + in: path + description: name that need to be deleted + required: true + schema: + type: string + requestBody: + description: Update an existent user in the store + content: + application/json: + schema: + "$ref": "#/components/schemas/User" + application/xml: + schema: + "$ref": "#/components/schemas/User" + application/x-www-form-urlencoded: + schema: + "$ref": "#/components/schemas/User" + responses: + default: + description: successful operation + delete: + tags: + - user + summary: Delete user + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - name: username + in: path + description: The name that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid username supplied + '404': + description: User not found +components: + schemas: + Order: + type: object + properties: + id: + type: integer + format: int64 + example: 10 + petId: + type: integer + format: int64 + example: 198772 + quantity: + type: integer + format: int32 + example: 7 + shipDate: + type: string + format: date-time + status: + type: string + description: Order Status + example: approved + enum: + - placed + - approved + - delivered + complete: + type: boolean + xml: + name: order + Customer: + type: object + properties: + id: + type: integer + format: int64 + example: 100000 + username: + type: string + example: fehguy + address: + type: array + xml: + name: addresses + wrapped: true + items: + "$ref": "#/components/schemas/Address" + xml: + name: customer + Address: + type: object + properties: + street: + type: string + example: 437 Lytton + city: + type: string + example: Palo Alto + state: + type: string + example: CA + zip: + type: string + example: '94301' + xml: + name: address + Category: + type: object + properties: + id: + type: integer + format: int64 + example: 1 + name: + type: string + example: Dogs + xml: + name: category + User: + type: object + properties: + id: + type: integer + format: int64 + example: 10 + username: + type: string + example: theUser + firstName: + type: string + example: John + lastName: + type: string + example: James + email: + type: string + example: john@email.com + password: + type: string + example: '12345' + phone: + type: string + example: '12345' + userStatus: + type: integer + description: User Status + format: int32 + example: 1 + xml: + name: user + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: tag + Pet: + required: + - name + - photoUrls + type: object + properties: + id: + type: integer + format: int64 + example: 10 + name: + type: string + example: doggie + category: + "$ref": "#/components/schemas/Category" + photoUrls: + type: array + xml: + wrapped: true + items: + type: string + xml: + name: photoUrl + tags: + type: array + xml: + wrapped: true + items: + "$ref": "#/components/schemas/Tag" + status: + type: string + description: pet status in the store + enum: + - available + - pending + - sold + xml: + name: pet + ApiResponse: + type: object + properties: + code: + type: integer + format: int32 + type: + type: string + message: + type: string + xml: + name: "##default" + requestBodies: + Pet: + description: Pet object that needs to be added to the store + content: + application/json: + schema: + "$ref": "#/components/schemas/Pet" + application/xml: + schema: + "$ref": "#/components/schemas/Pet" + UserArray: + description: List of user object + content: + application/json: + schema: + type: array + items: + "$ref": "#/components/schemas/User" + securitySchemes: + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: https://petstore3.swagger.io/oauth/authorize + scopes: + write:pets: modify pets in your account + read:pets: read your pets + api_key: + type: apiKey + name: api_key + in: header diff --git a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/openapi3.spec.js b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/openapi3.spec.js new file mode 100644 index 0000000000..6278e0fece --- /dev/null +++ b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/openapi3.spec.js @@ -0,0 +1,256 @@ +const fs = require("fs") +const path = require("path") +const getGlobalDB = jest.fn().mockReturnValue("db") +const getTenantId = jest.fn().mockReturnValue("1") +const isMultiTenant = jest.fn().mockReturnValue(true) +const getScopedConfig = jest + .fn() + .mockResolvedValue({ platformUrl: "somePlatform" }) + +jest.mock("@budibase/backend-core/db", () => ({ + getScopedConfig, +})) + +jest.mock("@budibase/backend-core/tenancy", () => ({ + getTenantId, + getGlobalDB, + isMultiTenant, +})) +const { OpenAPI3 } = require("../../openapi3") + +const getData = (file, extension) => { + return fs.readFileSync( + path.join(__dirname, `./data/${file}/${file}.${extension}`), + "utf8" + ) +} + +describe("OpenAPI3 Import", () => { + let openapi3 + + beforeEach(() => { + openapi3 = new OpenAPI3() + }) + + it("validates unsupported data", async () => { + let data + let supported + + // non json / yaml + data = "curl http://example.com" + supported = await openapi3.isSupported(data) + expect(supported).toBe(false) + + // Empty + data = "" + supported = await openapi3.isSupported(data) + expect(supported).toBe(false) + }) + + const runTests = async (filename, test, assertions) => { + /*for (let extension of ["json", "yaml"]) { + await test(filename, extension, assertions) + }*/ + await test(filename, "json", assertions) + } + + const testImportInfo = async (file, extension) => { + await openapi3.isSupported(getData(file, extension)) + const info = await openapi3.getInfo() + expect(info.name).toBe("Swagger Petstore - OpenAPI 3.0") + } + + it("returns import info", async () => { + await runTests("petstore", testImportInfo) + }) + + describe("Returns queries", () => { + const indexQueries = queries => { + return queries.reduce((acc, query) => { + acc[query.name] = query + return acc + }, {}) + } + + const getQueries = async (file, extension) => { + await openapi3.isSupported(getData(file, extension)) + const queries = await openapi3.getQueries() + expect(queries.length).toBe(6) + return indexQueries(queries) + } + + const testVerb = async (file, extension, assertions) => { + const queries = await getQueries(file, extension) + for (let [operationId, method] of Object.entries(assertions)) { + expect(queries[operationId].queryVerb).toBe(method) + } + } + + it("populates verb", async () => { + const assertions = { + createEntity: "create", + getEntities: "read", + getEntity: "read", + updateEntity: "update", + patchEntity: "patch", + deleteEntity: "delete", + } + await runTests("crud", testVerb, assertions) + }) + + const testPath = async (file, extension, assertions) => { + const queries = await getQueries(file, extension) + for (let [operationId, urlPath] of Object.entries(assertions)) { + expect(queries[operationId].fields.path).toBe(urlPath) + } + } + + it("populates path", async () => { + const assertions = { + createEntity: "http://example.com/entities", + getEntities: "http://example.com/entities", + getEntity: "http://example.com/entities/{{entityId}}", + updateEntity: "http://example.com/entities/{{entityId}}", + patchEntity: "http://example.com/entities/{{entityId}}", + deleteEntity: "http://example.com/entities/{{entityId}}", + } + await runTests("crud", testPath, assertions) + }) + + const testHeaders = async (file, extension, assertions) => { + const queries = await getQueries(file, extension) + for (let [operationId, headers] of Object.entries(assertions)) { + expect(queries[operationId].fields.headers).toStrictEqual(headers) + } + } + + const contentTypeHeader = { + "Content-Type": "application/json", + } + + it("populates headers", async () => { + const assertions = { + createEntity: { + ...contentTypeHeader, + }, + getEntities: {}, + getEntity: {}, + updateEntity: { + ...contentTypeHeader, + }, + patchEntity: { + ...contentTypeHeader, + }, + deleteEntity: { + "x-api-key": "{{x-api-key}}", + }, + } + + await runTests("crud", testHeaders, assertions) + }) + + const testQuery = async (file, extension, assertions) => { + const queries = await getQueries(file, extension) + for (let [operationId, queryString] of Object.entries(assertions)) { + expect(queries[operationId].fields.queryString).toStrictEqual( + queryString + ) + } + } + + it("populates query", async () => { + const assertions = { + createEntity: "", + getEntities: "page={{page}}&size={{size}}", + getEntity: "", + updateEntity: "", + patchEntity: "", + deleteEntity: "", + } + await runTests("crud", testQuery, assertions) + }) + + const testParameters = async (file, extension, assertions) => { + const queries = await getQueries(file, extension) + for (let [operationId, parameters] of Object.entries(assertions)) { + expect(queries[operationId].parameters).toStrictEqual(parameters) + } + } + + it("populates parameters", async () => { + const assertions = { + createEntity: [], + getEntities: [ + { + name: "page", + default: "", + }, + { + name: "size", + default: "", + }, + ], + getEntity: [ + { + name: "entityId", + default: "", + }, + ], + updateEntity: [ + { + name: "entityId", + default: "", + }, + ], + patchEntity: [ + { + name: "entityId", + default: "", + }, + ], + deleteEntity: [ + { + name: "entityId", + default: "", + }, + { + name: "x-api-key", + default: "", + }, + ], + } + await runTests("crud", testParameters, assertions) + }) + + const testBody = async (file, extension, assertions) => { + const queries = await getQueries(file, extension) + for (let [operationId, body] of Object.entries(assertions)) { + expect(queries[operationId].fields.requestBody).toStrictEqual( + JSON.stringify(body, null, 2) + ) + } + } + it("populates body", async () => { + const assertions = { + createEntity: { + name: "name", + type: "type", + }, + getEntities: undefined, + getEntity: undefined, + updateEntity: { + id: 1, + name: "name", + type: "type", + }, + patchEntity: { + id: 1, + name: "name", + type: "type", + }, + deleteEntity: undefined, + } + await runTests("crud", testBody, assertions) + }) + }) +}) From 5bc9051efac6d07c16355b41a3d8cf62e0fe88e8 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Thu, 3 Mar 2022 15:19:36 +0100 Subject: [PATCH 007/171] fix openapi 3 test doc and tests --- .../query/import/sources/base/index.ts | 6 +- .../query/import/sources/openapi3.ts | 71 +++--- .../tests/openapi3/data/crud/crud.json | 144 +++++++----- .../tests/openapi3/data/crud/crud.yaml | 209 +++++++++--------- .../sources/tests/openapi3/openapi3.spec.js | 20 +- 5 files changed, 225 insertions(+), 225 deletions(-) diff --git a/packages/server/src/api/controllers/query/import/sources/base/index.ts b/packages/server/src/api/controllers/query/import/sources/base/index.ts index e666fdc193..096fa10e92 100644 --- a/packages/server/src/api/controllers/query/import/sources/base/index.ts +++ b/packages/server/src/api/controllers/query/import/sources/base/index.ts @@ -23,7 +23,7 @@ export abstract class ImportSource { name: string, method: string, path: string, - url: URL, + url: URL | null, queryString: string, headers: object = {}, parameters: QueryParameter[] = [], @@ -34,7 +34,9 @@ export abstract class ImportSource { const transformer = "return data" const schema = {} path = this.processPath(path) - path = `${url.origin}/${path}` + if (url) { + path = `${url.origin}/${path}` + } queryString = this.processQuery(queryString) const requestBody = JSON.stringify(body, null, 2) diff --git a/packages/server/src/api/controllers/query/import/sources/openapi3.ts b/packages/server/src/api/controllers/query/import/sources/openapi3.ts index 8c40c49c9d..c9e49595b2 100644 --- a/packages/server/src/api/controllers/query/import/sources/openapi3.ts +++ b/packages/server/src/api/controllers/query/import/sources/openapi3.ts @@ -3,14 +3,7 @@ import { Query, QueryParameter } from "../../../../../definitions/datasource" import { OpenAPIV3 } from "openapi-types" import { OpenAPISource } from "./base/openapi" import { URL } from "url" -import { - getGlobalDB, - getTenantId, - isMultiTenant, -} from "@budibase/backend-core/tenancy" -import { getScopedConfig } from "@budibase/backend-core/db" -const jsonMimeType = "application/json" const parameterNotRef = ( param: OpenAPIV3.ParameterObject | OpenAPIV3.ReferenceObject ): param is OpenAPIV3.ParameterObject => { @@ -25,6 +18,13 @@ const requestBodyNotRef = ( return param !== undefined } +const schemaNotRef = ( + param: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined +): param is OpenAPIV3.SchemaObject => { + // all refs are deferenced by parser library + return param !== undefined +} + const isOpenAPI3 = (document: any): document is OpenAPIV3.Document => { return document.openapi.includes("3") } @@ -49,9 +49,25 @@ const getRequestBody = (operation: OpenAPIV3.OperationObject) => { if (requestBodyNotRef(operation.requestBody)) { const request: OpenAPIV3.RequestBodyObject = operation.requestBody as OpenAPIV3.RequestBodyObject - return request.content[jsonMimeType]?.example + const supportedMimeTypes = getMimeTypes(operation) + return supportedMimeTypes.length > 0 && + schemaNotRef(request.content[supportedMimeTypes[0]].schema) + ? ( + request.content[supportedMimeTypes[0]] + .schema as OpenAPIV3.SchemaObject + ).example + : undefined } - return null + return undefined +} + +const getMimeTypes = (operation: OpenAPIV3.OperationObject): string[] => { + if (requestBodyNotRef(operation.requestBody)) { + const request: OpenAPIV3.RequestBodyObject = + operation.requestBody as OpenAPIV3.RequestBodyObject + return Object.keys(request.content) + } + return [] } /** @@ -75,34 +91,6 @@ export class OpenAPI3 extends OpenAPISource { } } - getPlatformUrl = async (): Promise => { - const db = getGlobalDB() - const publicConfig = await getScopedConfig(db, { - type: "settings", - }) - - let url = publicConfig.platformUrl - if (isMultiTenant()) { - url += `/${getTenantId()}` - } - return url - } - - getUrl = async (): Promise => { - const platformUrl = await this.getPlatformUrl() - let url = this.document.servers ? this.document.servers[0].url : null - if (url) { - // check if url is relative or absolute - if (url.includes("http") || url.includes("https")) { - return new URL(url) - } - - return new URL(`${platformUrl}${url}`) - } - // if the specification doesn't contain a servers object, return the PLATFORM_URM environment variable - return new URL(platformUrl) - } - getInfo = async (): Promise => { const name = this.document.info.title || "Swagger Import" return { @@ -111,7 +99,9 @@ export class OpenAPI3 extends OpenAPISource { } getQueries = async (datasourceId: string): Promise => { - const url: URL = await this.getUrl() + const url: URL | null = this.document.servers + ? new URL(this.document.servers[0].url) + : null const queries: Query[] = [] for (let [path, pathItemObject] of Object.entries(this.document.paths)) { @@ -138,6 +128,11 @@ export class OpenAPI3 extends OpenAPISource { const headers: any = {} let requestBody = getRequestBody(operation) const parameters: QueryParameter[] = [] + const mimeTypes = getMimeTypes(operation) + + if (mimeTypes.length > 0) { + headers["Content-Type"] = mimeTypes[0] + } // combine the path parameters with the operation parameters const operationParams = operation.parameters || [] diff --git a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json index c1cf4c2b18..a859eec8e5 100644 --- a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json +++ b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json @@ -5,6 +5,11 @@ "version": "1.0.0", "title": "CRUD" }, + "servers": [ + { + "url": "http://example.com" + } + ], "tags": [ { "name": "entity" @@ -17,16 +22,24 @@ "entity" ], "operationId": "createEntity", - "parameters": [ - { - "$ref": "#/components/schemas/CreateEntityParameter" + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateEntity" + } + } } - ], + }, "responses": { "200": { "description": "successful operation", - "schema": { - "$ref": "#/components/schemas/Entity" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Entity" + } + } } } } @@ -36,22 +49,23 @@ "entity" ], "operationId": "getEntities", - "produces": [ - "application/json" - ], "parameters": [ { - "$ref": "#/components/schemas/PageParameter" + "$ref": "#/components/parameters/PageParameter" }, { - "$ref": "#/components/schemas/SizeParameter" + "$ref": "#/components/parameters/SizeParameter" } ], "responses": { "200": { "description": "successful operation", - "schema": { - "$ref": "#/components/schemas/Entities" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Entities" + } + } } } } @@ -60,7 +74,7 @@ "/entities/{entityId}": { "parameters": [ { - "$ref": "#/components/schemas/EntityIdParameter" + "$ref": "#/components/parameters/EntityIdParameter" } ], "get": { @@ -68,14 +82,15 @@ "entity" ], "operationId": "getEntity", - "produces": [ - "application/json" - ], "responses": { "200": { "description": "successful operation", - "schema": { - "$ref": "#/components/schemas/Entity" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Entity" + } + } } } } @@ -85,16 +100,24 @@ "entity" ], "operationId": "updateEntity", - "parameters": [ - { - "$ref": "#/components/schemas/EntityParameter" + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Entity" + } + } } - ], + }, "responses": { "200": { "description": "successful operation", - "schema": { - "$ref": "#/components/schemas/Entity" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Entity" + } + } } } } @@ -104,16 +127,24 @@ "entity" ], "operationId": "patchEntity", - "parameters": [ - { - "$ref": "#/components/schemas/EntityParameter" + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Entity" + } + } } - ], + }, "responses": { "200": { "description": "successful operation", - "schema": { - "$ref": "#/components/schemas/Entity" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Entity" + } + } } } } @@ -124,10 +155,7 @@ ], "parameters": [ { - "type": "string", - "name": "x-api-key", - "in": "header", - "required": false + "$ref": "#/components/parameters/APIKeyParameter" } ], "operationId": "deleteEntity", @@ -140,50 +168,44 @@ } }, "components": { - "schemas": { + "parameters": { "EntityIdParameter": { - "type": "integer", - "format": "int64", + "schema": { + "type": "integer", + "format": "int64" + }, "name": "entityId", "in": "path", "required": true }, - "CreateEntityParameter": { - "name": "entity", - "in": "body", - "required": true, - "schema": { - "$ref": "#/components/schemas/CreateEntity" - } - }, - "EntityParameter": { - "name": "entity", - "in": "body", - "required": true, - "schema": { - "$ref": "#/components/schemas/Entity" - } - }, - "PageParameter": { - "type": "integer", - "format": "int32", + "PageParameter": { + "schema": { + "type": "integer", + "format": "int32" + }, "name": "page", "in": "query", "required": false }, "SizeParameter": { - "type": "integer", - "format": "int32", + "schema": { + "type": "integer", + "format": "int32" + }, "name": "size", "in": "query", "required": false }, "APIKeyParameter": { - "type": "string", + "schema": { + "type": "string" + }, "name": "x-api-key", "in": "header", "required": false - }, + } + }, + "schemas": { "CreateEntity": { "type": "object", "properties": { diff --git a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.yaml b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.yaml index f87b3e347c..0a44a50a7b 100644 --- a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.yaml +++ b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.yaml @@ -1,10 +1,11 @@ --- -openapi: "3.0.2" +openapi: 3.0.2 info: description: A basic swagger file version: 1.0.0 title: CRUD -host: example.com +servers: + - url: http://example.com tags: - name: entity paths: @@ -13,144 +14,140 @@ paths: tags: - entity operationId: createEntity - produces: - - application/json - parameters: - - "$ref": "#/parameters/CreateEntity" + requestBody: + content: + application/json: + schema: + "$ref": "#/components/schemas/CreateEntity" responses: - "200": + '200': description: successful operation - schema: - "$ref": "#/definitions/Entity" + content: + application/json: + schema: + "$ref": "#/components/schemas/Entity" get: tags: - entity operationId: getEntities - produces: - - application/json parameters: - - "$ref": "#/parameters/Page" - - "$ref": "#/parameters/Size" + - "$ref": "#/components/parameters/PageParameter" + - "$ref": "#/components/parameters/SizeParameter" responses: - "200": + '200': description: successful operation - schema: - "$ref": "#/definitions/Entities" + content: + application/json: + schema: + "$ref": "#/components/schemas/Entities" "/entities/{entityId}": parameters: - - "$ref": "#/parameters/EntityId" + - "$ref": "#/components/parameters/EntityIdParameter" get: tags: - entity operationId: getEntity - produces: - - application/json responses: - "200": + '200': description: successful operation - schema: - "$ref": "#/definitions/Entity" + content: + application/json: + schema: + "$ref": "#/components/schemas/Entity" put: tags: - entity operationId: updateEntity - consumes: - - application/json - produces: - - application/json - parameters: - - "$ref": "#/parameters/Entity" + requestBody: + content: + application/json: + schema: + "$ref": "#/components/schemas/Entity" responses: - "200": + '200': description: successful operation - schema: - "$ref": "#/definitions/Entity" + content: + application/json: + schema: + "$ref": "#/components/schemas/Entity" patch: tags: - entity operationId: patchEntity - consumes: - - application/json - produces: - - application/json - parameters: - - "$ref": "#/parameters/Entity" + requestBody: + content: + application/json: + schema: + "$ref": "#/components/schemas/Entity" responses: - "200": + '200': description: successful operation - schema: - "$ref": "#/definitions/Entity" + content: + application/json: + schema: + "$ref": "#/components/schemas/Entity" delete: tags: - entity parameters: - - "$ref": "#/parameters/APIKey" + - "$ref": "#/components/parameters/APIKeyParameter" operationId: deleteEntity - produces: - - application/json responses: - "204": + '204': description: successful operation -parameters: - EntityId: - type: integer - format: int64 - name: entityId - in: path - required: true - CreateEntity: - name: entity - in: body - required: true - schema: - "$ref": "#/definitions/CreateEntity" - Entity: - name: entity - in: body - required: true - schema: - "$ref": "#/definitions/Entity" - Page: - type: integer - format: int32 - name: page - in: query - required: false - Size: - type: integer - format: int32 - name: size - in: query - required: false - APIKey: - type: string - name: x-api-key - in: header - required: false -definitions: - CreateEntity: - type: object - properties: - name: +components: + parameters: + EntityIdParameter: + schema: + type: integer + format: int64 + name: entityId + in: path + required: true + PageParameter: + schema: + type: integer + format: int32 + name: page + in: query + required: false + SizeParameter: + schema: + type: integer + format: int32 + name: size + in: query + required: false + APIKeyParameter: + schema: type: string - type: - type: string - example: - name: name - type: type - Entity: - allOf: - - type: object - properties: - id: - type: integer - format: int64 - - "$ref": "#/definitions/CreateEntity" - example: - id: 1 - name: name - type: type - Entities: - type: array - items: - "$ref": "#/definitions/Entity" + name: x-api-key + in: header + required: false + schemas: + CreateEntity: + type: object + properties: + name: + type: string + type: + type: string + example: + name: name + type: type + Entity: + allOf: + - type: object + properties: + id: + type: integer + format: int64 + - "$ref": "#/components/schemas/CreateEntity" + example: + id: 1 + name: name + type: type + Entities: + type: array + items: + "$ref": "#/components/schemas/Entity" diff --git a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/openapi3.spec.js b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/openapi3.spec.js index 6278e0fece..731c245d4e 100644 --- a/packages/server/src/api/controllers/query/import/sources/tests/openapi3/openapi3.spec.js +++ b/packages/server/src/api/controllers/query/import/sources/tests/openapi3/openapi3.spec.js @@ -1,21 +1,6 @@ const fs = require("fs") const path = require("path") -const getGlobalDB = jest.fn().mockReturnValue("db") -const getTenantId = jest.fn().mockReturnValue("1") -const isMultiTenant = jest.fn().mockReturnValue(true) -const getScopedConfig = jest - .fn() - .mockResolvedValue({ platformUrl: "somePlatform" }) -jest.mock("@budibase/backend-core/db", () => ({ - getScopedConfig, -})) - -jest.mock("@budibase/backend-core/tenancy", () => ({ - getTenantId, - getGlobalDB, - isMultiTenant, -})) const { OpenAPI3 } = require("../../openapi3") const getData = (file, extension) => { @@ -48,10 +33,9 @@ describe("OpenAPI3 Import", () => { }) const runTests = async (filename, test, assertions) => { - /*for (let extension of ["json", "yaml"]) { + for (let extension of ["json", "yaml"]) { await test(filename, extension, assertions) - }*/ - await test(filename, "json", assertions) + } } const testImportInfo = async (file, extension) => { From 530024bd632d6ad47d0bf066c0192c3ed5d8dc37 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 7 Mar 2022 08:16:55 +0000 Subject: [PATCH 008/171] Add component name to settings panel --- .../design/PropertiesPanel/ComponentSettingsSection.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte b/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte index f9fa56f739..88455fb003 100644 --- a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte @@ -32,7 +32,7 @@ const customSections = settings.filter(setting => setting.section) return [ { - name: "General", + name: componentDefinition?.name || "General", info: componentDefinition?.info, settings: generalSettings, }, From 5ee150566b8f90261d8f9ac7f102fbbf696f98f1 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Mon, 7 Mar 2022 10:41:28 +0000 Subject: [PATCH 009/171] Fix build, additional tests, updated body detection, support variables in urls --- .../src/api/controllers/query/import/index.ts | 4 +- .../query/import/sources/base/index.ts | 8 +++- .../query/import/sources/openapi3.ts | 44 +++++++++++++------ .../query/import/tests/index.spec.js | 43 ++++++++++++++++++ 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/packages/server/src/api/controllers/query/import/index.ts b/packages/server/src/api/controllers/query/import/index.ts index 4573fd27f7..d6f5beedf5 100644 --- a/packages/server/src/api/controllers/query/import/index.ts +++ b/packages/server/src/api/controllers/query/import/index.ts @@ -1,7 +1,7 @@ import { queryValidation } from "../validation" import { generateQueryID } from "../../../../db/utils" import { ImportInfo, ImportSource } from "./sources/base" -import { OpenAPI3 } from "./sources/openapi2" +import { OpenAPI2 } from "./sources/openapi2" import { OpenAPI3 } from "./sources/openapi3" import { Query } from "./../../../../definitions/common" import { Curl } from "./sources/curl" @@ -19,7 +19,7 @@ export class RestImporter { constructor(data: string) { this.data = data - this.sources = [new OpenAPI3(), new OpenAPI3(), new Curl()] + this.sources = [new OpenAPI2(), new OpenAPI3(), new Curl()] } init = async () => { diff --git a/packages/server/src/api/controllers/query/import/sources/base/index.ts b/packages/server/src/api/controllers/query/import/sources/base/index.ts index 096fa10e92..d1584093cf 100644 --- a/packages/server/src/api/controllers/query/import/sources/base/index.ts +++ b/packages/server/src/api/controllers/query/import/sources/base/index.ts @@ -23,7 +23,7 @@ export abstract class ImportSource { name: string, method: string, path: string, - url: URL | null, + url: URL | string | undefined, queryString: string, headers: object = {}, parameters: QueryParameter[] = [], @@ -35,7 +35,11 @@ export abstract class ImportSource { const schema = {} path = this.processPath(path) if (url) { - path = `${url.origin}/${path}` + if (typeof url === "string") { + path = `${url}/${path}` + } else { + path = `${url.origin}/${path}` + } } queryString = this.processQuery(queryString) const requestBody = JSON.stringify(body, null, 2) diff --git a/packages/server/src/api/controllers/query/import/sources/openapi3.ts b/packages/server/src/api/controllers/query/import/sources/openapi3.ts index c9e49595b2..65719ef71d 100644 --- a/packages/server/src/api/controllers/query/import/sources/openapi3.ts +++ b/packages/server/src/api/controllers/query/import/sources/openapi3.ts @@ -47,24 +47,32 @@ const isParameter = ( const getRequestBody = (operation: OpenAPIV3.OperationObject) => { if (requestBodyNotRef(operation.requestBody)) { - const request: OpenAPIV3.RequestBodyObject = - operation.requestBody as OpenAPIV3.RequestBodyObject + const request: OpenAPIV3.RequestBodyObject = operation.requestBody const supportedMimeTypes = getMimeTypes(operation) - return supportedMimeTypes.length > 0 && - schemaNotRef(request.content[supportedMimeTypes[0]].schema) - ? ( - request.content[supportedMimeTypes[0]] - .schema as OpenAPIV3.SchemaObject - ).example - : undefined + if (supportedMimeTypes.length > 0) { + const mimeType = supportedMimeTypes[0] + + // try get example from request + const content = request.content[mimeType] + if (content.example) { + return content.example + } + + // try get example from schema + if (schemaNotRef(content.schema)) { + const schema = content.schema + if (schema.example) { + return schema.example + } + } + } } return undefined } const getMimeTypes = (operation: OpenAPIV3.OperationObject): string[] => { if (requestBodyNotRef(operation.requestBody)) { - const request: OpenAPIV3.RequestBodyObject = - operation.requestBody as OpenAPIV3.RequestBodyObject + const request: OpenAPIV3.RequestBodyObject = operation.requestBody return Object.keys(request.content) } return [] @@ -99,9 +107,17 @@ export class OpenAPI3 extends OpenAPISource { } getQueries = async (datasourceId: string): Promise => { - const url: URL | null = this.document.servers - ? new URL(this.document.servers[0].url) - : null + let url: string | URL | undefined + if (this.document.servers?.length) { + url = this.document.servers[0].url + try { + url = new URL(url) + } catch (err) { + // unable to construct url, e.g. with variables + // proceed with string form of url + } + } + const queries: Query[] = [] for (let [path, pathItemObject] of Object.entries(this.document.paths)) { diff --git a/packages/server/src/api/controllers/query/import/tests/index.spec.js b/packages/server/src/api/controllers/query/import/tests/index.spec.js index 8d074ea885..0cfb4f4f19 100644 --- a/packages/server/src/api/controllers/query/import/tests/index.spec.js +++ b/packages/server/src/api/controllers/query/import/tests/index.spec.js @@ -23,14 +23,27 @@ const oapi2CrudYaml = getData("openapi2/data/crud/crud.json") const oapi2PetstoreJson = getData("openapi2/data/petstore/petstore.json") const oapi2PetstoreYaml = getData("openapi2/data/petstore/petstore.json") +// openapi3 +const oapi3CrudJson = getData("openapi3/data/crud/crud.json") +const oapi3CrudYaml = getData("openapi3/data/crud/crud.json") +const oapi3PetstoreJson = getData("openapi3/data/petstore/petstore.json") +const oapi3PetstoreYaml = getData("openapi3/data/petstore/petstore.json") + // curl const curl = getData("curl/data/post.txt") const datasets = { + // openapi2 (swagger) oapi2CrudJson, oapi2CrudYaml, oapi2PetstoreJson, oapi2PetstoreYaml, + // openapi3 + oapi3CrudJson, + oapi3CrudYaml, + oapi3PetstoreJson, + oapi3PetstoreYaml, + // curl curl } @@ -56,6 +69,7 @@ describe("Rest Importer", () => { it("gets info", async () => { const assertions = { + // openapi2 (swagger) "oapi2CrudJson" : { name: "CRUD", }, @@ -68,6 +82,20 @@ describe("Rest Importer", () => { "oapi2PetstoreYaml" :{ name: "Swagger Petstore", }, + // openapi3 + "oapi3CrudJson" : { + name: "CRUD", + }, + "oapi3CrudYaml" : { + name: "CRUD", + }, + "oapi3PetstoreJson" : { + name: "Swagger Petstore - OpenAPI 3.0", + }, + "oapi3PetstoreYaml" :{ + name: "Swagger Petstore - OpenAPI 3.0", + }, + // curl "curl": { name: "example.com", } @@ -89,6 +117,7 @@ describe("Rest Importer", () => { // simple sanity assertions that the whole dataset // makes it through the importer const assertions = { + // openapi2 (swagger) "oapi2CrudJson" : { count: 6, }, @@ -101,6 +130,20 @@ describe("Rest Importer", () => { "oapi2PetstoreYaml" :{ count: 20, }, + // openapi3 + "oapi3CrudJson" : { + count: 6, + }, + "oapi3CrudYaml" :{ + count: 6, + }, + "oapi3PetstoreJson" : { + count: 19, + }, + "oapi3PetstoreYaml" :{ + count: 19, + }, + // curl "curl": { count: 1 } From 4c88a046fd7de958ac91ceea943bce5c87006c07 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 7 Mar 2022 10:41:52 +0000 Subject: [PATCH 010/171] Update confirm text button when duplicating screens --- .../ComponentNavigationTree/ScreenDropdownMenu.svelte | 1 + .../design/NavigationPanel/ScreenDetailsModal.svelte | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 7d0b88c235..3a5e60ae57 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -85,5 +85,6 @@ onConfirm={createDuplicateScreen} screenName={screen?.props._instanceName} screenUrl={screen?.routing.route} + confirmText="Duplicate" /> diff --git a/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte b/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte index 82b90be6a6..75977e51a2 100644 --- a/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte @@ -9,6 +9,7 @@ export let showProgressCircle = false export let screenName export let screenUrl + export let confirmText = "Continue" let routeError let touched = false @@ -46,7 +47,7 @@ Date: Mon, 7 Mar 2022 13:58:04 +0100 Subject: [PATCH 011/171] implement review comments --- .../src/api/controllers/query/import/sources/openapi3.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/server/src/api/controllers/query/import/sources/openapi3.ts b/packages/server/src/api/controllers/query/import/sources/openapi3.ts index 65719ef71d..e6bdbe8682 100644 --- a/packages/server/src/api/controllers/query/import/sources/openapi3.ts +++ b/packages/server/src/api/controllers/query/import/sources/openapi3.ts @@ -26,7 +26,7 @@ const schemaNotRef = ( } const isOpenAPI3 = (document: any): document is OpenAPIV3.Document => { - return document.openapi.includes("3") + return document.openapi.includes("3.0") } const methods: string[] = Object.values(OpenAPIV3.HttpMethods) @@ -79,8 +79,8 @@ const getMimeTypes = (operation: OpenAPIV3.OperationObject): string[] => { } /** - * OpenAPI Version 3.1 - aka "Swagger" - * https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md + * OpenAPI Version 3.0 + * https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md */ export class OpenAPI3 extends OpenAPISource { document!: OpenAPIV3.Document @@ -100,7 +100,7 @@ export class OpenAPI3 extends OpenAPISource { } getInfo = async (): Promise => { - const name = this.document.info.title || "Swagger Import" + const name = this.document.info.title || "OpenAPI Import" return { name, } From d2b13cf3fa0b68d6313e8366c0a48b18d3b926b9 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 7 Mar 2022 13:56:06 +0000 Subject: [PATCH 012/171] Add option to paste inside screens --- .../ScreenDropdownMenu.svelte | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 3a5e60ae57..972414ae0b 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -62,6 +62,14 @@ notifications.error("Error deleting screen") } } + + const pasteComponent = mode => { + try { + store.actions.components.paste(screen?.props, mode) + } catch (error) { + notifications.error("Error saving component") + } + } @@ -69,6 +77,13 @@
Duplicate + pasteComponent("inside")} + disabled={!$store.componentToPaste} + > + Paste inside + Delete From e84e4f98996ea8625f1daaf2fb1195d3cc4b201e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 7 Mar 2022 14:05:26 +0000 Subject: [PATCH 013/171] Add duplicate action to settings bar --- .../design/AppPreview/CurrentItemPreview.svelte | 5 +++++ .../client/src/components/preview/SettingsBar.svelte | 10 ++++++++++ packages/client/src/stores/builder.js | 3 +++ 3 files changed, 18 insertions(+) diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 2a886fab0c..b0b7c16c68 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -159,6 +159,11 @@ await store.actions.components.updateProp(data.prop, data.value) } else if (type === "delete-component" && data.id) { confirmDeleteComponent(data.id) + } else if (type === "duplicate-component" && data.id) { + const rootComponent = get(currentAsset).props + const component = findComponent(rootComponent, data.id) + store.actions.components.copy(component) + await store.actions.components.paste(component) } else if (type === "preview-loaded") { // Wait for this event to show the client library if intelligent // loading is supported diff --git a/packages/client/src/components/preview/SettingsBar.svelte b/packages/client/src/components/preview/SettingsBar.svelte index a4e3ca4d72..c5ad8bef6c 100644 --- a/packages/client/src/components/preview/SettingsBar.svelte +++ b/packages/client/src/components/preview/SettingsBar.svelte @@ -146,6 +146,15 @@
{/if} {/each} + { + builderStore.actions.duplicateComponent( + $builderStore.selectedComponent._id + ) + }} + title="Duplicate component" + /> { @@ -153,6 +162,7 @@ $builderStore.selectedComponent._id ) }} + title="Delete component" />
{/if} diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 719909b538..27c8bbe2a2 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -62,6 +62,9 @@ const createBuilderStore = () => { deleteComponent: id => { dispatchEvent("delete-component", { id }) }, + duplicateComponent: id => { + dispatchEvent("duplicate-component", { id }) + }, notifyLoaded: () => { dispatchEvent("preview-loaded") }, From 8131bae496687e6d9fbba82fd19d8d39065c8089 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 8 Mar 2022 08:46:07 +0000 Subject: [PATCH 014/171] Update cypress tests for different button casing --- packages/builder/cypress/support/commands.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index ede1038a58..699cf1fbf0 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -247,7 +247,7 @@ Cypress.Commands.add("createScreen", (screenName, route) => { cy.get("[aria-label=AddCircle]").click() cy.get(".spectrum-Modal").within(() => { cy.get(".item").contains("Blank").click() - cy.get(".spectrum-Button").contains("Add Screens").click({ force: true }) + cy.get(".spectrum-Button").contains("Add screens").click({ force: true }) cy.wait(500) }) cy.get(".spectrum-Dialog-grid").within(() => { @@ -265,7 +265,7 @@ Cypress.Commands.add("createAutogeneratedScreens", screenNames => { for (let i = 0; i < screenNames.length; i++) { cy.get(".item").contains(screenNames[i]).click() } - cy.get(".spectrum-Button").contains("Add Screens").click({ force: true }) + cy.get(".spectrum-Button").contains("Add screens").click({ force: true }) cy.wait(4000) }) From 5811217a4eee6468d3cdd590a47d23cf626cad7b Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 8 Mar 2022 13:43:12 +0000 Subject: [PATCH 015/171] initial version of nextjs app with bulma, for use with BB public API. --- examples/nextjs-api-sales/.eslintrc.json | 3 + examples/nextjs-api-sales/.gitignore | 38 + examples/nextjs-api-sales/README.md | 34 + examples/nextjs-api-sales/next-env.d.ts | 5 + examples/nextjs-api-sales/next.config.js | 10 + examples/nextjs-api-sales/package.json | 25 + examples/nextjs-api-sales/pages/_app.tsx | 8 + examples/nextjs-api-sales/pages/api/hello.ts | 13 + examples/nextjs-api-sales/pages/index.tsx | 72 + examples/nextjs-api-sales/public/favicon.ico | Bin 0 -> 25931 bytes examples/nextjs-api-sales/public/vercel.svg | 4 + examples/nextjs-api-sales/styles/global.sass | 12 + .../nextjs-api-sales/styles/home.module.css | 116 + examples/nextjs-api-sales/tsconfig.json | 20 + examples/nextjs-api-sales/yarn.lock | 3042 +++++++++++++++++ 15 files changed, 3402 insertions(+) create mode 100644 examples/nextjs-api-sales/.eslintrc.json create mode 100644 examples/nextjs-api-sales/.gitignore create mode 100644 examples/nextjs-api-sales/README.md create mode 100644 examples/nextjs-api-sales/next-env.d.ts create mode 100644 examples/nextjs-api-sales/next.config.js create mode 100644 examples/nextjs-api-sales/package.json create mode 100644 examples/nextjs-api-sales/pages/_app.tsx create mode 100644 examples/nextjs-api-sales/pages/api/hello.ts create mode 100644 examples/nextjs-api-sales/pages/index.tsx create mode 100644 examples/nextjs-api-sales/public/favicon.ico create mode 100644 examples/nextjs-api-sales/public/vercel.svg create mode 100644 examples/nextjs-api-sales/styles/global.sass create mode 100644 examples/nextjs-api-sales/styles/home.module.css create mode 100644 examples/nextjs-api-sales/tsconfig.json create mode 100644 examples/nextjs-api-sales/yarn.lock diff --git a/examples/nextjs-api-sales/.eslintrc.json b/examples/nextjs-api-sales/.eslintrc.json new file mode 100644 index 0000000000..bffb357a71 --- /dev/null +++ b/examples/nextjs-api-sales/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/examples/nextjs-api-sales/.gitignore b/examples/nextjs-api-sales/.gitignore new file mode 100644 index 0000000000..7d093c39ff --- /dev/null +++ b/examples/nextjs-api-sales/.gitignore @@ -0,0 +1,38 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo diff --git a/examples/nextjs-api-sales/README.md b/examples/nextjs-api-sales/README.md new file mode 100644 index 0000000000..c87e0421d2 --- /dev/null +++ b/examples/nextjs-api-sales/README.md @@ -0,0 +1,34 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/nextjs-api-sales/next-env.d.ts b/examples/nextjs-api-sales/next-env.d.ts new file mode 100644 index 0000000000..4f11a03dc6 --- /dev/null +++ b/examples/nextjs-api-sales/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/nextjs-api-sales/next.config.js b/examples/nextjs-api-sales/next.config.js new file mode 100644 index 0000000000..12c41deacd --- /dev/null +++ b/examples/nextjs-api-sales/next.config.js @@ -0,0 +1,10 @@ +const path = require("path") +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + sassOptions: { + includePaths: [path.join(__dirname, "styles")] + } +} + +module.exports = nextConfig diff --git a/examples/nextjs-api-sales/package.json b/examples/nextjs-api-sales/package.json new file mode 100644 index 0000000000..4212ea6c5b --- /dev/null +++ b/examples/nextjs-api-sales/package.json @@ -0,0 +1,25 @@ +{ + "name": "nextjs-api-sales", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev -p 3001", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "bulma": "^0.9.3", + "next": "12.1.0", + "node-sass": "^7.0.1", + "react": "17.0.2", + "react-dom": "17.0.2" + }, + "devDependencies": { + "@types/node": "17.0.21", + "@types/react": "17.0.39", + "eslint": "8.10.0", + "eslint-config-next": "12.1.0", + "typescript": "4.6.2" + } +} diff --git a/examples/nextjs-api-sales/pages/_app.tsx b/examples/nextjs-api-sales/pages/_app.tsx new file mode 100644 index 0000000000..71f53e7f8a --- /dev/null +++ b/examples/nextjs-api-sales/pages/_app.tsx @@ -0,0 +1,8 @@ +import "../styles/global.sass" +import type { AppProps } from "next/app" + +function MyApp({ Component, pageProps }: AppProps) { + return +} + +export default MyApp diff --git a/examples/nextjs-api-sales/pages/api/hello.ts b/examples/nextjs-api-sales/pages/api/hello.ts new file mode 100644 index 0000000000..f8bcc7e5ca --- /dev/null +++ b/examples/nextjs-api-sales/pages/api/hello.ts @@ -0,0 +1,13 @@ +// Next.js API route support: https://nextjs.org/docs/api-routes/introduction +import type { NextApiRequest, NextApiResponse } from 'next' + +type Data = { + name: string +} + +export default function handler( + req: NextApiRequest, + res: NextApiResponse +) { + res.status(200).json({ name: 'John Doe' }) +} diff --git a/examples/nextjs-api-sales/pages/index.tsx b/examples/nextjs-api-sales/pages/index.tsx new file mode 100644 index 0000000000..7b0ab6aebe --- /dev/null +++ b/examples/nextjs-api-sales/pages/index.tsx @@ -0,0 +1,72 @@ +import type { NextPage } from "next" +import Head from "next/head" +import Image from "next/image" +import styles from "../styles/home.module.css" + +const Home: NextPage = () => { + return ( + + ) +} + +export default Home diff --git a/examples/nextjs-api-sales/public/favicon.ico b/examples/nextjs-api-sales/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 zcmeHv30#a{`}aL_*G&7qml|y<+KVaDM2m#dVr!KsA!#An?kSQM(q<_dDNCpjEux83 zLb9Z^XxbDl(w>%i@8hT6>)&Gu{h#Oeyszu?xtw#Zb1mO{pgX9699l+Qppw7jXaYf~-84xW z)w4x8?=youko|}Vr~(D$UXIbiXABHh`p1?nn8Po~fxRJv}|0e(BPs|G`(TT%kKVJAdg5*Z|x0leQq0 zkdUBvb#>9F()jo|T~kx@OM8$9wzs~t2l;K=woNssA3l6|sx2r3+kdfVW@e^8e*E}v zA1y5{bRi+3Z`uD3{F7LgFJDdvm;nJilkzDku>BwXH(8ItVCXk*-lSJnR?-2UN%hJ){&rlvg`CDTj z)Bzo!3v7Ou#83zEDEFcKt(f1E0~=rqeEbTnMvWR#{+9pg%7G8y>u1OVRUSoox-ovF z2Ydma(;=YuBY(eI|04{hXzZD6_f(v~H;C~y5=DhAC{MMS>2fm~1H_t2$56pc$NH8( z5bH|<)71dV-_oCHIrzrT`2s-5w_+2CM0$95I6X8p^r!gHp+j_gd;9O<1~CEQQGS8) zS9Qh3#p&JM-G8rHekNmKVewU;pJRcTAog68KYo^dRo}(M>36U4Us zfgYWSiHZL3;lpWT=zNAW>Dh#mB!_@Lg%$ms8N-;aPqMn+C2HqZgz&9~Eu z4|Kp<`$q)Uw1R?y(~S>ePdonHxpV1#eSP1B;Ogo+-Pk}6#0GsZZ5!||ev2MGdh}_m z{DeR7?0-1^zVs&`AV6Vt;r3`I`OI_wgs*w=eO%_#7Kepl{B@xiyCANc(l zzIyd4y|c6PXWq9-|KM8(zIk8LPk(>a)zyFWjhT!$HJ$qX1vo@d25W<fvZQ2zUz5WRc(UnFMKHwe1| zWmlB1qdbiA(C0jmnV<}GfbKtmcu^2*P^O?MBLZKt|As~ge8&AAO~2K@zbXelK|4T<{|y4`raF{=72kC2Kn(L4YyenWgrPiv z@^mr$t{#X5VuIMeL!7Ab6_kG$&#&5p*Z{+?5U|TZ`B!7llpVmp@skYz&n^8QfPJzL z0G6K_OJM9x+Wu2gfN45phANGt{7=C>i34CV{Xqlx(fWpeAoj^N0Biu`w+MVcCUyU* zDZuzO0>4Z6fbu^T_arWW5n!E45vX8N=bxTVeFoep_G#VmNlQzAI_KTIc{6>c+04vr zx@W}zE5JNSU>!THJ{J=cqjz+4{L4A{Ob9$ZJ*S1?Ggg3klFp!+Y1@K+pK1DqI|_gq z5ZDXVpge8-cs!o|;K73#YXZ3AShj50wBvuq3NTOZ`M&qtjj#GOFfgExjg8Gn8>Vq5 z`85n+9|!iLCZF5$HJ$Iu($dm?8~-ofu}tEc+-pyke=3!im#6pk_Wo8IA|fJwD&~~F zc16osQ)EBo58U7XDuMexaPRjU@h8tXe%S{fA0NH3vGJFhuyyO!Uyl2^&EOpX{9As0 zWj+P>{@}jxH)8|r;2HdupP!vie{sJ28b&bo!8`D^x}TE$%zXNb^X1p@0PJ86`dZyj z%ce7*{^oo+6%&~I!8hQy-vQ7E)0t0ybH4l%KltWOo~8cO`T=157JqL(oq_rC%ea&4 z2NcTJe-HgFjNg-gZ$6!Y`SMHrlj}Etf7?r!zQTPPSv}{so2e>Fjs1{gzk~LGeesX%r(Lh6rbhSo_n)@@G-FTQy93;l#E)hgP@d_SGvyCp0~o(Y;Ee8{ zdVUDbHm5`2taPUOY^MAGOw*>=s7=Gst=D+p+2yON!0%Hk` zz5mAhyT4lS*T3LS^WSxUy86q&GnoHxzQ6vm8)VS}_zuqG?+3td68_x;etQAdu@sc6 zQJ&5|4(I?~3d-QOAODHpZ=hlSg(lBZ!JZWCtHHSj`0Wh93-Uk)_S%zsJ~aD>{`A0~ z9{AG(e|q3g5B%wYKRxiL2Y$8(4w6bzchKuloQW#e&S3n+P- z8!ds-%f;TJ1>)v)##>gd{PdS2Oc3VaR`fr=`O8QIO(6(N!A?pr5C#6fc~Ge@N%Vvu zaoAX2&(a6eWy_q&UwOhU)|P3J0Qc%OdhzW=F4D|pt0E4osw;%<%Dn58hAWD^XnZD= z>9~H(3bmLtxpF?a7su6J7M*x1By7YSUbxGi)Ot0P77`}P3{)&5Un{KD?`-e?r21!4vTTnN(4Y6Lin?UkSM z`MXCTC1@4A4~mvz%Rh2&EwY))LeoT=*`tMoqcEXI>TZU9WTP#l?uFv+@Dn~b(>xh2 z;>B?;Tz2SR&KVb>vGiBSB`@U7VIWFSo=LDSb9F{GF^DbmWAfpms8Sx9OX4CnBJca3 zlj9(x!dIjN?OG1X4l*imJNvRCk}F%!?SOfiOq5y^mZW)jFL@a|r-@d#f7 z2gmU8L3IZq0ynIws=}~m^#@&C%J6QFo~Mo4V`>v7MI-_!EBMMtb%_M&kvAaN)@ZVw z+`toz&WG#HkWDjnZE!6nk{e-oFdL^$YnbOCN}JC&{$#$O27@|Tn-skXr)2ml2~O!5 zX+gYoxhoc7qoU?C^3~&!U?kRFtnSEecWuH0B0OvLodgUAi}8p1 zrO6RSXHH}DMc$&|?D004DiOVMHV8kXCP@7NKB zgaZq^^O<7PoKEp72kby@W0Z!Y*Ay{&vfg#C&gG@YVR9g?FEocMUi1gSN$+V+ayF45{a zuDZDTN}mS|;BO%gEf}pjBfN2-gIrU#G5~cucA;dokXW89%>AyXJJI z9X4UlIWA|ZYHgbI z5?oFk@A=Ik7lrEQPDH!H+b`7_Y~aDb_qa=B2^Y&Ow41cU=4WDd40dp5(QS-WMN-=Y z9g;6_-JdNU;|6cPwf$ak*aJIcwL@1n$#l~zi{c{EW?T;DaW*E8DYq?Umtz{nJ&w-M zEMyTDrC&9K$d|kZe2#ws6)L=7K+{ zQw{XnV6UC$6-rW0emqm8wJoeZK)wJIcV?dST}Z;G0Arq{dVDu0&4kd%N!3F1*;*pW zR&qUiFzK=@44#QGw7k1`3t_d8&*kBV->O##t|tonFc2YWrL7_eqg+=+k;!F-`^b8> z#KWCE8%u4k@EprxqiV$VmmtiWxDLgnGu$Vs<8rppV5EajBXL4nyyZM$SWVm!wnCj-B!Wjqj5-5dNXukI2$$|Bu3Lrw}z65Lc=1G z^-#WuQOj$hwNGG?*CM_TO8Bg-1+qc>J7k5c51U8g?ZU5n?HYor;~JIjoWH-G>AoUP ztrWWLbRNqIjW#RT*WqZgPJXU7C)VaW5}MiijYbABmzoru6EmQ*N8cVK7a3|aOB#O& zBl8JY2WKfmj;h#Q!pN%9o@VNLv{OUL?rixHwOZuvX7{IJ{(EdPpuVFoQqIOa7giLVkBOKL@^smUA!tZ1CKRK}#SSM)iQHk)*R~?M!qkCruaS!#oIL1c z?J;U~&FfH#*98^G?i}pA{ z9Jg36t4=%6mhY(quYq*vSxptes9qy|7xSlH?G=S@>u>Ebe;|LVhs~@+06N<4CViBk zUiY$thvX;>Tby6z9Y1edAMQaiH zm^r3v#$Q#2T=X>bsY#D%s!bhs^M9PMAcHbCc0FMHV{u-dwlL;a1eJ63v5U*?Q_8JO zT#50!RD619#j_Uf))0ooADz~*9&lN!bBDRUgE>Vud-i5ck%vT=r^yD*^?Mp@Q^v+V zG#-?gKlr}Eeqifb{|So?HM&g91P8|av8hQoCmQXkd?7wIJwb z_^v8bbg`SAn{I*4bH$u(RZ6*xUhuA~hc=8czK8SHEKTzSxgbwi~9(OqJB&gwb^l4+m`k*Q;_?>Y-APi1{k zAHQ)P)G)f|AyjSgcCFps)Fh6Bca*Xznq36!pV6Az&m{O8$wGFD? zY&O*3*J0;_EqM#jh6^gMQKpXV?#1?>$ml1xvh8nSN>-?H=V;nJIwB07YX$e6vLxH( zqYwQ>qxwR(i4f)DLd)-$P>T-no_c!LsN@)8`e;W@)-Hj0>nJ-}Kla4-ZdPJzI&Mce zv)V_j;(3ERN3_@I$N<^|4Lf`B;8n+bX@bHbcZTopEmDI*Jfl)-pFDvo6svPRoo@(x z);_{lY<;);XzT`dBFpRmGrr}z5u1=pC^S-{ce6iXQlLGcItwJ^mZx{m$&DA_oEZ)B{_bYPq-HA zcH8WGoBG(aBU_j)vEy+_71T34@4dmSg!|M8Vf92Zj6WH7Q7t#OHQqWgFE3ARt+%!T z?oLovLVlnf?2c7pTc)~cc^($_8nyKwsN`RA-23ed3sdj(ys%pjjM+9JrctL;dy8a( z@en&CQmnV(()bu|Y%G1-4a(6x{aLytn$T-;(&{QIJB9vMox11U-1HpD@d(QkaJdEb zG{)+6Dos_L+O3NpWo^=gR?evp|CqEG?L&Ut#D*KLaRFOgOEK(Kq1@!EGcTfo+%A&I z=dLbB+d$u{sh?u)xP{PF8L%;YPPW53+@{>5W=Jt#wQpN;0_HYdw1{ksf_XhO4#2F= zyPx6Lx2<92L-;L5PD`zn6zwIH`Jk($?Qw({erA$^bC;q33hv!d!>%wRhj# zal^hk+WGNg;rJtb-EB(?czvOM=H7dl=vblBwAv>}%1@{}mnpUznfq1cE^sgsL0*4I zJ##!*B?=vI_OEVis5o+_IwMIRrpQyT_Sq~ZU%oY7c5JMIADzpD!Upz9h@iWg_>>~j zOLS;wp^i$-E?4<_cp?RiS%Rd?i;f*mOz=~(&3lo<=@(nR!_Rqiprh@weZlL!t#NCc zO!QTcInq|%#>OVgobj{~ixEUec`E25zJ~*DofsQdzIa@5^nOXj2T;8O`l--(QyU^$t?TGY^7#&FQ+2SS3B#qK*k3`ye?8jUYSajE5iBbJls75CCc(m3dk{t?- zopcER9{Z?TC)mk~gpi^kbbu>b-+a{m#8-y2^p$ka4n60w;Sc2}HMf<8JUvhCL0B&Btk)T`ctE$*qNW8L$`7!r^9T+>=<=2qaq-;ll2{`{Rg zc5a0ZUI$oG&j-qVOuKa=*v4aY#IsoM+1|c4Z)<}lEDvy;5huB@1RJPquU2U*U-;gu z=En2m+qjBzR#DEJDO`WU)hdd{Vj%^0V*KoyZ|5lzV87&g_j~NCjwv0uQVqXOb*QrQ zy|Qn`hxx(58c70$E;L(X0uZZ72M1!6oeg)(cdKO ze0gDaTz+ohR-#d)NbAH4x{I(21yjwvBQfmpLu$)|m{XolbgF!pmsqJ#D}(ylp6uC> z{bqtcI#hT#HW=wl7>p!38sKsJ`r8}lt-q%Keqy%u(xk=yiIJiUw6|5IvkS+#?JTBl z8H5(Q?l#wzazujH!8o>1xtn8#_w+397*_cy8!pQGP%K(Ga3pAjsaTbbXJlQF_+m+-UpUUent@xM zg%jqLUExj~o^vQ3Gl*>wh=_gOr2*|U64_iXb+-111aH}$TjeajM+I20xw(((>fej-@CIz4S1pi$(#}P7`4({6QS2CaQS4NPENDp>sAqD z$bH4KGzXGffkJ7R>V>)>tC)uax{UsN*dbeNC*v}#8Y#OWYwL4t$ePR?VTyIs!wea+ z5Urmc)X|^`MG~*dS6pGSbU+gPJoq*^a=_>$n4|P^w$sMBBy@f*Z^Jg6?n5?oId6f{ z$LW4M|4m502z0t7g<#Bx%X;9<=)smFolV&(V^(7Cv2-sxbxopQ!)*#ZRhTBpx1)Fc zNm1T%bONzv6@#|dz(w02AH8OXe>kQ#1FMCzO}2J_mST)+ExmBr9cva-@?;wnmWMOk z{3_~EX_xadgJGv&H@zK_8{(x84`}+c?oSBX*Ge3VdfTt&F}yCpFP?CpW+BE^cWY0^ zb&uBN!Ja3UzYHK-CTyA5=L zEMW{l3Usky#ly=7px648W31UNV@K)&Ub&zP1c7%)`{);I4b0Q<)B}3;NMG2JH=X$U zfIW4)4n9ZM`-yRj67I)YSLDK)qfUJ_ij}a#aZN~9EXrh8eZY2&=uY%2N0UFF7<~%M zsB8=erOWZ>Ct_#^tHZ|*q`H;A)5;ycw*IcmVxi8_0Xk}aJA^ath+E;xg!x+As(M#0=)3!NJR6H&9+zd#iP(m0PIW8$ z1Y^VX`>jm`W!=WpF*{ioM?C9`yOR>@0q=u7o>BP-eSHqCgMDj!2anwH?s%i2p+Q7D zzszIf5XJpE)IG4;d_(La-xenmF(tgAxK`Y4sQ}BSJEPs6N_U2vI{8=0C_F?@7<(G; zo$~G=8p+076G;`}>{MQ>t>7cm=zGtfbdDXm6||jUU|?X?CaE?(<6bKDYKeHlz}DA8 zXT={X=yp_R;HfJ9h%?eWvQ!dRgz&Su*JfNt!Wu>|XfU&68iRikRrHRW|ZxzRR^`eIGt zIeiDgVS>IeExKVRWW8-=A=yA`}`)ZkWBrZD`hpWIxBGkh&f#ijr449~m`j6{4jiJ*C!oVA8ZC?$1RM#K(_b zL9TW)kN*Y4%^-qPpMP7d4)o?Nk#>aoYHT(*g)qmRUb?**F@pnNiy6Fv9rEiUqD(^O zzyS?nBrX63BTRYduaG(0VVG2yJRe%o&rVrLjbxTaAFTd8s;<<@Qs>u(<193R8>}2_ zuwp{7;H2a*X7_jryzriZXMg?bTuegABb^87@SsKkr2)0Gyiax8KQWstw^v#ix45EVrcEhr>!NMhprl$InQMzjSFH54x5k9qHc`@9uKQzvL4ihcq{^B zPrVR=o_ic%Y>6&rMN)hTZsI7I<3&`#(nl+3y3ys9A~&^=4?PL&nd8)`OfG#n zwAMN$1&>K++c{^|7<4P=2y(B{jJsQ0a#U;HTo4ZmWZYvI{+s;Td{Yzem%0*k#)vjpB zia;J&>}ICate44SFYY3vEelqStQWFihx%^vQ@Do(sOy7yR2@WNv7Y9I^yL=nZr3mb zXKV5t@=?-Sk|b{XMhA7ZGB@2hqsx}4xwCW!in#C zI@}scZlr3-NFJ@NFaJlhyfcw{k^vvtGl`N9xSo**rDW4S}i zM9{fMPWo%4wYDG~BZ18BD+}h|GQKc-g^{++3MY>}W_uq7jGHx{mwE9fZiPCoxN$+7 zrODGGJrOkcPQUB(FD5aoS4g~7#6NR^ma7-!>mHuJfY5kTe6PpNNKC9GGRiu^L31uG z$7v`*JknQHsYB!Tm_W{a32TM099djW%5e+j0Ve_ct}IM>XLF1Ap+YvcrLV=|CKo6S zb+9Nl3_YdKP6%Cxy@6TxZ>;4&nTneadr z_ES90ydCev)LV!dN=#(*f}|ZORFdvkYBni^aLbUk>BajeWIOcmHP#8S)*2U~QKI%S zyrLmtPqb&TphJ;>yAxri#;{uyk`JJqODDw%(Z=2`1uc}br^V%>j!gS)D*q*f_-qf8&D;W1dJgQMlaH5er zN2U<%Smb7==vE}dDI8K7cKz!vs^73o9f>2sgiTzWcwY|BMYHH5%Vn7#kiw&eItCqa zIkR2~Q}>X=Ar8W|^Ms41Fm8o6IB2_j60eOeBB1Br!boW7JnoeX6Gs)?7rW0^5psc- zjS16yb>dFn>KPOF;imD}e!enuIniFzv}n$m2#gCCv4jM#ArwlzZ$7@9&XkFxZ4n!V zj3dyiwW4Ki2QG{@i>yuZXQizw_OkZI^-3otXC{!(lUpJF33gI60ak;Uqitp74|B6I zgg{b=Iz}WkhCGj1M=hu4#Aw173YxIVbISaoc z-nLZC*6Tgivd5V`K%GxhBsp@SUU60-rfc$=wb>zdJzXS&-5(NRRodFk;Kxk!S(O(a0e7oY=E( zAyS;Ow?6Q&XA+cnkCb{28_1N8H#?J!*$MmIwLq^*T_9-z^&UE@A(z9oGYtFy6EZef LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/examples/nextjs-api-sales/public/vercel.svg b/examples/nextjs-api-sales/public/vercel.svg new file mode 100644 index 0000000000..fbf0e25a65 --- /dev/null +++ b/examples/nextjs-api-sales/public/vercel.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/examples/nextjs-api-sales/styles/global.sass b/examples/nextjs-api-sales/styles/global.sass new file mode 100644 index 0000000000..794e1ce4d8 --- /dev/null +++ b/examples/nextjs-api-sales/styles/global.sass @@ -0,0 +1,12 @@ +@charset "utf-8" + +// Import a Google Font +@import url('https://fonts.googleapis.com/css?family=Roboto:400,700') + +$family-sans-serif: "Roboto", sans-serif +//$grey-dark: color +//$grey-light: color +//$primary: color +//$link: color + +@import "../node_modules/bulma/bulma.sass" \ No newline at end of file diff --git a/examples/nextjs-api-sales/styles/home.module.css b/examples/nextjs-api-sales/styles/home.module.css new file mode 100644 index 0000000000..4906fe57f1 --- /dev/null +++ b/examples/nextjs-api-sales/styles/home.module.css @@ -0,0 +1,116 @@ +.container { + padding: 0 2rem; +} + +.main { + min-height: 100vh; + padding: 4rem 0; + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.footer { + display: flex; + flex: 1; + padding: 2rem 0; + border-top: 1px solid #eaeaea; + justify-content: center; + align-items: center; +} + +.footer a { + display: flex; + justify-content: center; + align-items: center; + flex-grow: 1; +} + +.title a { + color: #0070f3; + text-decoration: none; +} + +.title a:hover, +.title a:focus, +.title a:active { + text-decoration: underline; +} + +.title { + margin: 0; + line-height: 1.15; + font-size: 4rem; +} + +.title, +.description { + text-align: center; +} + +.description { + margin: 4rem 0; + line-height: 1.5; + font-size: 1.5rem; +} + +.code { + background: #fafafa; + border-radius: 5px; + padding: 0.75rem; + font-size: 1.1rem; + font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, + Bitstream Vera Sans Mono, Courier New, monospace; +} + +.grid { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + max-width: 800px; +} + +.card { + margin: 1rem; + padding: 1.5rem; + text-align: left; + color: inherit; + text-decoration: none; + border: 1px solid #eaeaea; + border-radius: 10px; + transition: color 0.15s ease, border-color 0.15s ease; + max-width: 300px; +} + +.card:hover, +.card:focus, +.card:active { + color: #0070f3; + border-color: #0070f3; +} + +.card h2 { + margin: 0 0 1rem 0; + font-size: 1.5rem; +} + +.card p { + margin: 0; + font-size: 1.25rem; + line-height: 1.5; +} + +.logo { + height: 1em; + margin-left: 0.5rem; +} + +@media (max-width: 600px) { +.grid { + width: 100%; + flex-direction: column; +} +} diff --git a/examples/nextjs-api-sales/tsconfig.json b/examples/nextjs-api-sales/tsconfig.json new file mode 100644 index 0000000000..99710e8578 --- /dev/null +++ b/examples/nextjs-api-sales/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/examples/nextjs-api-sales/yarn.lock b/examples/nextjs-api-sales/yarn.lock new file mode 100644 index 0000000000..d23f480c44 --- /dev/null +++ b/examples/nextjs-api-sales/yarn.lock @@ -0,0 +1,3042 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/runtime-corejs3@^7.10.2": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz#fdca2cd05fba63388babe85d349b6801b008fd13" + integrity sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg== + dependencies: + core-js-pure "^3.20.2" + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.10.2", "@babel/runtime@^7.16.3": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" + integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== + dependencies: + regenerator-runtime "^0.13.4" + +"@eslint/eslintrc@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a" + integrity sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.3.1" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@gar/promisify@^1.0.1": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== + +"@humanwhocodes/config-array@^0.9.2": + version "0.9.5" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" + integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@next/env@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.0.tgz#73713399399b34aa5a01771fb73272b55b22c314" + integrity sha512-nrIgY6t17FQ9xxwH3jj0a6EOiQ/WDHUos35Hghtr+SWN/ntHIQ7UpuvSi0vaLzZVHQWaDupKI+liO5vANcDeTQ== + +"@next/eslint-plugin-next@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.1.0.tgz#32586a11378b3ffa5a93ac40a3c44ad99d70e95a" + integrity sha512-WFiyvSM2G5cQmh32t/SiQuJ+I2O+FHVlK/RFw5b1565O2kEM/36EXncjt88Pa+X5oSc+1SS+tWxowWJd1lqI+g== + dependencies: + glob "7.1.7" + +"@next/swc-android-arm64@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.0.tgz#865ba3a9afc204ff2bdeea49dd64d58705007a39" + integrity sha512-/280MLdZe0W03stA69iL+v6I+J1ascrQ6FrXBlXGCsGzrfMaGr7fskMa0T5AhQIVQD4nA/46QQWxG//DYuFBcA== + +"@next/swc-darwin-arm64@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.0.tgz#08e8b411b8accd095009ed12efbc2f1d4d547135" + integrity sha512-R8vcXE2/iONJ1Unf5Ptqjk6LRW3bggH+8drNkkzH4FLEQkHtELhvcmJwkXcuipyQCsIakldAXhRbZmm3YN1vXg== + +"@next/swc-darwin-x64@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.0.tgz#fcd684497a76e8feaca88db3c394480ff0b007cd" + integrity sha512-ieAz0/J0PhmbZBB8+EA/JGdhRHBogF8BWaeqR7hwveb6SYEIJaDNQy0I+ZN8gF8hLj63bEDxJAs/cEhdnTq+ug== + +"@next/swc-linux-arm-gnueabihf@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.0.tgz#9ec6380a27938a5799aaa6035c205b3c478468a7" + integrity sha512-njUd9hpl6o6A5d08dC0cKAgXKCzm5fFtgGe6i0eko8IAdtAPbtHxtpre3VeSxdZvuGFh+hb0REySQP9T1ttkog== + +"@next/swc-linux-arm64-gnu@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.0.tgz#7f4196dff1049cea479607c75b81033ae2dbd093" + integrity sha512-OqangJLkRxVxMhDtcb7Qn1xjzFA3s50EIxY7mljbSCLybU+sByPaWAHY4px97ieOlr2y4S0xdPKkQ3BCAwyo6Q== + +"@next/swc-linux-arm64-musl@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.0.tgz#b445f767569cdc2dddee785ca495e1a88c025566" + integrity sha512-hB8cLSt4GdmOpcwRe2UzI5UWn6HHO/vLkr5OTuNvCJ5xGDwpPXelVkYW/0+C3g5axbDW2Tym4S+MQCkkH9QfWA== + +"@next/swc-linux-x64-gnu@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.0.tgz#67610e9be4fbc987de7535f1bcb17e45fe12f90e" + integrity sha512-OKO4R/digvrVuweSw/uBM4nSdyzsBV5EwkUeeG4KVpkIZEe64ZwRpnFB65bC6hGwxIBnTv5NMSnJ+0K/WmG78A== + +"@next/swc-linux-x64-musl@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.0.tgz#ea19a23db08a9f2e34ac30401f774cf7d1669d31" + integrity sha512-JohhgAHZvOD3rQY7tlp7NlmvtvYHBYgY0x5ZCecUT6eCCcl9lv6iV3nfu82ErkxNk1H893fqH0FUpznZ/H3pSw== + +"@next/swc-win32-arm64-msvc@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.0.tgz#eadf054fc412085659b98e145435bbba200b5283" + integrity sha512-T/3gIE6QEfKIJ4dmJk75v9hhNiYZhQYAoYm4iVo1TgcsuaKLFa+zMPh4056AHiG6n9tn2UQ1CFE8EoybEsqsSw== + +"@next/swc-win32-ia32-msvc@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.0.tgz#68faeae10c89f698bf9d28759172b74c9c21bda1" + integrity sha512-iwnKgHJdqhIW19H9PRPM9j55V6RdcOo6rX+5imx832BCWzkDbyomWnlzBfr6ByUYfhohb8QuH4hSGEikpPqI0Q== + +"@next/swc-win32-x64-msvc@12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.0.tgz#d27e7e76c87a460a4da99c5bfdb1618dcd6cd064" + integrity sha512-aBvcbMwuanDH4EMrL2TthNJy+4nP59Bimn8egqv6GHMVj0a44cU6Au4PjOhLNqEh9l+IpRGBqMTzec94UdC5xg== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@npmcli/fs@^1.0.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" + integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== + dependencies: + "@gar/promisify" "^1.0.1" + semver "^7.3.5" + +"@npmcli/move-file@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" + integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== + dependencies: + mkdirp "^1.0.4" + rimraf "^3.0.2" + +"@rushstack/eslint-patch@^1.0.8": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323" + integrity sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A== + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + +"@types/minimist@^1.2.0": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" + integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== + +"@types/node@17.0.21": + version "17.0.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" + integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== + +"@types/normalize-package-data@^2.4.0": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" + integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + +"@types/prop-types@*": + version "15.7.4" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" + integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + +"@types/react@17.0.39": + version "17.0.39" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce" + integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + +"@typescript-eslint/parser@^5.0.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.14.0.tgz#7c79f898aa3cff0ceee6f1d34eeed0f034fb9ef3" + integrity sha512-aHJN8/FuIy1Zvqk4U/gcO/fxeMKyoSv/rS46UXMXOJKVsLQ+iYPuXNbpbH7cBLcpSbmyyFbwrniLx5+kutu1pw== + dependencies: + "@typescript-eslint/scope-manager" "5.14.0" + "@typescript-eslint/types" "5.14.0" + "@typescript-eslint/typescript-estree" "5.14.0" + debug "^4.3.2" + +"@typescript-eslint/scope-manager@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.14.0.tgz#ea518962b42db8ed0a55152ea959c218cb53ca7b" + integrity sha512-LazdcMlGnv+xUc5R4qIlqH0OWARyl2kaP8pVCS39qSL3Pd1F7mI10DbdXeARcE62sVQE4fHNvEqMWsypWO+yEw== + dependencies: + "@typescript-eslint/types" "5.14.0" + "@typescript-eslint/visitor-keys" "5.14.0" + +"@typescript-eslint/types@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.14.0.tgz#96317cf116cea4befabc0defef371a1013f8ab11" + integrity sha512-BR6Y9eE9360LNnW3eEUqAg6HxS9Q35kSIs4rp4vNHRdfg0s+/PgHgskvu5DFTM7G5VKAVjuyaN476LCPrdA7Mw== + +"@typescript-eslint/typescript-estree@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.14.0.tgz#78b7f7385d5b6f2748aacea5c9b7f6ae62058314" + integrity sha512-QGnxvROrCVtLQ1724GLTHBTR0lZVu13izOp9njRvMkCBgWX26PKvmMP8k82nmXBRD3DQcFFq2oj3cKDwr0FaUA== + dependencies: + "@typescript-eslint/types" "5.14.0" + "@typescript-eslint/visitor-keys" "5.14.0" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/visitor-keys@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.14.0.tgz#1927005b3434ccd0d3ae1b2ecf60e65943c36986" + integrity sha512-yL0XxfzR94UEkjBqyymMLgCBdojzEuy/eim7N9/RIcTNxpJudAcqsU8eRyfzBbcEzGoPWfdM3AGak3cN08WOIw== + dependencies: + "@typescript-eslint/types" "5.14.0" + eslint-visitor-keys "^3.0.0" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.7.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + +agent-base@6, agent-base@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +agentkeepalive@^4.1.3: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" + integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA== + dependencies: + debug "^4.1.0" + depd "^1.1.2" + humanize-ms "^1.2.1" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +are-we-there-yet@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz#ba20bd6b553e31d62fc8c31bd23d22b95734390d" + integrity sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-query@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" + integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== + dependencies: + "@babel/runtime" "^7.10.2" + "@babel/runtime-corejs3" "^7.10.2" + +array-includes@^3.1.3, array-includes@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" + integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.flat@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + +array.prototype.flatmap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446" + integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.19.0" + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +ast-types-flow@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" + integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= + +async-foreach@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +axe-core@^4.3.5: + version "4.4.1" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413" + integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw== + +axobject-query@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" + integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +bulma@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.9.3.tgz#ddccb7436ebe3e21bf47afe01d3c43a296b70243" + integrity sha512-0d7GNW1PY4ud8TWxdNcP6Cc8Bu7MxcntD/RRLGWuiw/s0a9P+XlH/6QoOIrmbj6o8WWJzJYhytiu9nFjTszk1g== + +cacache@^15.2.0: + version "15.3.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" + integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== + dependencies: + "@npmcli/fs" "^1.0.0" + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^6.0.0" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^8.0.1" + tar "^6.0.2" + unique-filename "^1.1.1" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-keys@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-lite@^1.0.30001283: + version "1.0.30001314" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001314.tgz#65c7f9fb7e4594fca0a333bec1d8939662377596" + integrity sha512-0zaSO+TnCHtHJIbpLroX7nsD+vYuOVjl3uzFbJO1wMVbuveJA0RK2WcQA9ZUIOiO0/ArMiMgHJLxfEZhQiC0kw== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-support@^1.1.2, color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +core-js-pure@^3.20.2: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" + integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +csstype@^3.0.2: + version "3.0.11" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" + integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== + +damerau-levenshtein@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +depd@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +encoding@^0.1.12: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +err-code@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.19.0, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.1" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.1" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +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" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-next@12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.1.0.tgz#8ace680dc5207e6ab6c915f3989adec122f582e7" + integrity sha512-tBhuUgoDITcdcM7xFvensi9I5WTI4dnvH4ETGRg1U8ZKpXrZsWQFdOKIDzR3RLP5HR3xXrLviaMM4c3zVoE/pA== + dependencies: + "@next/eslint-plugin-next" "12.1.0" + "@rushstack/eslint-patch" "^1.0.8" + "@typescript-eslint/parser" "^5.0.0" + eslint-import-resolver-node "^0.3.4" + eslint-import-resolver-typescript "^2.4.0" + eslint-plugin-import "^2.25.2" + eslint-plugin-jsx-a11y "^6.5.1" + eslint-plugin-react "^7.27.0" + eslint-plugin-react-hooks "^4.3.0" + +eslint-import-resolver-node@^0.3.4, eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-import-resolver-typescript@^2.4.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz#07661966b272d14ba97f597b51e1a588f9722f0a" + integrity sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ== + dependencies: + debug "^4.3.1" + glob "^7.1.7" + is-glob "^4.0.1" + resolve "^1.20.0" + tsconfig-paths "^3.9.0" + +eslint-module-utils@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee" + integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== + dependencies: + debug "^3.2.7" + find-up "^2.1.0" + +eslint-plugin-import@^2.25.2: + version "2.25.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1" + integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA== + dependencies: + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.7.2" + has "^1.0.3" + is-core-module "^2.8.0" + is-glob "^4.0.3" + minimatch "^3.0.4" + object.values "^1.1.5" + resolve "^1.20.0" + tsconfig-paths "^3.12.0" + +eslint-plugin-jsx-a11y@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8" + integrity sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g== + dependencies: + "@babel/runtime" "^7.16.3" + aria-query "^4.2.2" + array-includes "^3.1.4" + ast-types-flow "^0.0.7" + axe-core "^4.3.5" + axobject-query "^2.2.0" + damerau-levenshtein "^1.0.7" + emoji-regex "^9.2.2" + has "^1.0.3" + jsx-ast-utils "^3.2.1" + language-tags "^1.0.5" + minimatch "^3.0.4" + +eslint-plugin-react-hooks@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" + integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== + +eslint-plugin-react@^7.27.0: + version "7.29.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.3.tgz#f4eab757f2756d25d6d4c2a58a9e20b004791f05" + integrity sha512-MzW6TuCnDOcta67CkpDyRfRsEVx9FNMDV8wZsDqe1luHPdGTrQIUaUXD27Ja3gHsdOIs/cXzNchWGlqm+qRVRg== + dependencies: + array-includes "^3.1.4" + array.prototype.flatmap "^1.2.5" + doctrine "^2.1.0" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.5" + object.fromentries "^2.0.5" + object.hasown "^1.1.0" + object.values "^1.1.5" + prop-types "^15.8.1" + resolve "^2.0.0-next.3" + semver "^6.3.0" + string.prototype.matchall "^4.0.6" + +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +eslint@8.10.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d" + integrity sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw== + dependencies: + "@eslint/eslintrc" "^1.2.0" + "@humanwhocodes/config-array" "^0.9.2" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^6.0.1" + globals "^13.6.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" + integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== + dependencies: + acorn "^8.7.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^3.3.0" + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.5" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +gauge@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.2.tgz#c3777652f542b6ef62797246e8c7caddecb32cc7" + integrity sha512-aSPRm2CvA9R8QyU5eXMFPd+cYkyxLsXHd2l5/FOH2V/eml//M04G6KZOmTap07O1PvEwNcl2NndyLfK8g3QrKA== + dependencies: + ansi-regex "^5.0.1" + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + +gaze@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" + integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== + dependencies: + globule "^1.0.0" + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@7.1.7, glob@~7.1.1: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.7: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.6.0, globals@^13.9.0: + version "13.12.1" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb" + integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw== + dependencies: + type-fest "^0.20.2" + +globby@^11.0.4: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +globule@^1.0.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.3.tgz#811919eeac1ab7344e905f2e3be80a13447973c2" + integrity sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg== + dependencies: + glob "~7.1.1" + lodash "~4.17.10" + minimatch "~3.0.2" + +graceful-fs@^4.2.6: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hosted-git-info@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== + dependencies: + lru-cache "^6.0.0" + +http-cache-semantics@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= + dependencies: + ms "^2.0.0" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +ip@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.8.0, is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-lambda@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" + integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= + +is-negative-zero@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-weakref@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +js-base64@^2.4.3: + version "2.6.4" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" + integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" + integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA== + dependencies: + array-includes "^3.1.3" + object.assign "^4.1.2" + +kind-of@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +language-subtag-registry@~0.3.2: + version "0.3.21" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" + integrity sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg== + +language-tags@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" + integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= + dependencies: + language-subtag-registry "~0.3.2" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash@^4.17.11, lodash@^4.17.15, lodash@~4.17.10: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-fetch-happen@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" + integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== + dependencies: + agentkeepalive "^4.1.3" + cacache "^15.2.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^6.0.0" + minipass "^3.1.3" + minipass-collect "^1.0.2" + minipass-fetch "^1.3.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.2" + promise-retry "^2.0.1" + socks-proxy-agent "^6.0.0" + ssri "^8.0.0" + +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + +map-obj@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== + +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize "^1.2.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +minimatch@^3.0.4, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@~3.0.2: + version "3.0.8" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" + integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== + dependencies: + brace-expansion "^1.1.7" + +minimist-options@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + +minimist@^1.2.0: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-fetch@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" + integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== + dependencies: + minipass "^3.1.0" + minipass-sized "^1.0.3" + minizlib "^2.0.0" + optionalDependencies: + encoding "^0.1.12" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass-sized@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" + integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: + version "3.1.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" + integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + dependencies: + yallist "^4.0.0" + +minizlib@^2.0.0, minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.0.0, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nan@^2.13.2: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + +nanoid@^3.1.30: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +next@12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/next/-/next-12.1.0.tgz#c33d753b644be92fc58e06e5a214f143da61dd5d" + integrity sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q== + dependencies: + "@next/env" "12.1.0" + caniuse-lite "^1.0.30001283" + postcss "8.4.5" + styled-jsx "5.0.0" + use-subscription "1.5.1" + optionalDependencies: + "@next/swc-android-arm64" "12.1.0" + "@next/swc-darwin-arm64" "12.1.0" + "@next/swc-darwin-x64" "12.1.0" + "@next/swc-linux-arm-gnueabihf" "12.1.0" + "@next/swc-linux-arm64-gnu" "12.1.0" + "@next/swc-linux-arm64-musl" "12.1.0" + "@next/swc-linux-x64-gnu" "12.1.0" + "@next/swc-linux-x64-musl" "12.1.0" + "@next/swc-win32-arm64-msvc" "12.1.0" + "@next/swc-win32-ia32-msvc" "12.1.0" + "@next/swc-win32-x64-msvc" "12.1.0" + +node-gyp@^8.4.1: + version "8.4.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" + integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.6" + make-fetch-happen "^9.1.0" + nopt "^5.0.0" + npmlog "^6.0.0" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.2" + which "^2.0.2" + +node-sass@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-7.0.1.tgz#ad4f6bc663de8acc0a9360db39165a1e2620aa72" + integrity sha512-uMy+Xt29NlqKCFdFRZyXKOTqGt+QaKHexv9STj2WeLottnlqZEEWx6Bj0MXNthmFRRdM/YwyNo/8Tr46TOM0jQ== + dependencies: + async-foreach "^0.1.3" + chalk "^4.1.2" + cross-spawn "^7.0.3" + gaze "^1.0.0" + get-stdin "^4.0.1" + glob "^7.0.3" + lodash "^4.17.15" + meow "^9.0.0" + nan "^2.13.2" + node-gyp "^8.4.1" + npmlog "^5.0.0" + request "^2.88.0" + sass-graph "4.0.0" + stdout-stream "^1.4.0" + "true-case-path" "^1.0.2" + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-package-data@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" + integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== + dependencies: + hosted-git-info "^4.0.1" + is-core-module "^2.5.0" + semver "^7.3.4" + validate-npm-package-license "^3.0.1" + +npmlog@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + +npmlog@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.1.tgz#06f1344a174c06e8de9c6c70834cfba2964bba17" + integrity sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.0" + set-blocking "^2.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-inspect@^1.11.0, object-inspect@^1.9.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.entries@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" + integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.fromentries@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" + integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.hasown@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5" + integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.values@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +postcss@8.4.5: + version "8.4.5" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" + integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== + dependencies: + nanoid "^3.1.30" + picocolors "^1.0.0" + source-map-js "^1.0.1" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +promise-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" + integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== + dependencies: + err-code "^2.0.2" + retry "^0.12.0" + +prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + +react-dom@17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" + integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler "^0.20.2" + +react-is@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react@17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" + integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +readable-stream@^2.0.1: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +regexp.prototype.flags@^1.3.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" + integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +request@^2.88.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.10.0, resolve@^1.20.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.3: + version "2.0.0-next.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" + integrity sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sass-graph@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-4.0.0.tgz#fff8359efc77b31213056dfd251d05dadc74c613" + integrity sha512-WSO/MfXqKH7/TS8RdkCX3lVkPFQzCgbqdGsmSKq6tlPU+GpGEsa/5aW18JqItnqh+lPtcjifqdZ/VmiILkKckQ== + dependencies: + glob "^7.0.0" + lodash "^4.17.11" + scss-tokenizer "^0.3.0" + yargs "^17.2.1" + +scheduler@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" + integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +scss-tokenizer@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.3.0.tgz#ef7edc3bc438b25cd6ffacf1aa5b9ad5813bf260" + integrity sha512-14Zl9GcbBvOT9057ZKjpz5yPOyUWG2ojd9D5io28wHRYsOrs7U95Q+KNL87+32p8rc+LvDpbu/i9ZYjM9Q+FsQ== + dependencies: + js-base64 "^2.4.3" + source-map "^0.7.1" + +"semver@2 || 3 || 4 || 5": + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.4, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks-proxy-agent@^6.0.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" + integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== + dependencies: + agent-base "^6.0.2" + debug "^4.3.1" + socks "^2.6.1" + +socks@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" + integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== + dependencies: + ip "^1.1.5" + smart-buffer "^4.2.0" + +source-map-js@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map@^0.7.1: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +ssri@^8.0.0, ssri@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" + integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== + dependencies: + minipass "^3.1.1" + +stdout-stream@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" + integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== + dependencies: + readable-stream "^2.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.matchall@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" + integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.3.1" + side-channel "^1.0.4" + +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +styled-jsx@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77" + integrity sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tar@^6.0.2, tar@^6.1.2: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +trim-newlines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" + integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== + +"true-case-path@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" + integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== + dependencies: + glob "^7.1.2" + +tsconfig-paths@^3.12.0, tsconfig-paths@^3.9.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7" + integrity sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typescript@4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" + integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== + +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +use-subscription@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" + integrity sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA== + dependencies: + object-assign "^4.1.1" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.2, wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^20.2.3: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.0.0: + version "21.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" + integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== + +yargs@^17.2.1: + version "17.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" + integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" From d8cb5bfd246f82704def4276f3bafc9a7953e62a Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 8 Mar 2022 14:14:57 +0000 Subject: [PATCH 016/171] Fix screen renaming when same route already exists --- packages/builder/cypress.json | 2 +- .../src/components/design/NavigationPanel/ScreenWizard.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/cypress.json b/packages/builder/cypress.json index edad1f39d3..3e4d4c4d1b 100644 --- a/packages/builder/cypress.json +++ b/packages/builder/cypress.json @@ -1,6 +1,6 @@ { "baseUrl": "http://localhost:4100", - "video": false, + "video": true, "projectId": "bmbemn", "env": { "PORT": "4100", diff --git a/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte b/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte index 76ee253e00..c30241868a 100644 --- a/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte @@ -93,7 +93,7 @@ return `/${url}-${suffix}` } else { const split = url.split("/") - return `/${split[0]}-${suffix}/${split.join("/")}` + return `/${split[0]}-${suffix}/${split.slice(1).join("/")}` } } From 5bef8849ca041c10baf349e89d681b0ff25cf0e7 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 8 Mar 2022 14:45:47 +0000 Subject: [PATCH 017/171] Remove cypress video flag again --- packages/builder/cypress.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/cypress.json b/packages/builder/cypress.json index 3e4d4c4d1b..edad1f39d3 100644 --- a/packages/builder/cypress.json +++ b/packages/builder/cypress.json @@ -1,6 +1,6 @@ { "baseUrl": "http://localhost:4100", - "video": true, + "video": false, "projectId": "bmbemn", "env": { "PORT": "4100", From c2d48bebd7100d7949de4555759de543a00b9256 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Tue, 8 Mar 2022 17:31:36 +0100 Subject: [PATCH 018/171] initial setup for google firebase integration --- .../DatasourceNavigator/icons/Firebase.svelte | 54 ++++++ .../DatasourceNavigator/icons/firebase.svg | 91 ++++++++++ .../DatasourceNavigator/icons/index.js | 2 + .../builder/src/constants/backend/index.js | 2 + packages/server/package.json | 1 + .../server/src/api/routes/public/index.ts | 4 +- packages/server/src/definitions/datasource.ts | 1 + packages/server/src/integrations/firebase.ts | 161 ++++++++++++++++++ packages/server/src/integrations/index.ts | 3 + 9 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 packages/builder/src/components/backend/DatasourceNavigator/icons/Firebase.svelte create mode 100644 packages/builder/src/components/backend/DatasourceNavigator/icons/firebase.svg create mode 100644 packages/server/src/integrations/firebase.ts diff --git a/packages/builder/src/components/backend/DatasourceNavigator/icons/Firebase.svelte b/packages/builder/src/components/backend/DatasourceNavigator/icons/Firebase.svelte new file mode 100644 index 0000000000..3a776a9217 --- /dev/null +++ b/packages/builder/src/components/backend/DatasourceNavigator/icons/Firebase.svelte @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/components/backend/DatasourceNavigator/icons/firebase.svg b/packages/builder/src/components/backend/DatasourceNavigator/icons/firebase.svg new file mode 100644 index 0000000000..dc569606ad --- /dev/null +++ b/packages/builder/src/components/backend/DatasourceNavigator/icons/firebase.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js b/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js index 350fccf73f..515f20a93b 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js +++ b/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js @@ -12,6 +12,7 @@ import Rest from "./Rest.svelte" import Budibase from "./Budibase.svelte" import Oracle from "./Oracle.svelte" import GoogleSheets from "./GoogleSheets.svelte" +import Firebase from "./Firebase.svelte" export default { BUDIBASE: Budibase, @@ -28,4 +29,5 @@ export default { REST: Rest, ORACLE: Oracle, GOOGLE_SHEETS: GoogleSheets, + FIREBASE: Firebase, } diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index 4d6a7e3884..9a623241ca 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -178,6 +178,7 @@ export const IntegrationTypes = { ORACLE: "ORACLE", INTERNAL: "INTERNAL", GOOGLE_SHEETS: "GOOGLE_SHEETS", + FIREBASE: "FIREBASE", } export const IntegrationNames = { @@ -195,6 +196,7 @@ export const IntegrationNames = { [IntegrationTypes.ORACLE]: "Oracle", [IntegrationTypes.INTERNAL]: "Internal", [IntegrationTypes.GOOGLE_SHEETS]: "Google Sheets", + [IntegrationTypes.FIREBASE]: "Firebase", } export const SchemaTypeOptions = [ diff --git a/packages/server/package.json b/packages/server/package.json index 30e21a7170..b80b99ab69 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -77,6 +77,7 @@ "@bull-board/api": "^3.7.0", "@bull-board/koa": "^3.7.0", "@elastic/elasticsearch": "7.10.0", + "@google-cloud/firestore": "^5.0.2", "@koa/router": "8.0.0", "@sendgrid/mail": "7.1.1", "@sentry/node": "^6.0.0", diff --git a/packages/server/src/api/routes/public/index.ts b/packages/server/src/api/routes/public/index.ts index 800eae6101..63a6946606 100644 --- a/packages/server/src/api/routes/public/index.ts +++ b/packages/server/src/api/routes/public/index.ts @@ -29,7 +29,7 @@ function getApiLimitPerSecond(): number { return parseInt(env.API_REQ_LIMIT_PER_SEC) } -if (!env.isTest()) { +/*if (!env.isTest()) { const REDIS_OPTS = getRedisOptions() RateLimit.defaultOptions({ store: new Stores.Redis({ @@ -42,7 +42,7 @@ if (!env.isTest()) { database: 1, }), }) -} +}*/ // rate limiting, allows for 2 requests per second const limiter = RateLimit.middleware({ interval: { sec: 1 }, diff --git a/packages/server/src/definitions/datasource.ts b/packages/server/src/definitions/datasource.ts index 6c8c8dc07d..208b2dc0a3 100644 --- a/packages/server/src/definitions/datasource.ts +++ b/packages/server/src/definitions/datasource.ts @@ -48,6 +48,7 @@ export enum SourceNames { REST = "REST", ORACLE = "ORACLE", GOOGLE_SHEETS = "GOOGLE_SHEETS", + FIREBASE = "FIREBASE", } export enum IncludeRelationships { diff --git a/packages/server/src/integrations/firebase.ts b/packages/server/src/integrations/firebase.ts new file mode 100644 index 0000000000..8bcf198b7d --- /dev/null +++ b/packages/server/src/integrations/firebase.ts @@ -0,0 +1,161 @@ +import { + DatasourceFieldTypes, + Integration, + QueryTypes, +} from "../definitions/datasource" +import { IntegrationBase } from "./base/IntegrationBase" +import { Firestore, WhereFilterOp } from "@google-cloud/firestore" + +module Firebase { + interface FirebaseConfig { + email: string + privateKey: string + projectId: string + } + + const SCHEMA: Integration = { + docs: "https://firebase.google.com/docs/firestore/quickstart", + friendlyName: "Firestore", + description: + "Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud.", + datasource: { + email: { + type: DatasourceFieldTypes.STRING, + required: true, + }, + privateKey: { + type: DatasourceFieldTypes.STRING, + required: true, + }, + projectId: { + type: DatasourceFieldTypes.STRING, + required: true, + }, + }, + query: { + create: { + type: QueryTypes.JSON, + }, + read: { + type: QueryTypes.JSON, + }, + update: { + type: QueryTypes.JSON, + }, + delete: { + type: QueryTypes.JSON, + }, + }, + extra: { + collection: { + displayName: "Collection", + type: DatasourceFieldTypes.STRING, + required: true, + }, + filter: { + displayName: "Filter query", + type: DatasourceFieldTypes.LIST, + required: false, + data: { + read: [ + "==", + "<", + "<=", + "==", + "!=", + ">=", + ">", + "array-contains", + "in", + "not-in", + "array-contains-any", + ], + }, + }, + queryValue: { + displayName: "Query value", + type: DatasourceFieldTypes.STRING, + required: false, + }, + }, + } + + class FirebaseIntegration implements IntegrationBase { + private config: FirebaseConfig + private db: Firestore + + constructor(config: FirebaseConfig) { + this.config = config + this.db = new Firestore({ + projectId: config.projectId, + credential: { + clientEmail: config.email, + privateKey: config.privateKey, + }, + }) + } + + async create(query: { json: object; extra: { [key: string]: string } }) { + try { + return await this.db.collection(query.extra.collection).add(query.json) + } catch (err) { + console.error("Error writing to Firestore", err) + throw err + } + } + + async read(query: { + field: string + opStr: WhereFilterOp + value: any + extra: { [key: string]: string } + }) { + try { + const snapshot = await this.db + .collection(query.extra.collection) + .where(query.field, query.opStr, query.value) + .get() + const result: any[] = [] + snapshot.forEach(doc => result.push(doc.data())) + + return result + } catch (err) { + console.error("Error querying Firestore", err) + throw err + } + } + + async update(query: { + id: string + json: object + extra: { [key: string]: string } + }) { + try { + return await this.db + .collection(query.extra.collection) + .doc(query.id) + .update(query.json) + } catch (err) { + console.error("Error writing to mongodb", err) + throw err + } + } + + async delete(query: { id: string; extra: { [key: string]: string } }) { + try { + return await this.db + .collection(query.extra.collection) + .doc(query.id) + .delete() + } catch (err) { + console.error("Error writing to mongodb", err) + throw err + } + } + } + + module.exports = { + schema: SCHEMA, + integration: FirebaseIntegration, + } +} diff --git a/packages/server/src/integrations/index.ts b/packages/server/src/integrations/index.ts index 00b00c25fb..07f3211fcb 100644 --- a/packages/server/src/integrations/index.ts +++ b/packages/server/src/integrations/index.ts @@ -10,6 +10,7 @@ const mysql = require("./mysql") const arangodb = require("./arangodb") const rest = require("./rest") const googlesheets = require("./googlesheets") +const firebase = require("./firebase") const { SourceNames } = require("../definitions/datasource") const environment = require("../environment") @@ -25,6 +26,7 @@ const DEFINITIONS = { [SourceNames.MYSQL]: mysql.schema, [SourceNames.ARANGODB]: arangodb.schema, [SourceNames.REST]: rest.schema, + [SourceNames.FIREBASE]: firebase.schema, } const INTEGRATIONS = { @@ -39,6 +41,7 @@ const INTEGRATIONS = { [SourceNames.MYSQL]: mysql.integration, [SourceNames.ARANGODB]: arangodb.integration, [SourceNames.REST]: rest.integration, + [SourceNames.FIREBASE]: firebase.integration, } // optionally add oracle integration if the oracle binary can be installed From b67b34928a415522253f9625e455df329aa70e8e Mon Sep 17 00:00:00 2001 From: Dean Date: Tue, 8 Mar 2022 16:41:21 +0000 Subject: [PATCH 019/171] Initial Commit for Issue/3819. World map component added and a small change to the Component draggable behaviour to accomodate it. --- .eslintrc.json | 3 + .../design/AppPreview/componentStructure.json | 3 +- packages/client/manifest.json | 76 +++++ packages/client/package.json | 2 + .../client/src/components/Component.svelte | 7 +- .../src/components/app/EmbeddedMap.svelte | 266 ++++++++++++++++++ .../src/components/app/EmbeddedMapControls.js | 192 +++++++++++++ packages/client/src/components/app/index.js | 1 + 8 files changed, 548 insertions(+), 2 deletions(-) create mode 100644 packages/client/src/components/app/EmbeddedMap.svelte create mode 100644 packages/client/src/components/app/EmbeddedMapControls.js diff --git a/.eslintrc.json b/.eslintrc.json index 4dc11c0d65..8f4f68036b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -28,5 +28,8 @@ ], "rules": { "no-self-assign": "off" + }, + "globals": { + "GeolocationPositionError": true } } diff --git a/packages/builder/src/components/design/AppPreview/componentStructure.json b/packages/builder/src/components/design/AppPreview/componentStructure.json index cacd70a89b..6873ae547d 100644 --- a/packages/builder/src/components/design/AppPreview/componentStructure.json +++ b/packages/builder/src/components/design/AppPreview/componentStructure.json @@ -82,7 +82,8 @@ "link", "icon", "embed", - "markdownviewer" + "markdownviewer", + "embeddedmap" ] } ] diff --git a/packages/client/manifest.json b/packages/client/manifest.json index d8e589588f..11c927700e 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2474,6 +2474,82 @@ } ] }, + "embeddedmap": { + "name": "Embedded Map", + "icon": "Location", + "styles": ["size"], + "editable": true, + "draggable": false, + "illegalChildren": [ + "section" + ], + "settings": [ + { + "type": "dataProvider", + "label": "Provider", + "key": "dataProvider" + }, + { + "type": "select", + "label": "Map Type", + "key": "mapType", + "options": [ + "Roadmap", + "Terrain", + "Satellite", + "Hybrid" + ], + "defaultValue": "Roadmap" + }, + { + "type": "boolean", + "label": "Enable Fullscreen", + "key": "fullScreenEnabled", + "defaultValue": true + }, + { + "type": "boolean", + "label": "Enabled Location", + "key": "locationEnabled", + "defaultValue": false + }, + { + "type": "boolean", + "label": "Enable Zoom", + "key": "zoomEnabled", + "defaultValue": true + }, + { + "type": "number", + "label": "Zoom Level (0-100)", + "key": "zoomLevel", + "defaultValue": 72, + "max" : 100, + "min" : 0 + }, + { + "type": "field", + "label": "Latitude Key", + "key": "latitudeKey" + }, + { + "type": "field", + "label": "Longitude Key", + "key": "longitudeKey" + }, + { + "type": "field", + "label": "Title Key", + "key": "titleKey" + }, + { + "type": "text", + "label": "Tile URL", + "key": "tileURL", + "defaultValue": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" + } + ] + }, "attachmentfield": { "name": "Attachment", "icon": "Attach", diff --git a/packages/client/package.json b/packages/client/package.json index 8772b9135f..16a2f34c8e 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -32,8 +32,10 @@ "@spectrum-css/vars": "^3.0.1", "apexcharts": "^3.22.1", "dayjs": "^1.10.5", + "leaflet": "^1.7.1", "regexparam": "^1.3.0", "rollup-plugin-polyfill-node": "^0.8.0", + "screenfull": "^6.0.1", "shortid": "^2.2.15", "svelte": "^3.38.2", "svelte-apexcharts": "^1.0.2", diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 78fff52426..e4176587ee 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -103,7 +103,12 @@ ($builderStore.previewType === "layout" || insideScreenslot) && !isBlock $: editing = editable && selected && $builderStore.editMode - $: draggable = !inDragPath && interactive && !isLayout && !isScreen + $: draggable = + !inDragPath && + interactive && + !isLayout && + !isScreen && + definition?.draggable !== false $: droppable = interactive && !isLayout && !isScreen // Empty components are those which accept children but do not have any. diff --git a/packages/client/src/components/app/EmbeddedMap.svelte b/packages/client/src/components/app/EmbeddedMap.svelte new file mode 100644 index 0000000000..63b98ba651 --- /dev/null +++ b/packages/client/src/components/app/EmbeddedMap.svelte @@ -0,0 +1,266 @@ + + +
+ {#if error} +
{error}
+ {/if} + +
+
+ + diff --git a/packages/client/src/components/app/EmbeddedMapControls.js b/packages/client/src/components/app/EmbeddedMapControls.js new file mode 100644 index 0000000000..ca1b1ed22a --- /dev/null +++ b/packages/client/src/components/app/EmbeddedMapControls.js @@ -0,0 +1,192 @@ +import L from "leaflet" +import screenfull from "screenfull" + +const createButton = function (html, title, className, container, fn) { + let link = L.DomUtil.create("a", className, container) + link.innerHTML = html + link.href = "#" + link.title = title + + link.setAttribute("role", "button") + link.setAttribute("aria-label", title) + + L.DomEvent.disableClickPropagation(link) + L.DomEvent.on(link, "click", L.DomEvent.stop) + L.DomEvent.on(link, "click", fn, this) + L.DomEvent.on(link, "click", this._refocusOnMap, this) + + return link +} + +// Full Screen Control + +const FullScreenControl = L.Control.extend({ + options: { + position: "topright", + fullScreenContent: + '' + + '' + + '', + fullScreenTitle: "Enter Fullscreen", + }, + onAdd: function () { + var fullScreenClassName = "leaflet-control-fullscreen", + container = L.DomUtil.create("div", fullScreenClassName + " leaflet-bar"), + options = this.options + + this._fullScreenButton = this._createButton( + options.fullScreenContent, + options.fullScreenTitle, + "map-fullscreen", + container, + this._fullScreen + ) + + return container + }, + _fullScreen: function () { + var map = this._map + if (screenfull.isEnabled) { + screenfull.toggle(map.getContainer()) + } + }, + _createButton: createButton, +}) + +const initFullScreenControl = () => { + L.Map.mergeOptions({ + fullScreen: false, + }) + + L.Map.addInitHook(function () { + if (this.options.fullScreen) { + this.fullScreenControl = new FullScreenControl() + this.addControl(this.fullScreenControl) + } else { + this.fullScreenControl = null + } + }) +} + +// Location Control + +const LocationControl = L.Control.extend({ + options: { + position: "topright", + locationContent: + '' + + '' + + '', + locationTitle: "Show Your Location", + }, + onAdd: function () { + var locationClassName = "leaflet-control-location", + container = L.DomUtil.create("div", locationClassName + " leaflet-bar"), + options = this.options + + this._locationButton = this._createButton( + options.locationContent, + options.locationTitle, + "map-location", + container, + this._location + ) + + this._updateDisabled() + + return container + }, + disable: function () { + this._disabled = true + this._updateDisabled() + return this + }, + enable: function () { + this._disabled = false + this._updateDisabled() + return this + }, + _location: function () { + if (this._disabled == true) { + return + } + this.disable() + + const success = pos => { + this._map.closePopup() + if (typeof this.options.onLocationSuccess === "function") { + this.options.onLocationSuccess({ + lat: pos.coords.latitude, + lng: pos.coords.longitude, + }) + } + } + + const error = err => { + if (typeof this.options.onLocationFail === "function") { + this.options.onLocationFail(err) + } + } + + this._getPosition() + .then(success) + .catch(error) + .finally(() => { + this.enable() + }) + }, + _getPosition: function () { + var options = { + enableHighAccuracy: false, + timeout: 5000, + maximumAge: 30000, + } + + return new Promise((resolve, reject) => { + navigator.geolocation.getCurrentPosition(resolve, reject, options) + }) + }, + + _createButton: createButton, + + _updateDisabled: function () { + let disabledClassName = "leaflet-disabled" + L.DomUtil.removeClass(this._locationButton, disabledClassName) + this._locationButton.setAttribute("aria-disabled", "false") + + if (this._disabled) { + L.DomUtil.addClass(this._locationButton, disabledClassName) + this._locationButton.setAttribute("aria-disabled", "true") + } + }, +}) + +const initLocationControl = () => { + L.Map.mergeOptions({ + location: false, + onLocationFail: null, + onLocationSuccess: null, + }) + + L.Map.addInitHook(function () { + if (this.options.location) { + this.localControl = new LocationControl() + this.addControl(this.LocationControl) + } else { + this.localControl = null + } + }) +} + +const initMapControls = () => { + initFullScreenControl() + initLocationControl() +} + +export { + initFullScreenControl, + initLocationControl, + initMapControls, + FullScreenControl, + LocationControl, +} diff --git a/packages/client/src/components/app/index.js b/packages/client/src/components/app/index.js index 5af62201e5..e23659620b 100644 --- a/packages/client/src/components/app/index.js +++ b/packages/client/src/components/app/index.js @@ -31,6 +31,7 @@ export { default as cardstat } from "./CardStat.svelte" export { default as spectrumcard } from "./SpectrumCard.svelte" export { default as tag } from "./Tag.svelte" export { default as markdownviewer } from "./MarkdownViewer.svelte" +export { default as embeddedmap } from "./EmbeddedMap.svelte" export * from "./charts" export * from "./forms" export * from "./table" From f78dce39505d4fbaa1a0d9556b55c047b45fb3a3 Mon Sep 17 00:00:00 2001 From: Dean Date: Tue, 8 Mar 2022 16:59:10 +0000 Subject: [PATCH 020/171] Added yarn lock files for Screenfull and LeafletJS --- packages/bbui/yarn.lock | 935 +--------------------------------------- 1 file changed, 6 insertions(+), 929 deletions(-) diff --git a/packages/bbui/yarn.lock b/packages/bbui/yarn.lock index 33c3c391be..5baad30282 100644 --- a/packages/bbui/yarn.lock +++ b/packages/bbui/yarn.lock @@ -28,43 +28,6 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@budibase/handlebars-helpers@^0.11.7": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.8.tgz#6953d29673a8c5c407e096c0a84890465c7ce841" - integrity sha512-ggWJUt0GqsHFAEup5tlWlcrmYML57nKhpNGGLzVsqXVYN8eVmf3xluYmmMe7fDYhQH0leSprrdEXmsdFQF3HAQ== - dependencies: - array-sort "^1.0.0" - define-property "^2.0.2" - extend-shallow "^3.0.2" - for-in "^1.0.2" - get-object "^0.2.0" - get-value "^3.0.1" - handlebars "^4.7.7" - handlebars-utils "^1.0.6" - has-value "^2.0.2" - helper-md "^0.2.2" - html-tag "^2.0.0" - is-even "^1.0.0" - is-glob "^4.0.1" - kind-of "^6.0.3" - micromatch "^3.1.5" - relative "^3.0.2" - striptags "^3.1.1" - to-gfm-code-block "^0.1.1" - year "^0.2.1" - -"@budibase/string-templates@^1.0.72-alpha.0": - version "1.0.75" - resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.75.tgz#5b4061f1a626160ec092f32f036541376298100c" - integrity sha512-hPgr6n5cpSCGFEha5DS/P+rtRXOLc72M6y4J/scl59JvUi/ZUJkjRgJdpQPdBLu04CNKp89V59+rAqAuDjOC0g== - dependencies: - "@budibase/handlebars-helpers" "^0.11.7" - dayjs "^1.10.4" - handlebars "^4.7.6" - handlebars-utils "^1.0.6" - lodash "^4.17.20" - vm2 "^3.9.4" - "@rollup/plugin-commonjs@^16.0.0": version "16.0.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz#169004d56cd0f0a1d0f35915d31a036b0efe281f" @@ -367,21 +330,11 @@ accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-walk@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - acorn@^7.3.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" @@ -409,87 +362,28 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -argparse@^1.0.10, argparse@^1.0.7: +argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= -array-sort@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" - integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== - dependencies: - default-compare "^1.0.0" - get-value "^2.0.6" - kind-of "^5.0.2" - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -autolinker@~0.28.0: - version "0.28.1" - resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-0.28.1.tgz#0652b491881879f0775dace0cdca3233942a4e47" - integrity sha1-BlK0kYgYefB3XazgzcoyM5QqTkc= - dependencies: - gulp-header "^1.7.1" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -529,22 +423,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -578,21 +456,6 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -672,16 +535,6 @@ chokidar@^3.0.0: optionalDependencies: fsevents "~2.3.1" -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - coa@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" @@ -703,14 +556,6 @@ codemirror@^5.63.1: resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.1.tgz#5988a812c974c467f964bcc1a00c944e373de502" integrity sha512-s6aac+DD+4O2u1aBmdxhB7yz2XU7tG3snOyQ05Kxifahz7hoxnfxIRHxiCSEv3TUC38dIVH8G+lZH9UWSfGQxA== -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -766,17 +611,12 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-with-sourcemaps@*, concat-with-sourcemaps@^1.1.0: +concat-with-sourcemaps@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== @@ -812,16 +652,6 @@ cookie@0.4.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - cosmiconfig@^5.0.0: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" @@ -993,7 +823,7 @@ dayjs@^1.10.4: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: +debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -1007,23 +837,11 @@ debug@^3.0.1: dependencies: ms "^2.1.1" -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== -default-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" - integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== - dependencies: - kind-of "^5.0.2" - define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -1031,28 +849,6 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -1127,11 +923,6 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -ent@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= - entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -1225,19 +1016,6 @@ eventemitter3@^4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - express-history-api-fallback@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/express-history-api-fallback/-/express-history-api-fallback-2.2.1.tgz#3a2ad27f7bebc90fc533d110d7c6d83097bcd057" @@ -1295,45 +1073,6 @@ express@^4.16.3: utils-merge "1.0.1" vary "~1.1.2" -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1359,33 +1098,16 @@ flatpickr@^4.5.2: resolved "https://registry.yarnpkg.com/flatpickr/-/flatpickr-4.6.9.tgz#9a13383e8a6814bda5d232eae3fcdccb97dc1499" integrity sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw== -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -fs-exists-sync@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" - integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1417,26 +1139,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" -get-object@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/get-object/-/get-object-0.2.0.tgz#d92ff7d5190c64530cda0543dac63a3d47fe8c0c" - integrity sha1-2S/31RkMZFMM2gVD2sY6PUf+jAw= - dependencies: - is-number "^2.0.2" - isobject "^0.2.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -get-value@^3.0.0, get-value@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-3.0.1.tgz#5efd2a157f1d6a516d7524e124ac52d0a39ef5a8" - integrity sha512-mKZj9JLQrwMBtj5wxi6MH8Z5eSKaERpAwjg43dPtlGI1ZVEgH/qC7T8/6R2OBSUA+zzHBZgICsVJaEIV2tKTDA== - dependencies: - isobject "^3.0.1" - glob-parent@~5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -1456,35 +1158,6 @@ glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -gulp-header@^1.7.1: - version "1.8.12" - resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-1.8.12.tgz#ad306be0066599127281c4f8786660e705080a84" - integrity sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ== - dependencies: - concat-with-sourcemaps "*" - lodash.template "^4.4.0" - through2 "^2.0.0" - -handlebars-utils@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/handlebars-utils/-/handlebars-utils-1.0.6.tgz#cb9db43362479054782d86ffe10f47abc76357f9" - integrity sha512-d5mmoQXdeEqSKMtQQZ9WkiUcO1E3tPbWxluCK9hVgIDPzQa9WsKo3Lbe/sGflTe7TomHEeZaOgwIkyIr1kfzkw== - dependencies: - kind-of "^6.0.0" - typeof-article "^0.1.1" - -handlebars@^4.7.6, handlebars@^4.7.7: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - has-bigints@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" @@ -1505,52 +1178,6 @@ has-symbols@^1.0.1, has-symbols@^1.0.2: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-value@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-2.0.2.tgz#d0f12e8780ba8e90e66ad1a21c707fdb67c25658" - integrity sha512-ybKOlcRsK2MqrM3Hmz/lQxXHZ6ejzSPzpNabKB45jb5qDgJvKPa3SdapTsTLwEb9WltgWpOmNax7i+DzNOk4TA== - dependencies: - get-value "^3.0.0" - has-values "^2.0.1" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has-values@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-2.0.1.tgz#3876200ff86d8a8546a9264a952c17d5fc17579d" - integrity sha512-+QdH3jOmq9P8GfdjFg0eJudqx1FqU62NQJ4P16rOEHeRdl7ckgwn6uqQjzYE0ZoHVV/e5E2esuJ5Gl5+HUW19w== - dependencies: - kind-of "^6.0.2" - has@^1.0.0, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1558,16 +1185,6 @@ has@^1.0.0, has@^1.0.3: dependencies: function-bind "^1.1.1" -helper-md@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/helper-md/-/helper-md-0.2.2.tgz#c1f59d7e55bbae23362fd8a0e971607aec69d41f" - integrity sha1-wfWdflW7riM2L9ig6XFgeuxp1B8= - dependencies: - ent "^2.2.0" - extend-shallow "^2.0.1" - fs-exists-sync "^0.1.0" - remarkable "^1.6.2" - hex-color-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" @@ -1583,14 +1200,6 @@ hsla-regex@^1.0.0: resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= -html-tag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/html-tag/-/html-tag-2.0.0.tgz#36c3bc8d816fd30b570d5764a497a641640c2fed" - integrity sha512-XxzooSo6oBoxBEUazgjdXj7VwTn/iSTSZzTYKzYY6I916tkaYzypHxy+pbVU1h+0UQ9JlVf5XkNQyxOAiiQO1g== - dependencies: - is-self-closing "^1.0.1" - kind-of "^6.0.0" - http-errors@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" @@ -1673,7 +1282,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@~2.0.3: +inherits@2, inherits@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1693,20 +1302,6 @@ is-absolute-url@^2.0.0: resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -1736,11 +1331,6 @@ is-boolean-object@^1.1.0: dependencies: call-bind "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-callable@^1.1.4, is-callable@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" @@ -1765,67 +1355,16 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - is-date-object@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= -is-even@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-even/-/is-even-1.0.0.tgz#76b5055fbad8d294a86b6a949015e1c97b717c06" - integrity sha1-drUFX7rY0pSoa2qUkBXhyXtxfAY= - dependencies: - is-odd "^0.1.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -1853,20 +1392,6 @@ is-number-object@^1.0.4: resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== -is-number@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -1877,20 +1402,6 @@ is-obj@^2.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== -is-odd@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-0.1.2.tgz#bc573b5ce371ef2aad6e6f49799b72bef13978a7" - integrity sha1-vFc7XONx7yqtbm9JeZtyvvE5eKc= - dependencies: - is-number "^3.0.0" - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - is-reference@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" @@ -1911,13 +1422,6 @@ is-resolvable@^1.0.0: resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== -is-self-closing@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-self-closing/-/is-self-closing-1.0.1.tgz#5f406b527c7b12610176320338af0fa3896416e4" - integrity sha512-E+60FomW7Blv5GXTlYee2KDrnG6srxF7Xt1SjrhWUGUEsTFIqY/nq2y3DaftCsgUMdh89V07IVfhY9KIJhLezg== - dependencies: - self-closing-tags "^1.0.1" - is-string@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" @@ -1930,38 +1434,11 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.1" -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isobject@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-0.2.0.tgz#a3432192f39b910b5f02cc989487836ec70aa85e" - integrity sha1-o0MhkvObkQtfAsyYlIeDbscKqF4= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - jest-worker@^26.2.1: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" @@ -2001,30 +1478,6 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0, kind-of@^5.0.2: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -2039,11 +1492,6 @@ loader-utils@^1.1.0: emojis-list "^3.0.0" json5 "^1.0.1" -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -2054,31 +1502,11 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.template@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.20: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - magic-string@^0.25.7: version "0.25.7" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" @@ -2086,18 +1514,6 @@ magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.4" -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - marked@^4.0.10: version "4.0.12" resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d" @@ -2133,25 +1549,6 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= -micromatch@^3.1.5: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - mime-db@1.47.0: version "1.47.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" @@ -2181,14 +1578,6 @@ minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -2216,33 +1605,11 @@ nanoid@^3.1.22: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.0.tgz#5906f776fd886c66c24f3653e0c46fcb1d4ad6b0" integrity sha512-JzxqqT5u/x+/KOFSd7JP15DOo9nOoHpx6DYatqIHUW2+flybkm+mdcraotSQR5WcnZr+qhGVh8Ted0KdfSMxlg== -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - node-releases@^1.1.71: version "1.1.73" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" @@ -2283,15 +1650,6 @@ nth-check@^1.0.2: dependencies: boolbase "~1.0.0" -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - object-inspect@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" @@ -2302,13 +1660,6 @@ object-keys@^1.0.12, object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" @@ -2328,13 +1679,6 @@ object.getownpropertydescriptors@^2.1.0: define-properties "^1.1.3" es-abstract "^1.18.0-next.2" -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - object.values@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.3.tgz#eaa8b1e17589f02f698db093f7c62ee1699742ee" @@ -2409,11 +1753,6 @@ parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -2449,11 +1788,6 @@ pify@^5.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - postcss-calc@^7.0.1: version "7.0.5" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" @@ -2797,11 +2131,6 @@ postcss@^8.2.9: nanoid "^3.1.22" source-map "^0.6.1" -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - promise.series@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/promise.series/-/promise.series-0.2.0.tgz#2cc7ebe959fc3a6619c04ab4dbdc9e452d864bbd" @@ -2857,19 +2186,6 @@ raw-body@^2.3.0: iconv-lite "0.4.24" unpipe "1.0.0" -readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - readdirp@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" @@ -2877,39 +2193,6 @@ readdirp@~3.5.0: dependencies: picomatch "^2.2.1" -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -relative@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/relative/-/relative-3.0.2.tgz#0dcd8ec54a5d35a3c15e104503d65375b5a5367f" - integrity sha1-Dc2OxUpdNaPBXhBFA9ZTdbWlNn8= - dependencies: - isobject "^2.0.0" - -remarkable@^1.6.2: - version "1.7.4" - resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.4.tgz#19073cb960398c87a7d6546eaa5e50d2022fcd00" - integrity sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg== - dependencies: - argparse "^1.0.10" - autolinker "~0.28.0" - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - require-relative@^0.8.7: version "0.8.7" resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" @@ -2930,11 +2213,6 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - resolve@^1.17.0, resolve@^1.19.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" @@ -2943,11 +2221,6 @@ resolve@^1.17.0, resolve@^1.19.0: is-core-module "^2.2.0" path-parse "^1.0.6" -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - rgb-regex@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" @@ -3009,7 +2282,7 @@ rollup@^2.45.2: optionalDependencies: fsevents "~2.3.1" -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -3024,13 +2297,6 @@ safe-identifier@^0.4.2: resolved "https://registry.yarnpkg.com/safe-identifier/-/safe-identifier-0.4.2.tgz#cf6bfca31c2897c588092d1750d30ef501d59fcb" integrity sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w== -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -3041,11 +2307,6 @@ sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -self-closing-tags@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/self-closing-tags/-/self-closing-tags-1.0.1.tgz#6c5fa497994bb826b484216916371accee490a5d" - integrity sha512-7t6hNbYMxM+VHXTgJmxwgZgLGktuXtVVD5AivWzNTdJBM4DBjnDKDzkf2SrNjihaArpeJYNjxkELBu1evI4lQA== - send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -3082,16 +2343,6 @@ serve-static@1.14.1: parseurl "~1.3.3" send "0.17.1" -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - setprototypeof@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" @@ -3116,53 +2367,12 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - "source-map-fast@npm:source-map@0.7.3", source-map@~0.7.2: name source-map-fast version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - source-map-support@~0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" @@ -3171,11 +2381,6 @@ source-map-support@~0.5.19: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -3191,13 +2396,6 @@ sourcemap-codec@^1.4.4: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -3208,14 +2406,6 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -3242,18 +2432,6 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -striptags@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.2.0.tgz#cc74a137db2de8b0b9a370006334161f7dd67052" - integrity sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw== - style-inject@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/style-inject/-/style-inject-0.3.0.tgz#d21c477affec91811cc82355832a700d22bf8dd3" @@ -3334,39 +2512,11 @@ terser@^5.0.0: source-map "~0.7.2" source-map-support "~0.5.19" -through2@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - timsort@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -to-gfm-code-block@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-gfm-code-block/-/to-gfm-code-block-0.1.1.tgz#25d045a5fae553189e9637b590900da732d8aa82" - integrity sha1-JdBFpfrlUxielje1kJANpzLYqoI= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3374,16 +2524,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" @@ -3397,23 +2537,11 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typeof-article@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/typeof-article/-/typeof-article-0.1.1.tgz#9f07e733c3fbb646ffa9e61c08debacd460e06af" - integrity sha1-nwfnM8P7tkb/qeYcCN66zUYOBq8= - dependencies: - kind-of "^3.1.0" - typo-js@*: version "1.2.1" resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.2.1.tgz#334a0d8c3f6c56f2f1e15fdf6c31677793cbbe9b" integrity sha512-bTGLjbD3WqZDR3CgEFkyi9Q/SS2oM29ipXrWfDb4M74ea69QwKAECVceYpaBu0GfdnASMg9Qfl67ttB23nePHg== -uglify-js@^3.1.4: - version "3.15.1" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.1.tgz#9403dc6fa5695a6172a91bc983ea39f0f7c9086d" - integrity sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ== - unbox-primitive@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" @@ -3424,16 +2552,6 @@ unbox-primitive@^1.0.0: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" @@ -3454,25 +2572,7 @@ unquote@~1.1.1: resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.2, util-deprecate@~1.0.1: +util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -3502,14 +2602,6 @@ vendors@^1.0.0: resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== -vm2@^3.9.4: - version "3.9.8" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.8.tgz#e99c000db042735cd2f94d8db6c42163a17be04e" - integrity sha512-/1PYg/BwdKzMPo8maOZ0heT7DLI0DAFTm7YQaz/Lim9oIaFZsJs3EdtalvXuBfZwczNwsYhju75NW4d6E+4q+w== - dependencies: - acorn "^8.7.0" - acorn-walk "^8.2.0" - which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -3528,11 +2620,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -3545,17 +2632,7 @@ ws@^5.2.0: dependencies: async-limiter "~1.0.0" -xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -year@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/year/-/year-0.2.1.tgz#4083ae520a318b23ec86037f3000cb892bdf9bb0" - integrity sha1-QIOuUgoxiyPshgN/MADLiSvfm7A= From 8051d6853c300f22c5db0a8487fb1c224c51535b Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 8 Mar 2022 17:29:49 +0000 Subject: [PATCH 021/171] Adding API communications to nextjs app. --- examples/nextjs-api-sales/README.md | 17 +- .../nextjs-api-sales/config/budibase.json | 5 + .../nextjs-api-sales/db/docker-compose.yml | 17 + examples/nextjs-api-sales/db/init.sql | 23 + .../nextjs-api-sales/definitions/index.ts | 7 + .../nextjs-api-sales/definitions/openapi.ts | 943 ++++++++++++++++++ examples/nextjs-api-sales/next.config.js | 9 +- examples/nextjs-api-sales/package.json | 1 + examples/nextjs-api-sales/pages/api/hello.ts | 13 - examples/nextjs-api-sales/pages/api/sales.ts | 66 ++ examples/nextjs-api-sales/yarn.lock | 39 + 11 files changed, 1109 insertions(+), 31 deletions(-) create mode 100644 examples/nextjs-api-sales/config/budibase.json create mode 100644 examples/nextjs-api-sales/db/docker-compose.yml create mode 100644 examples/nextjs-api-sales/db/init.sql create mode 100644 examples/nextjs-api-sales/definitions/index.ts create mode 100644 examples/nextjs-api-sales/definitions/openapi.ts delete mode 100644 examples/nextjs-api-sales/pages/api/hello.ts create mode 100644 examples/nextjs-api-sales/pages/api/sales.ts diff --git a/examples/nextjs-api-sales/README.md b/examples/nextjs-api-sales/README.md index c87e0421d2..328a299684 100644 --- a/examples/nextjs-api-sales/README.md +++ b/examples/nextjs-api-sales/README.md @@ -16,19 +16,4 @@ You can start editing the page by modifying `pages/index.tsx`. The page auto-upd [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. \ No newline at end of file diff --git a/examples/nextjs-api-sales/config/budibase.json b/examples/nextjs-api-sales/config/budibase.json new file mode 100644 index 0000000000..838c3ec419 --- /dev/null +++ b/examples/nextjs-api-sales/config/budibase.json @@ -0,0 +1,5 @@ +{ + "apiKey": "", + "appName": "", + "host": "http://localhost:10000" +} \ No newline at end of file diff --git a/examples/nextjs-api-sales/db/docker-compose.yml b/examples/nextjs-api-sales/db/docker-compose.yml new file mode 100644 index 0000000000..fdf189911f --- /dev/null +++ b/examples/nextjs-api-sales/db/docker-compose.yml @@ -0,0 +1,17 @@ +version: "3.8" +services: + db: + container_name: postgres + image: postgres + restart: always + environment: + POSTGRES_USER: root + POSTGRES_PASSWORD: root + POSTGRES_DB: postgres + ports: + - "5432:5432" + volumes: + - pg_data:/var/lib/postgresql/data/ + - ./init.sql:/docker-entrypoint-initdb.d/init.sql +volumes: + pg_data: diff --git a/examples/nextjs-api-sales/db/init.sql b/examples/nextjs-api-sales/db/init.sql new file mode 100644 index 0000000000..462d64ff30 --- /dev/null +++ b/examples/nextjs-api-sales/db/init.sql @@ -0,0 +1,23 @@ +CREATE TABLE IF NOT EXISTS sales_people ( + person_id INT NOT NULL, + name varchar(200) NOT NULL, + PRIMARY KEY (person_id) +); + +CREATE TABLE IF NOT EXISTS sales ( + sale_id INT NOT NULL, + sale_name varchar(200) NOT NULL, + sold_by INT, + PRIMARY KEY (sale_id), + CONSTRAINT sold_by_fk + FOREIGN KEY(sold_by) + REFERENCES sales_people(person_id) +); + +INSERT INTO sales_people +select id, concat('Sales person ', id) +FROM GENERATE_SERIES(1, 50) as id; + +INSERT INTO sales +select id, concat('Sale ', id), floor(random() * 50 + 1)::int +FROM GENERATE_SERIES(1, 200) as id; \ No newline at end of file diff --git a/examples/nextjs-api-sales/definitions/index.ts b/examples/nextjs-api-sales/definitions/index.ts new file mode 100644 index 0000000000..4eba86ca73 --- /dev/null +++ b/examples/nextjs-api-sales/definitions/index.ts @@ -0,0 +1,7 @@ +import { components } from "./openapi" + +export type App = components["schemas"]["applicationOutput"]["data"] +export type AppSearch = { + data: App[] +} +export type RowSearch = components["schemas"]["searchOutput"] \ No newline at end of file diff --git a/examples/nextjs-api-sales/definitions/openapi.ts b/examples/nextjs-api-sales/definitions/openapi.ts new file mode 100644 index 0000000000..71a9298040 --- /dev/null +++ b/examples/nextjs-api-sales/definitions/openapi.ts @@ -0,0 +1,943 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + "/applications": { + post: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the created application. */ + 200: { + content: { + "application/json": components["schemas"]["applicationOutput"] + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["application"] + } + } + } + } + "/applications/{appId}": { + get: { + parameters: { + path: { + /** The ID of the app which this request is targeting. */ + appId: components["parameters"]["appIdUrl"] + } + } + responses: { + /** Returns the retrieved application. */ + 200: { + content: { + "application/json": components["schemas"]["applicationOutput"] + } + } + } + } + put: { + parameters: { + path: { + /** The ID of the app which this request is targeting. */ + appId: components["parameters"]["appIdUrl"] + } + } + responses: { + /** Returns the updated application. */ + 200: { + content: { + "application/json": components["schemas"]["applicationOutput"] + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["application"] + } + } + } + delete: { + parameters: { + path: { + /** The ID of the app which this request is targeting. */ + appId: components["parameters"]["appIdUrl"] + } + } + responses: { + /** Returns the deleted application. */ + 200: { + content: { + "application/json": components["schemas"]["applicationOutput"] + } + } + } + } + } + "/applications/search": { + /** Based on application properties (currently only name) search for applications. */ + post: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the applications that were found based on the search parameters. */ + 200: { + content: { + "application/json": { + data: components["schemas"]["application"][] + } + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["nameSearch"] + } + } + } + } + "/queries/{queryId}": { + /** Queries which have been created within a Budibase app can be executed using this, */ + post: { + parameters: { + path: { + /** The ID of the query which this request is targeting. */ + queryId: components["parameters"]["queryId"] + } + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the result of the query execution. */ + 200: { + content: { + "application/json": components["schemas"]["executeQueryOutput"] + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["executeQuery"] + } + } + } + } + "/queries/search": { + /** Based on query properties (currently only name) search for queries. */ + post: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the queries found based on the search parameters. */ + 200: { + content: { + "application/json": { + data: components["schemas"]["query"][] + } + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["nameSearch"] + } + } + } + } + "/tables/{tableId}/rows": { + /** Creates a row within the specified table. */ + post: { + parameters: { + path: { + /** The ID of the table which this request is targeting. */ + tableId: components["parameters"]["tableId"] + } + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the created row, including the ID which has been generated for it. This can be found in the Budibase portal, viewed under the developer information. */ + 200: { + content: { + "application/json": components["schemas"]["rowOutput"] + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["row"] + } + } + } + } + "/tables/{tableId}/rows/{rowId}": { + /** This gets a single row, it will be enriched with the full related rows, rather than the squashed "primaryDisplay" format returned by the search endpoint. */ + get: { + parameters: { + path: { + /** The ID of the table which this request is targeting. */ + tableId: components["parameters"]["tableId"] + /** The ID of the row which this request is targeting. */ + rowId: components["parameters"]["rowId"] + } + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the retrieved row. */ + 200: { + content: { + "application/json": components["schemas"]["rowOutput"] + } + } + } + } + /** Updates a row within the specified table. */ + put: { + parameters: { + path: { + /** The ID of the table which this request is targeting. */ + tableId: components["parameters"]["tableId"] + /** The ID of the row which this request is targeting. */ + rowId: components["parameters"]["rowId"] + } + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the created row, including the ID which has been generated for it. */ + 200: { + content: { + "application/json": components["schemas"]["rowOutput"] + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["row"] + } + } + } + /** Deletes a row within the specified table. */ + delete: { + parameters: { + path: { + /** The ID of the table which this request is targeting. */ + tableId: components["parameters"]["tableId"] + /** The ID of the row which this request is targeting. */ + rowId: components["parameters"]["rowId"] + } + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the deleted row, including the ID which has been generated for it. */ + 200: { + content: { + "application/json": components["schemas"]["rowOutput"] + } + } + } + } + } + "/tables/{tableId}/rows/search": { + post: { + parameters: { + path: { + /** The ID of the table which this request is targeting. */ + tableId: components["parameters"]["tableId"] + } + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** The response will contain an array of rows that match the search parameters. */ + 200: { + content: { + "application/json": components["schemas"]["searchOutput"] + } + } + } + requestBody: { + content: { + "application/json": { + query: { + /** + * @description A map of field name to the string to search for, this will look for rows that have a value starting with the string value. + * @example [object Object] + */ + string?: { [key: string]: string } + /** @description A fuzzy search, only supported by internal tables. */ + fuzzy?: { [key: string]: unknown } + /** + * @description Searches within a range, the format of this must be columnName -> [low, high]. + * @example [object Object] + */ + range?: { [key: string]: unknown } + /** @description Searches for rows that have a column value that is exactly the value set. */ + equal?: { [key: string]: unknown } + /** @description Searches for any row which does not contain the specified column value. */ + notEqual?: { [key: string]: unknown } + /** + * @description Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value. + * @example [object Object] + */ + empty?: { [key: string]: unknown } + /** @description Searches for rows which have the specified column. */ + notEmpty?: { [key: string]: unknown } + /** @description Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2]. */ + oneOf?: { [key: string]: unknown } + } + /** @description Enables pagination, by default this is disabled. */ + paginate?: boolean + /** @description If retrieving another page, the bookmark from the previous request must be supplied. */ + bookmark?: string | number + /** @description The maximum number of rows to return, useful when paginating, for internal tables this will be limited to 1000, for SQL tables it will be 5000. */ + limit?: number + /** @description A set of parameters describing the sort behaviour of the search. */ + sort?: { + /** + * @description The order of the sort, by default this is ascending. + * @enum {string} + */ + order?: "ascending" | "descending" + /** @description The name of the column by which the rows will be sorted. */ + column?: string + /** + * @description Defines whether the column should be treated as a string or as numbers when sorting. + * @enum {string} + */ + type?: "string" | "number" + } + } + } + } + } + } + "/tables": { + /** Create a table, this could be internal or external. */ + post: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the created table, including the ID which has been generated for it. This can be internal or external data sources. */ + 200: { + content: { + "application/json": components["schemas"]["tableOutput"] + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["table"] + } + } + } + } + "/tables/{tableId}": { + /** Lookup a table, this could be internal or external. */ + get: { + parameters: { + path: { + /** The ID of the table which this request is targeting. */ + tableId: components["parameters"]["tableId"] + } + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the retrieved table. */ + 200: { + content: { + "application/json": components["schemas"]["tableOutput"] + } + } + } + } + /** Update a table, this could be internal or external. */ + put: { + parameters: { + path: { + /** The ID of the table which this request is targeting. */ + tableId: components["parameters"]["tableId"] + } + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the updated table. */ + 200: { + content: { + "application/json": components["schemas"]["tableOutput"] + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["table"] + } + } + } + /** Delete a table, this could be internal or external. */ + delete: { + parameters: { + path: { + /** The ID of the table which this request is targeting. */ + tableId: components["parameters"]["tableId"] + } + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the deleted table. */ + 200: { + content: { + "application/json": components["schemas"]["tableOutput"] + } + } + } + } + } + "/tables/search": { + /** Based on table properties (currently only name) search for tables. This could be an internal or an external table. */ + post: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"] + } + } + responses: { + /** Returns the found tables, based on the search parameters. */ + 200: { + content: { + "application/json": { + data: components["schemas"]["table"][] + } + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["nameSearch"] + } + } + } + } + "/users": { + post: { + responses: { + /** Returns the created user. */ + 200: { + content: { + "application/json": components["schemas"]["userOutput"] + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["user"] + } + } + } + } + "/users/{userId}": { + get: { + parameters: { + path: { + /** The ID of the user which this request is targeting. */ + userId: components["parameters"]["userId"] + } + } + responses: { + /** Returns the retrieved user. */ + 200: { + content: { + "application/json": components["schemas"]["userOutput"] + } + } + } + } + put: { + parameters: { + path: { + /** The ID of the user which this request is targeting. */ + userId: components["parameters"]["userId"] + } + } + responses: { + /** Returns the updated user. */ + 200: { + content: { + "application/json": components["schemas"]["userOutput"] + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["user"] + } + } + } + delete: { + parameters: { + path: { + /** The ID of the user which this request is targeting. */ + userId: components["parameters"]["userId"] + } + } + responses: { + /** Returns the deleted user. */ + 200: { + content: { + "application/json": components["schemas"]["userOutput"] + } + } + } + } + } + "/users/search": { + /** Based on user properties (currently only name) search for users. */ + post: { + responses: { + /** Returns the found users based on search parameters. */ + 200: { + content: { + "application/json": { + data: components["schemas"]["user"][] + } + } + } + } + requestBody: { + content: { + "application/json": components["schemas"]["nameSearch"] + } + } + } + } +} + +export interface components { + schemas: { + application: { + /** @description The name of the app. */ + name: string + /** @description The URL by which the app is accessed, this must be URL encoded. */ + url: string + } + applicationOutput: { + data: { + /** @description The name of the app. */ + name: string + /** @description The URL by which the app is accessed, this must be URL encoded. */ + url: string + /** @description The ID of the app. */ + _id: string + /** + * @description The status of the app, stating it if is the development or published version. + * @enum {string} + */ + status: "development" | "published" + /** @description States when the app was created, will be constant. Stored in ISO format. */ + createdAt: string + /** @description States the last time the app was updated - stored in ISO format. */ + updatedAt: string + /** @description States the version of the Budibase client this app is currently based on. */ + version: string + /** @description In a multi-tenant environment this will state the tenant this app is within. */ + tenantId?: string + /** @description The user this app is currently being built by. */ + lockedBy?: { [key: string]: unknown } + } + } + /** @description The row to be created/updated, based on the table schema. */ + row: { [key: string]: unknown } + searchOutput: { + /** @description An array of rows, these will each contain an _id field which can be used to update or delete them. */ + data: { [key: string]: unknown }[] + /** @description If pagination in use, this should be provided. */ + bookmark?: string | number + /** @description If pagination in use, this will determine if there is another page to fetch. */ + hasNextPage?: boolean + } + rowOutput: { + /** @description The row to be created/updated, based on the table schema. */ + data: { + /** @description The ID of the row. */ + _id: string + /** @description The ID of the table this row comes from. */ + tableId: string + } & { [key: string]: unknown } + } + /** @description The table to be created/updated. */ + table: { + /** @description The name of the table. */ + name: string + /** @description The name of the column which should be used in relationship tags when relating to this table. */ + primaryDisplay?: string + schema: { + [key: string]: + | { + /** + * @description A relationship column. + * @enum {string} + */ + type?: "link" + /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ + constraints?: { + /** @enum {string} */ + type?: "string" | "number" | "object" | "boolean" + /** @description Defines whether the column is required or not. */ + presence?: boolean + } + /** @description The name of the column. */ + name?: string + /** @description Defines whether the column is automatically generated. */ + autocolumn?: boolean + /** @description The name of the column which a relationship column is related to in another table. */ + fieldName?: string + /** @description The ID of the table which a relationship column is related to. */ + tableId?: string + /** + * @description Defines the type of relationship that this column will be used for. + * @enum {string} + */ + relationshipType?: "one-to-many" | "many-to-one" | "many-to-many" + /** @description When using a SQL table that contains many to many relationships this defines the table the relationships are linked through. */ + through?: string + /** @description When using a SQL table that contains a one to many relationship this defines the foreign key. */ + foreignKey?: string + /** @description When using a SQL table that utilises a through table, this defines the primary key in the through table for this table. */ + throughFrom?: string + /** @description When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table. */ + throughTo?: string + } + | { + /** + * @description A formula column. + * @enum {string} + */ + type?: "formula" + /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ + constraints?: { + /** @enum {string} */ + type?: "string" | "number" | "object" | "boolean" + /** @description Defines whether the column is required or not. */ + presence?: boolean + } + /** @description The name of the column. */ + name?: string + /** @description Defines whether the column is automatically generated. */ + autocolumn?: boolean + /** @description Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format. */ + formula?: string + /** + * @description Defines whether this is a static or dynamic formula. + * @enum {string} + */ + formulaType?: "static" | "dynamic" + } + | { + /** + * @description Defines the type of the column, most explain themselves, a link column is a relationship. + * @enum {string} + */ + type?: + | "string" + | "longform" + | "options" + | "number" + | "boolean" + | "array" + | "datetime" + | "attachment" + | "link" + | "formula" + | "auto" + | "json" + | "internal" + /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ + constraints?: { + /** @enum {string} */ + type?: "string" | "number" | "object" | "boolean" + /** @description Defines whether the column is required or not. */ + presence?: boolean + } + /** @description The name of the column. */ + name?: string + /** @description Defines whether the column is automatically generated. */ + autocolumn?: boolean + } + } + } + tableOutput: { + /** @description The table to be created/updated. */ + data: { + /** @description The name of the table. */ + name: string + /** @description The name of the column which should be used in relationship tags when relating to this table. */ + primaryDisplay?: string + schema: { + [key: string]: + | { + /** + * @description A relationship column. + * @enum {string} + */ + type?: "link" + /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ + constraints?: { + /** @enum {string} */ + type?: "string" | "number" | "object" | "boolean" + /** @description Defines whether the column is required or not. */ + presence?: boolean + } + /** @description The name of the column. */ + name?: string + /** @description Defines whether the column is automatically generated. */ + autocolumn?: boolean + /** @description The name of the column which a relationship column is related to in another table. */ + fieldName?: string + /** @description The ID of the table which a relationship column is related to. */ + tableId?: string + /** + * @description Defines the type of relationship that this column will be used for. + * @enum {string} + */ + relationshipType?: + | "one-to-many" + | "many-to-one" + | "many-to-many" + /** @description When using a SQL table that contains many to many relationships this defines the table the relationships are linked through. */ + through?: string + /** @description When using a SQL table that contains a one to many relationship this defines the foreign key. */ + foreignKey?: string + /** @description When using a SQL table that utilises a through table, this defines the primary key in the through table for this table. */ + throughFrom?: string + /** @description When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table. */ + throughTo?: string + } + | { + /** + * @description A formula column. + * @enum {string} + */ + type?: "formula" + /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ + constraints?: { + /** @enum {string} */ + type?: "string" | "number" | "object" | "boolean" + /** @description Defines whether the column is required or not. */ + presence?: boolean + } + /** @description The name of the column. */ + name?: string + /** @description Defines whether the column is automatically generated. */ + autocolumn?: boolean + /** @description Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format. */ + formula?: string + /** + * @description Defines whether this is a static or dynamic formula. + * @enum {string} + */ + formulaType?: "static" | "dynamic" + } + | { + /** + * @description Defines the type of the column, most explain themselves, a link column is a relationship. + * @enum {string} + */ + type?: + | "string" + | "longform" + | "options" + | "number" + | "boolean" + | "array" + | "datetime" + | "attachment" + | "link" + | "formula" + | "auto" + | "json" + | "internal" + /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ + constraints?: { + /** @enum {string} */ + type?: "string" | "number" | "object" | "boolean" + /** @description Defines whether the column is required or not. */ + presence?: boolean + } + /** @description The name of the column. */ + name?: string + /** @description Defines whether the column is automatically generated. */ + autocolumn?: boolean + } + } + /** @description The ID of the table. */ + _id: string + } + } + /** @description The query body must contain the required parameters for the query, this depends on query type, setup and bindings. */ + executeQuery: { [key: string]: unknown } + executeQueryOutput: { + /** @description The data response from the query. */ + data: { [key: string]: unknown }[] + /** @description Extra information that is not part of the main data, e.g. headers. */ + extra?: { + /** @description If carrying out a REST request, this will contain the response headers. */ + headers?: { [key: string]: unknown } + /** @description The raw query response, as a string. */ + raw?: string + } + /** @description If pagination is supported, this will contain the bookmark/anchor information for it. */ + pagination?: { [key: string]: unknown } + } + query: { + /** @description The ID of the query. */ + _id: string + /** @description The ID of the data source the query belongs to. */ + datasourceId?: string + /** @description The bindings which are required to perform this query. */ + parameters?: string[] + /** @description The fields that are used to perform this query, e.g. the sql statement */ + fields?: { [key: string]: unknown } + /** + * @description The verb that describes this query. + * @enum {undefined} + */ + queryVerb?: "create" | "read" | "update" | "delete" + /** @description The name of the query. */ + name: string + /** @description The schema of the data returned when the query is executed. */ + schema: { [key: string]: unknown } + /** @description The JavaScript transformer function, applied after the query responds with data. */ + transformer?: string + /** @description Whether the query has readable data. */ + readable?: boolean + } + user: { + /** @description The email address of the user, this must be unique. */ + email: string + /** @description The password of the user if using password based login - this will never be returned. This can be left out of subsequent requests (updates) and will be enriched back into the user structure. */ + password?: string + /** + * @description The status of the user, if they are active. + * @enum {string} + */ + status?: "active" + /** @description The first name of the user */ + firstName?: string + /** @description The last name of the user */ + lastName?: string + /** @description If set to true forces the user to reset their password on first login. */ + forceResetPassword?: boolean + /** @description Describes if the user is a builder user or not. */ + builder?: { + /** @description If set to true the user will be able to build any app in the system. */ + global?: boolean + } + /** @description Describes if the user is an admin user or not. */ + admin?: { + /** @description If set to true the user will be able to administrate the system. */ + global?: boolean + } + /** @description Contains the roles of the user per app (assuming they are not a builder user). */ + roles: { [key: string]: string } + } + userOutput: { + data: { + /** @description The email address of the user, this must be unique. */ + email: string + /** @description The password of the user if using password based login - this will never be returned. This can be left out of subsequent requests (updates) and will be enriched back into the user structure. */ + password?: string + /** + * @description The status of the user, if they are active. + * @enum {string} + */ + status?: "active" + /** @description The first name of the user */ + firstName?: string + /** @description The last name of the user */ + lastName?: string + /** @description If set to true forces the user to reset their password on first login. */ + forceResetPassword?: boolean + /** @description Describes if the user is a builder user or not. */ + builder?: { + /** @description If set to true the user will be able to build any app in the system. */ + global?: boolean + } + /** @description Describes if the user is an admin user or not. */ + admin?: { + /** @description If set to true the user will be able to administrate the system. */ + global?: boolean + } + /** @description Contains the roles of the user per app (assuming they are not a builder user). */ + roles: { [key: string]: string } + /** @description The ID of the user. */ + _id: string + } + } + nameSearch: { + /** @description The name to be used when searching - this will be used in a case insensitive starts with match. */ + name: string + } + } + parameters: { + /** @description The ID of the table which this request is targeting. */ + tableId: string + /** @description The ID of the row which this request is targeting. */ + rowId: string + /** @description The ID of the app which this request is targeting. */ + appId: string + /** @description The ID of the app which this request is targeting. */ + appIdUrl: string + /** @description The ID of the query which this request is targeting. */ + queryId: string + /** @description The ID of the user which this request is targeting. */ + userId: string + } +} + +export interface operations {} + +export interface external {} diff --git a/examples/nextjs-api-sales/next.config.js b/examples/nextjs-api-sales/next.config.js index 12c41deacd..61b35090e4 100644 --- a/examples/nextjs-api-sales/next.config.js +++ b/examples/nextjs-api-sales/next.config.js @@ -1,9 +1,14 @@ -const path = require("path") +const { join } = require("path") /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, sassOptions: { - includePaths: [path.join(__dirname, "styles")] + includePaths: [join(__dirname, "styles")] + }, + serverRuntimeConfig: { + apiKey: "", + appName: "", + host: "http://localhost:10000" } } diff --git a/examples/nextjs-api-sales/package.json b/examples/nextjs-api-sales/package.json index 4212ea6c5b..a278a3050a 100644 --- a/examples/nextjs-api-sales/package.json +++ b/examples/nextjs-api-sales/package.json @@ -11,6 +11,7 @@ "dependencies": { "bulma": "^0.9.3", "next": "12.1.0", + "node-fetch": "^3.2.2", "node-sass": "^7.0.1", "react": "17.0.2", "react-dom": "17.0.2" diff --git a/examples/nextjs-api-sales/pages/api/hello.ts b/examples/nextjs-api-sales/pages/api/hello.ts deleted file mode 100644 index f8bcc7e5ca..0000000000 --- a/examples/nextjs-api-sales/pages/api/hello.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from 'next' - -type Data = { - name: string -} - -export default function handler( - req: NextApiRequest, - res: NextApiResponse -) { - res.status(200).json({ name: 'John Doe' }) -} diff --git a/examples/nextjs-api-sales/pages/api/sales.ts b/examples/nextjs-api-sales/pages/api/sales.ts new file mode 100644 index 0000000000..41b9c0d08e --- /dev/null +++ b/examples/nextjs-api-sales/pages/api/sales.ts @@ -0,0 +1,66 @@ +import getConfig from "next/config" +import fetch from "node-fetch" +import { App, AppSearch, RowSearch } from "../../definitions" + +const { serverRuntimeConfig } = getConfig() +const apiKey = serverRuntimeConfig["apiKey"] +const appName = serverRuntimeConfig["appName"] +const host = serverRuntimeConfig["host"] + +async function makeCall(method: string, url: string, opts?: { body?: any, appId?: string } = {}): Promise { + const fetchOpts: any = { + method, + headers: { + "x-budibase-api-key": apiKey, + } + } + if (opts?.appId) { + fetchOpts.headers["x-budibase-app-id"] = opts.appId + } + if (opts?.body) { + fetchOpts.body = JSON.stringify(opts?.body) + fetchOpts.headers["Content-Type"] = "application/json" + } + const response = await fetch(`${host}/public/v1/${url}`, fetchOpts) + if (response.status === 200) { + return response.json() + } else { + throw new Error(await response.text()) + } +} + +async function getApp(): Promise { + const apps: AppSearch = await makeCall("post", "applications/search", { + body: { + name: appName, + } + }) + if (!Array.isArray(apps?.data)) { + throw new Error("Fatal error, no apps found.") + } + const app = apps.data.find((app: App) => app.name === appName) + if (!app) { + throw new Error("Could not find app, please make sure app name in config is correct.") + } + return app +} + +async function getSales(req: any) { + const { _id: appId } = await getApp() +} + +async function saveSale(req: any) { + const { _id: appId } = await getApp() +} + +export default async function handler(req: any, res: any) { + let response: any = {} + if (req.method === "POST") { + response = await saveSale(req) + } else if (req.method === "GET") { + response = await getSales(req) + } else { + res.status(404) + } + res.status(200).json(response) +} \ No newline at end of file diff --git a/examples/nextjs-api-sales/yarn.lock b/examples/nextjs-api-sales/yarn.lock index d23f480c44..b1a66a4ac5 100644 --- a/examples/nextjs-api-sales/yarn.lock +++ b/examples/nextjs-api-sales/yarn.lock @@ -673,6 +673,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-uri-to-buffer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" + integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== + debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" @@ -1098,6 +1103,14 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.1.4.tgz#e8c6567f80ad7fc22fd302e7dcb72bafde9c1717" + integrity sha512-Eq5Xv5+VlSrYWEqKrusxY1C3Hm/hjeAsCGVG3ft7pZahlUAChpGZT/Ms1WmSLnEAisEXszjzu/s+ce6HZB2VHA== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -1154,6 +1167,13 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -1995,6 +2015,20 @@ next@12.1.0: "@next/swc-win32-ia32-msvc" "12.1.0" "@next/swc-win32-x64-msvc" "12.1.0" +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.2.tgz#16d33fbe32ca7c6ca1ca8ba5dfea1dd885c59f04" + integrity sha512-Cwhq1JFIoon15wcIkFzubVNFE5GvXGV82pKf4knXXjvGmn7RJKcypeuqcVNZMGDZsAFWyIRya/anwAJr7TWJ7w== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-gyp@^8.4.1: version "8.4.1" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" @@ -2964,6 +2998,11 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +web-streams-polyfill@^3.0.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" + integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" From 990442b45e06614344ff728f26b25e1a1954720b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 8 Mar 2022 17:57:36 +0000 Subject: [PATCH 022/171] Add optional chaining to all current asset references to account for nullish values --- packages/builder/src/builderStore/dataBinding.js | 4 ++-- packages/builder/src/builderStore/index.js | 2 +- packages/builder/src/builderStore/store/frontend.js | 4 ++-- .../ComponentNavigationTree/ComponentDropdownMenu.svelte | 4 ++-- .../ButtonActionEditor/actions/S3Upload.svelte | 2 +- .../PropertyControls/DataProviderSelect.svelte | 2 +- .../PropertiesPanel/PropertyControls/FormFieldSelect.svelte | 2 +- .../PropertiesPanel/PropertyControls/ResetFieldsButton.svelte | 2 +- .../app/[application]/design/[assetType]/_layout.svelte | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 5b9bebcbf5..41174a9d9d 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -126,7 +126,7 @@ export const getDatasourceForProvider = (asset, component) => { if (dataProviderSetting) { const settingValue = component[dataProviderSetting.key] const providerId = extractLiteralHandlebarsID(settingValue) - const provider = findComponent(asset.props, providerId) + const provider = findComponent(asset?.props, providerId) return getDatasourceForProvider(asset, provider) } @@ -458,7 +458,7 @@ export const getSchemaForDatasource = (asset, datasource, options) => { // Determine the entity which backs this datasource. // "provider" datasources are those targeting another data provider if (type === "provider") { - const component = findComponent(asset.props, datasource.providerId) + const component = findComponent(asset?.props, datasource.providerId) const source = getDatasourceForProvider(asset, component) return getSchemaForDatasource(asset, source, options) } diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 5181e756c6..82556c74cf 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -25,7 +25,7 @@ export const selectedComponent = derived( if (!$currentAsset || !$store.selectedComponentId) { return null } - return findComponent($currentAsset.props, $store.selectedComponentId) + return findComponent($currentAsset?.props, $store.selectedComponentId) } ) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index c8e4c85b06..fd29414e3c 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -400,11 +400,11 @@ export const getFrontendStore = () => { parentComponent = selected } else { // Otherwise we need to use the parent of this component - parentComponent = findComponentParent(asset.props, selected._id) + parentComponent = findComponentParent(asset?.props, selected._id) } } else { // Use screen or layout if no component is selected - parentComponent = asset.props + parentComponent = asset?.props } // Attach component diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte index df6be7e88f..75601084a0 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte @@ -21,7 +21,7 @@ const moveUpComponent = () => { const asset = get(currentAsset) - const parent = findComponentParent(asset.props, component._id) + const parent = findComponentParent(asset?.props, component._id) if (!parent) { return } @@ -41,7 +41,7 @@ const moveDownComponent = () => { const asset = get(currentAsset) - const parent = findComponentParent(asset.props, component._id) + const parent = findComponentParent(asset?.props, component._id) if (!parent) { return } diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte index 76cccf58c5..2e374f165f 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte @@ -5,7 +5,7 @@ export let parameters - $: components = findAllMatchingComponents($currentAsset.props, component => + $: components = findAllMatchingComponents($currentAsset?.props, component => component._component.endsWith("s3upload") ) diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte index d7118fd3ec..a5b7a08255 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte @@ -10,7 +10,7 @@ const dispatch = createEventDispatcher() const getValue = component => `{{ literal ${makePropSafe(component._id)} }}` - $: path = findComponentPath($currentAsset.props, $store.selectedComponentId) + $: path = findComponentPath($currentAsset?.props, $store.selectedComponentId) $: providers = path.filter(c => c._component?.endsWith("/dataprovider")) // Set initial value to closest data provider diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte index 94a542480f..1f08c56ff5 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte @@ -12,7 +12,7 @@ export let type $: form = findClosestMatchingComponent( - $currentAsset.props, + $currentAsset?.props, componentInstance._id, component => component._component === "@budibase/standard-components/form" ) diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ResetFieldsButton.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ResetFieldsButton.svelte index a76a93d7f6..e927526b92 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ResetFieldsButton.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ResetFieldsButton.svelte @@ -11,7 +11,7 @@ const resetFormFields = async () => { const form = findClosestMatchingComponent( - $currentAsset.props, + $currentAsset?.props, componentInstance._id, component => component._component.endsWith("/form") ) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte index dc565e5f39..97697c7449 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte @@ -135,7 +135,7 @@ if (asset?._id) { url += `/${asset._id}` if (componentId) { - const componentPath = findComponentPath(asset.props, componentId) + const componentPath = findComponentPath(asset?.props, componentId) const componentURL = componentPath .slice(1) .map(comp => comp._id) From 4312e53464a775a4e891aca1d96e5653b326b7d3 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 8 Mar 2022 20:17:07 +0000 Subject: [PATCH 023/171] Adding in pagination to next frontend. --- .../nextjs-api-sales/definitions/index.ts | 6 +- .../nextjs-api-sales/definitions/openapi.ts | 206 +++++++++++++++++- examples/nextjs-api-sales/next.config.js | 4 +- examples/nextjs-api-sales/pages/api/sales.ts | 83 +++++-- examples/nextjs-api-sales/pages/index.tsx | 113 +++++----- 5 files changed, 317 insertions(+), 95 deletions(-) diff --git a/examples/nextjs-api-sales/definitions/index.ts b/examples/nextjs-api-sales/definitions/index.ts index 4eba86ca73..c84a893e81 100644 --- a/examples/nextjs-api-sales/definitions/index.ts +++ b/examples/nextjs-api-sales/definitions/index.ts @@ -1,7 +1,7 @@ import { components } from "./openapi" export type App = components["schemas"]["applicationOutput"]["data"] -export type AppSearch = { - data: App[] -} +export type Table = components["schemas"]["tableOutput"]["data"] +export type TableSearch = components["schemas"]["tableSearch"] +export type AppSearch = components["schemas"]["applicationSearch"] export type RowSearch = components["schemas"]["searchOutput"] \ No newline at end of file diff --git a/examples/nextjs-api-sales/definitions/openapi.ts b/examples/nextjs-api-sales/definitions/openapi.ts index 71a9298040..4f4ad45fc6 100644 --- a/examples/nextjs-api-sales/definitions/openapi.ts +++ b/examples/nextjs-api-sales/definitions/openapi.ts @@ -95,9 +95,7 @@ export interface paths { /** Returns the applications that were found based on the search parameters. */ 200: { content: { - "application/json": { - data: components["schemas"]["application"][] - } + "application/json": components["schemas"]["applicationSearch"] } } } @@ -149,9 +147,7 @@ export interface paths { /** Returns the queries found based on the search parameters. */ 200: { content: { - "application/json": { - data: components["schemas"]["query"][] - } + "application/json": components["schemas"]["querySearch"] } } } @@ -449,9 +445,7 @@ export interface paths { /** Returns the found tables, based on the search parameters. */ 200: { content: { - "application/json": { - data: components["schemas"]["table"][] - } + "application/json": components["schemas"]["tableSearch"] } } } @@ -541,9 +535,7 @@ export interface paths { /** Returns the found users based on search parameters. */ 200: { content: { - "application/json": { - data: components["schemas"]["user"][] - } + "application/json": components["schemas"]["userSearch"] } } } @@ -589,6 +581,31 @@ export interface components { lockedBy?: { [key: string]: unknown } } } + applicationSearch: { + data: { + /** @description The name of the app. */ + name: string + /** @description The URL by which the app is accessed, this must be URL encoded. */ + url: string + /** @description The ID of the app. */ + _id: string + /** + * @description The status of the app, stating it if is the development or published version. + * @enum {string} + */ + status: "development" | "published" + /** @description States when the app was created, will be constant. Stored in ISO format. */ + createdAt: string + /** @description States the last time the app was updated - stored in ISO format. */ + updatedAt: string + /** @description States the version of the Budibase client this app is currently based on. */ + version: string + /** @description In a multi-tenant environment this will state the tenant this app is within. */ + tenantId?: string + /** @description The user this app is currently being built by. */ + lockedBy?: { [key: string]: unknown } + }[] + } /** @description The row to be created/updated, based on the table schema. */ row: { [key: string]: unknown } searchOutput: { @@ -817,6 +834,113 @@ export interface components { _id: string } } + tableSearch: { + data: { + /** @description The name of the table. */ + name: string + /** @description The name of the column which should be used in relationship tags when relating to this table. */ + primaryDisplay?: string + schema: { + [key: string]: + | { + /** + * @description A relationship column. + * @enum {string} + */ + type?: "link" + /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ + constraints?: { + /** @enum {string} */ + type?: "string" | "number" | "object" | "boolean" + /** @description Defines whether the column is required or not. */ + presence?: boolean + } + /** @description The name of the column. */ + name?: string + /** @description Defines whether the column is automatically generated. */ + autocolumn?: boolean + /** @description The name of the column which a relationship column is related to in another table. */ + fieldName?: string + /** @description The ID of the table which a relationship column is related to. */ + tableId?: string + /** + * @description Defines the type of relationship that this column will be used for. + * @enum {string} + */ + relationshipType?: + | "one-to-many" + | "many-to-one" + | "many-to-many" + /** @description When using a SQL table that contains many to many relationships this defines the table the relationships are linked through. */ + through?: string + /** @description When using a SQL table that contains a one to many relationship this defines the foreign key. */ + foreignKey?: string + /** @description When using a SQL table that utilises a through table, this defines the primary key in the through table for this table. */ + throughFrom?: string + /** @description When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table. */ + throughTo?: string + } + | { + /** + * @description A formula column. + * @enum {string} + */ + type?: "formula" + /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ + constraints?: { + /** @enum {string} */ + type?: "string" | "number" | "object" | "boolean" + /** @description Defines whether the column is required or not. */ + presence?: boolean + } + /** @description The name of the column. */ + name?: string + /** @description Defines whether the column is automatically generated. */ + autocolumn?: boolean + /** @description Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format. */ + formula?: string + /** + * @description Defines whether this is a static or dynamic formula. + * @enum {string} + */ + formulaType?: "static" | "dynamic" + } + | { + /** + * @description Defines the type of the column, most explain themselves, a link column is a relationship. + * @enum {string} + */ + type?: + | "string" + | "longform" + | "options" + | "number" + | "boolean" + | "array" + | "datetime" + | "attachment" + | "link" + | "formula" + | "auto" + | "json" + | "internal" + /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ + constraints?: { + /** @enum {string} */ + type?: "string" | "number" | "object" | "boolean" + /** @description Defines whether the column is required or not. */ + presence?: boolean + } + /** @description The name of the column. */ + name?: string + /** @description Defines whether the column is automatically generated. */ + autocolumn?: boolean + } + } + /** @description The ID of the table. */ + _id: string + }[] + } /** @description The query body must contain the required parameters for the query, this depends on query type, setup and bindings. */ executeQuery: { [key: string]: unknown } executeQueryOutput: { @@ -855,6 +979,31 @@ export interface components { /** @description Whether the query has readable data. */ readable?: boolean } + querySearch: { + data: { + /** @description The ID of the query. */ + _id: string + /** @description The ID of the data source the query belongs to. */ + datasourceId?: string + /** @description The bindings which are required to perform this query. */ + parameters?: string[] + /** @description The fields that are used to perform this query, e.g. the sql statement */ + fields?: { [key: string]: unknown } + /** + * @description The verb that describes this query. + * @enum {undefined} + */ + queryVerb?: "create" | "read" | "update" | "delete" + /** @description The name of the query. */ + name: string + /** @description The schema of the data returned when the query is executed. */ + schema: { [key: string]: unknown } + /** @description The JavaScript transformer function, applied after the query responds with data. */ + transformer?: string + /** @description Whether the query has readable data. */ + readable?: boolean + }[] + } user: { /** @description The email address of the user, this must be unique. */ email: string @@ -917,6 +1066,39 @@ export interface components { _id: string } } + userSearch: { + data: { + /** @description The email address of the user, this must be unique. */ + email: string + /** @description The password of the user if using password based login - this will never be returned. This can be left out of subsequent requests (updates) and will be enriched back into the user structure. */ + password?: string + /** + * @description The status of the user, if they are active. + * @enum {string} + */ + status?: "active" + /** @description The first name of the user */ + firstName?: string + /** @description The last name of the user */ + lastName?: string + /** @description If set to true forces the user to reset their password on first login. */ + forceResetPassword?: boolean + /** @description Describes if the user is a builder user or not. */ + builder?: { + /** @description If set to true the user will be able to build any app in the system. */ + global?: boolean + } + /** @description Describes if the user is an admin user or not. */ + admin?: { + /** @description If set to true the user will be able to administrate the system. */ + global?: boolean + } + /** @description Contains the roles of the user per app (assuming they are not a builder user). */ + roles: { [key: string]: string } + /** @description The ID of the user. */ + _id: string + }[] + } nameSearch: { /** @description The name to be used when searching - this will be used in a case insensitive starts with match. */ name: string diff --git a/examples/nextjs-api-sales/next.config.js b/examples/nextjs-api-sales/next.config.js index 61b35090e4..335db3d3fe 100644 --- a/examples/nextjs-api-sales/next.config.js +++ b/examples/nextjs-api-sales/next.config.js @@ -6,8 +6,8 @@ const nextConfig = { includePaths: [join(__dirname, "styles")] }, serverRuntimeConfig: { - apiKey: "", - appName: "", + apiKey: "bf4d86af933b5ac0af0fdbe4bf7d89ff-f929752a1eeaafb00f4b5e3325097d51a44fe4b39f22ed857923409cc75414b379323a25ebfb4916", + appName: "sales", host: "http://localhost:10000" } } diff --git a/examples/nextjs-api-sales/pages/api/sales.ts b/examples/nextjs-api-sales/pages/api/sales.ts index 41b9c0d08e..0700711e88 100644 --- a/examples/nextjs-api-sales/pages/api/sales.ts +++ b/examples/nextjs-api-sales/pages/api/sales.ts @@ -1,13 +1,15 @@ import getConfig from "next/config" -import fetch from "node-fetch" -import { App, AppSearch, RowSearch } from "../../definitions" +import {App, AppSearch, Table, TableSearch} from "../../definitions" const { serverRuntimeConfig } = getConfig() const apiKey = serverRuntimeConfig["apiKey"] const appName = serverRuntimeConfig["appName"] const host = serverRuntimeConfig["host"] -async function makeCall(method: string, url: string, opts?: { body?: any, appId?: string } = {}): Promise { +let APP: App | null = null +let TABLES: { [key: string]: Table } = {} + +async function makeCall(method: string, url: string, opts?: { body?: any, appId?: string }): Promise { const fetchOpts: any = { method, headers: { @@ -18,49 +20,96 @@ async function makeCall(method: string, url: string, opts?: { body?: any, appId? fetchOpts.headers["x-budibase-app-id"] = opts.appId } if (opts?.body) { - fetchOpts.body = JSON.stringify(opts?.body) + fetchOpts.body = typeof opts.body !== "string" ? JSON.stringify(opts.body) : opts.body fetchOpts.headers["Content-Type"] = "application/json" } - const response = await fetch(`${host}/public/v1/${url}`, fetchOpts) - if (response.status === 200) { + const finalUrl = `${host}/api/public/v1/${url}` + const response = await fetch(finalUrl, fetchOpts) + if (response.ok) { return response.json() } else { - throw new Error(await response.text()) + const error = await response.text() + console.error("Budibase server error - ", error) + throw new Error(error) } } async function getApp(): Promise { + if (APP) { + return APP + } const apps: AppSearch = await makeCall("post", "applications/search", { body: { name: appName, } }) - if (!Array.isArray(apps?.data)) { - throw new Error("Fatal error, no apps found.") - } const app = apps.data.find((app: App) => app.name === appName) if (!app) { throw new Error("Could not find app, please make sure app name in config is correct.") } + APP = app return app } +async function findTable(appId: string, tableName: string): Promise { + if (TABLES[tableName]) { + return TABLES[tableName] + } + const tables: TableSearch = await makeCall("post", "tables/search", { + body: { + name: tableName, + }, + appId, + }) + const table = tables.data.find((table: Table) => table.name === tableName) + if (!table) { + throw new Error("Could not find table, please make sure your app is configured with the Postgres datasource correctly.") + } + TABLES[tableName] = table + return table +} + async function getSales(req: any) { + const { page } = req.query const { _id: appId } = await getApp() + const table = await findTable(appId, "sales") + return await makeCall("post", `tables/${table._id}/rows/search`, { + appId, + body: { + limit: 10, + sort: { + type: "string", + order: "ascending", + column: "sale_id", + }, + paginate: true, + bookmark: parseInt(page), + } + }) } async function saveSale(req: any) { const { _id: appId } = await getApp() + const table = await findTable(appId, "sales") + return await makeCall("post", `tables/${table._id}/rows`, { + body: req.body, + appId, + }) } export default async function handler(req: any, res: any) { let response: any = {} - if (req.method === "POST") { - response = await saveSale(req) - } else if (req.method === "GET") { - response = await getSales(req) - } else { - res.status(404) + try { + if (req.method === "POST") { + response = await saveSale(req) + } else if (req.method === "GET") { + response = await getSales(req) + } else { + res.status(404) + return + } + res.status(200).json(response) + } catch (err: any) { + res.status(400).send(err) } - res.status(200).json(response) } \ No newline at end of file diff --git a/examples/nextjs-api-sales/pages/index.tsx b/examples/nextjs-api-sales/pages/index.tsx index 7b0ab6aebe..84debb998c 100644 --- a/examples/nextjs-api-sales/pages/index.tsx +++ b/examples/nextjs-api-sales/pages/index.tsx @@ -1,70 +1,61 @@ import type { NextPage } from "next" -import Head from "next/head" -import Image from "next/image" import styles from "../styles/home.module.css" +import { useState, useEffect } from "react" const Home: NextPage = () => { + const [sales, setSales] = useState([]) + const [currentPage, setCurrentPage] = useState(1) + + const getSales = async (page: Number = 1) => { + let url = "/api/sales" + if (page) { + url += `?page=${page}` + } + const response = await fetch(url) + if (!response.ok) { + throw new Error(await response.text()) + } + const sales = await response.json() + // @ts-ignore + setCurrentPage(page) + return setSales(sales.data) + } + + const saveSale = async () => { + const response = await fetch("/api/sales", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({}), + }) + if (!response.ok) { + throw new Error(await response.text()) + } + } + + const goToNextPage = async () => { + await getSales(currentPage + 1) + } + + const goToPrevPage = async () => { + if (currentPage > 1) { + await getSales(currentPage - 1) + } + } + + useEffect(() => { + getSales().catch(() => { + setSales([]) + }) + }, []) + return ( ) } From c1efc455ed371c030690f4e6bd80305a9a692a7c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 8 Mar 2022 20:18:11 +0000 Subject: [PATCH 024/171] Fixing heading. --- examples/nextjs-api-sales/pages/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nextjs-api-sales/pages/index.tsx b/examples/nextjs-api-sales/pages/index.tsx index 84debb998c..1c4b450b53 100644 --- a/examples/nextjs-api-sales/pages/index.tsx +++ b/examples/nextjs-api-sales/pages/index.tsx @@ -52,7 +52,7 @@ const Home: NextPage = () => { return (
-

Sales

+

Sales

{sales.map((sale: any) =>

{sale.sale_id}

)}
From 3b9b4d92772f8ebc61c505d929c4b5d8a39868fd Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 9 Mar 2022 09:23:20 +0000 Subject: [PATCH 025/171] Removed unused map property definition --- packages/client/manifest.json | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 11c927700e..c7f25f8270 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2489,18 +2489,6 @@ "label": "Provider", "key": "dataProvider" }, - { - "type": "select", - "label": "Map Type", - "key": "mapType", - "options": [ - "Roadmap", - "Terrain", - "Satellite", - "Hybrid" - ], - "defaultValue": "Roadmap" - }, { "type": "boolean", "label": "Enable Fullscreen", From 2560bec3e841417f221d5ffc8e46878220ce9f68 Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 9 Mar 2022 10:28:55 +0000 Subject: [PATCH 026/171] Screenfull and leafletjs additions --- packages/client/yarn.lock | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/client/yarn.lock b/packages/client/yarn.lock index 54d3ae755f..d87edfcc7b 100644 --- a/packages/client/yarn.lock +++ b/packages/client/yarn.lock @@ -684,6 +684,11 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" +leaflet@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.7.1.tgz#10d684916edfe1bf41d688a3b97127c0322a2a19" + integrity sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw== + lilconfig@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" @@ -1252,6 +1257,11 @@ safe-identifier@^0.4.2: resolved "https://registry.yarnpkg.com/safe-identifier/-/safe-identifier-0.4.2.tgz#cf6bfca31c2897c588092d1750d30ef501d59fcb" integrity sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w== +screenfull@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-6.0.1.tgz#3b71e6f06b72d817a8d3be73c45ebe71fa8da1ce" + integrity sha512-yzQW+j4zMUBQC51xxWaoDYjxOtl8Kn+xvue3p6v/fv2pIi1jH4AldgVLU8TBfFVgH2x3VXlf3+YiA/AYIPlaew== + serialize-javascript@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" From 05352703b9d8105103075f2ef587962abd23411a Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 9 Mar 2022 15:00:36 +0000 Subject: [PATCH 027/171] Final version of example, has save form and table of sales, supporting relationships and pagination all from Postgres. --- .../nextjs-api-sales/components/layout.tsx | 43 +++++++ .../components/notifications.ts | 28 +++++ examples/nextjs-api-sales/components/utils.ts | 70 +++++++++++ examples/nextjs-api-sales/db/init.sql | 18 ++- examples/nextjs-api-sales/package.json | 3 +- examples/nextjs-api-sales/pages/_app.tsx | 7 +- examples/nextjs-api-sales/pages/api/sales.ts | 73 +---------- .../nextjs-api-sales/pages/api/salespeople.ts | 31 +++++ examples/nextjs-api-sales/pages/index.tsx | 72 +++++++---- examples/nextjs-api-sales/pages/save.tsx | 81 ++++++++++++ .../nextjs-api-sales/public/bb-emblem.svg | 80 ++++++++++++ examples/nextjs-api-sales/public/vercel.svg | 4 - examples/nextjs-api-sales/styles/global.sass | 27 ++-- .../nextjs-api-sales/styles/home.module.css | 118 +++--------------- .../nextjs-api-sales/styles/save.module.css | 20 +++ examples/nextjs-api-sales/yarn.lock | 5 + 16 files changed, 458 insertions(+), 222 deletions(-) create mode 100644 examples/nextjs-api-sales/components/layout.tsx create mode 100644 examples/nextjs-api-sales/components/notifications.ts create mode 100644 examples/nextjs-api-sales/components/utils.ts create mode 100644 examples/nextjs-api-sales/pages/api/salespeople.ts create mode 100644 examples/nextjs-api-sales/pages/save.tsx create mode 100644 examples/nextjs-api-sales/public/bb-emblem.svg delete mode 100644 examples/nextjs-api-sales/public/vercel.svg create mode 100644 examples/nextjs-api-sales/styles/save.module.css diff --git a/examples/nextjs-api-sales/components/layout.tsx b/examples/nextjs-api-sales/components/layout.tsx new file mode 100644 index 0000000000..63049af025 --- /dev/null +++ b/examples/nextjs-api-sales/components/layout.tsx @@ -0,0 +1,43 @@ +import Link from "next/link" +import Image from "next/image" +import { ReactNotifications } from "react-notifications-component" + +function layout(props: any) { + return ( + <> + + + {props.children} + + ) +} + +export default layout \ No newline at end of file diff --git a/examples/nextjs-api-sales/components/notifications.ts b/examples/nextjs-api-sales/components/notifications.ts new file mode 100644 index 0000000000..6e528dfeaa --- /dev/null +++ b/examples/nextjs-api-sales/components/notifications.ts @@ -0,0 +1,28 @@ +import { Store } from "react-notifications-component" + +const notifications = { + error: (error: string, title: string) => { + Store.addNotification({ + container: "top-right", + type: "danger", + message: error, + title: title, + dismiss: { + duration: 10000, + } + }) + }, + success: (message: string, title: string) => { + Store.addNotification({ + container: "top-right", + type: "success", + message: message, + title: title, + dismiss: { + duration: 3000, + } + }) + } +} + +export default notifications \ No newline at end of file diff --git a/examples/nextjs-api-sales/components/utils.ts b/examples/nextjs-api-sales/components/utils.ts new file mode 100644 index 0000000000..b0d9a8ebca --- /dev/null +++ b/examples/nextjs-api-sales/components/utils.ts @@ -0,0 +1,70 @@ +import { App, AppSearch, Table, TableSearch } from "../definitions" +import getConfig from "next/config" + +const { serverRuntimeConfig } = getConfig() +const apiKey = serverRuntimeConfig["apiKey"] +const appName = serverRuntimeConfig["appName"] +const host = serverRuntimeConfig["host"] + +let APP: App | null = null +let TABLES: { [key: string]: Table } = {} + +export async function makeCall(method: string, url: string, opts?: { body?: any, appId?: string }): Promise { + const fetchOpts: any = { + method, + headers: { + "x-budibase-api-key": apiKey, + } + } + if (opts?.appId) { + fetchOpts.headers["x-budibase-app-id"] = opts.appId + } + if (opts?.body) { + fetchOpts.body = typeof opts.body !== "string" ? JSON.stringify(opts.body) : opts.body + fetchOpts.headers["Content-Type"] = "application/json" + } + const finalUrl = `${host}/api/public/v1/${url}` + const response = await fetch(finalUrl, fetchOpts) + if (response.ok) { + return response.json() + } else { + const error = await response.text() + console.error("Budibase server error - ", error) + throw new Error(error) + } +} + +export async function getApp(): Promise { + if (APP) { + return APP + } + const apps: AppSearch = await makeCall("post", "applications/search", { + body: { + name: appName, + } + }) + const app = apps.data.find((app: App) => app.name === appName) + if (!app) { + throw new Error("Could not find app, please make sure app name in config is correct.") + } + APP = app + return app +} + +export async function findTable(appId: string, tableName: string): Promise
{ + if (TABLES[tableName]) { + return TABLES[tableName] + } + const tables: TableSearch = await makeCall("post", "tables/search", { + body: { + name: tableName, + }, + appId, + }) + const table = tables.data.find((table: Table) => table.name === tableName) + if (!table) { + throw new Error("Could not find table, please make sure your app is configured with the Postgres datasource correctly.") + } + TABLES[tableName] = table + return table +} diff --git a/examples/nextjs-api-sales/db/init.sql b/examples/nextjs-api-sales/db/init.sql index 462d64ff30..f0a0c9d100 100644 --- a/examples/nextjs-api-sales/db/init.sql +++ b/examples/nextjs-api-sales/db/init.sql @@ -1,23 +1,21 @@ CREATE TABLE IF NOT EXISTS sales_people ( - person_id INT NOT NULL, - name varchar(200) NOT NULL, - PRIMARY KEY (person_id) + person_id SERIAL PRIMARY KEY, + name varchar(200) NOT NULL ); CREATE TABLE IF NOT EXISTS sales ( - sale_id INT NOT NULL, + sale_id SERIAL PRIMARY KEY, sale_name varchar(200) NOT NULL, sold_by INT, - PRIMARY KEY (sale_id), CONSTRAINT sold_by_fk FOREIGN KEY(sold_by) REFERENCES sales_people(person_id) ); -INSERT INTO sales_people -select id, concat('Sales person ', id) +INSERT INTO sales_people (name) +select 'Salesperson ' || id FROM GENERATE_SERIES(1, 50) as id; -INSERT INTO sales -select id, concat('Sale ', id), floor(random() * 50 + 1)::int -FROM GENERATE_SERIES(1, 200) as id; \ No newline at end of file +INSERT INTO sales (sale_name, sold_by) +select 'Sale ' || id, floor(random() * 50 + 1)::int +FROM GENERATE_SERIES(1, 200) as id; diff --git a/examples/nextjs-api-sales/package.json b/examples/nextjs-api-sales/package.json index a278a3050a..6d75c85f01 100644 --- a/examples/nextjs-api-sales/package.json +++ b/examples/nextjs-api-sales/package.json @@ -14,7 +14,8 @@ "node-fetch": "^3.2.2", "node-sass": "^7.0.1", "react": "17.0.2", - "react-dom": "17.0.2" + "react-dom": "17.0.2", + "react-notifications-component": "^3.4.1" }, "devDependencies": { "@types/node": "17.0.21", diff --git a/examples/nextjs-api-sales/pages/_app.tsx b/examples/nextjs-api-sales/pages/_app.tsx index 71f53e7f8a..c6c68091e3 100644 --- a/examples/nextjs-api-sales/pages/_app.tsx +++ b/examples/nextjs-api-sales/pages/_app.tsx @@ -1,8 +1,13 @@ import "../styles/global.sass" import type { AppProps } from "next/app" +import Layout from "../components/layout" function MyApp({ Component, pageProps }: AppProps) { - return + return ( + + + + ) } export default MyApp diff --git a/examples/nextjs-api-sales/pages/api/sales.ts b/examples/nextjs-api-sales/pages/api/sales.ts index 0700711e88..95d01d6c40 100644 --- a/examples/nextjs-api-sales/pages/api/sales.ts +++ b/examples/nextjs-api-sales/pages/api/sales.ts @@ -1,73 +1,4 @@ -import getConfig from "next/config" -import {App, AppSearch, Table, TableSearch} from "../../definitions" - -const { serverRuntimeConfig } = getConfig() -const apiKey = serverRuntimeConfig["apiKey"] -const appName = serverRuntimeConfig["appName"] -const host = serverRuntimeConfig["host"] - -let APP: App | null = null -let TABLES: { [key: string]: Table } = {} - -async function makeCall(method: string, url: string, opts?: { body?: any, appId?: string }): Promise { - const fetchOpts: any = { - method, - headers: { - "x-budibase-api-key": apiKey, - } - } - if (opts?.appId) { - fetchOpts.headers["x-budibase-app-id"] = opts.appId - } - if (opts?.body) { - fetchOpts.body = typeof opts.body !== "string" ? JSON.stringify(opts.body) : opts.body - fetchOpts.headers["Content-Type"] = "application/json" - } - const finalUrl = `${host}/api/public/v1/${url}` - const response = await fetch(finalUrl, fetchOpts) - if (response.ok) { - return response.json() - } else { - const error = await response.text() - console.error("Budibase server error - ", error) - throw new Error(error) - } -} - -async function getApp(): Promise { - if (APP) { - return APP - } - const apps: AppSearch = await makeCall("post", "applications/search", { - body: { - name: appName, - } - }) - const app = apps.data.find((app: App) => app.name === appName) - if (!app) { - throw new Error("Could not find app, please make sure app name in config is correct.") - } - APP = app - return app -} - -async function findTable(appId: string, tableName: string): Promise
{ - if (TABLES[tableName]) { - return TABLES[tableName] - } - const tables: TableSearch = await makeCall("post", "tables/search", { - body: { - name: tableName, - }, - appId, - }) - const table = tables.data.find((table: Table) => table.name === tableName) - if (!table) { - throw new Error("Could not find table, please make sure your app is configured with the Postgres datasource correctly.") - } - TABLES[tableName] = table - return table -} +import { getApp, findTable, makeCall } from "../../components/utils" async function getSales(req: any) { const { page } = req.query @@ -79,7 +10,7 @@ async function getSales(req: any) { limit: 10, sort: { type: "string", - order: "ascending", + order: "descending", column: "sale_id", }, paginate: true, diff --git a/examples/nextjs-api-sales/pages/api/salespeople.ts b/examples/nextjs-api-sales/pages/api/salespeople.ts new file mode 100644 index 0000000000..190e901486 --- /dev/null +++ b/examples/nextjs-api-sales/pages/api/salespeople.ts @@ -0,0 +1,31 @@ +import { getApp, findTable, makeCall } from "../../components/utils" + +async function getSalespeople() { + const { _id: appId } = await getApp() + const table = await findTable(appId, "sales_people") + return await makeCall("post", `tables/${table._id}/rows/search`, { + appId, + body: { + sort: { + type: "string", + order: "ascending", + column: "person_id", + }, + } + }) +} + +export default async function handler(req: any, res: any) { + let response: any = {} + try { + if (req.method === "GET") { + response = await getSalespeople() + } else { + res.status(404) + return + } + res.status(200).json(response) + } catch (err: any) { + res.status(400).send(err) + } +} \ No newline at end of file diff --git a/examples/nextjs-api-sales/pages/index.tsx b/examples/nextjs-api-sales/pages/index.tsx index 1c4b450b53..01e1feb67a 100644 --- a/examples/nextjs-api-sales/pages/index.tsx +++ b/examples/nextjs-api-sales/pages/index.tsx @@ -1,61 +1,81 @@ import type { NextPage } from "next" import styles from "../styles/home.module.css" -import { useState, useEffect } from "react" +import { useState, useEffect, useCallback } from "react" +import Notifications from "../components/notifications" const Home: NextPage = () => { const [sales, setSales] = useState([]) const [currentPage, setCurrentPage] = useState(1) + const [loaded, setLoaded] = useState(false) - const getSales = async (page: Number = 1) => { + const getSales = useCallback(async (page: Number = 1) => { let url = "/api/sales" if (page) { url += `?page=${page}` } const response = await fetch(url) if (!response.ok) { - throw new Error(await response.text()) + const error = await response.text() + Notifications.error(error, "Failed to get sales") + return } const sales = await response.json() // @ts-ignore setCurrentPage(page) return setSales(sales.data) - } + }, []) - const saveSale = async () => { - const response = await fetch("/api/sales", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({}), - }) - if (!response.ok) { - throw new Error(await response.text()) - } - } - - const goToNextPage = async () => { + const goToNextPage = useCallback(async () => { await getSales(currentPage + 1) - } + }, [currentPage, getSales]) - const goToPrevPage = async () => { + const goToPrevPage = useCallback(async () => { if (currentPage > 1) { await getSales(currentPage - 1) } - } + }, [currentPage, getSales]) useEffect(() => { - getSales().catch(() => { + getSales().then(() => { + setLoaded(true) + }).catch(() => { setSales([]) }) }, []) + if (!loaded) { + return null + } + return (
-

Sales

-
{sales.map((sale: any) =>

{sale.sale_id}

)}
- - +
+

Sales

+
+
+ + + + + + + + + {sales.map((sale: any) => + + + + + + )} + +
Sale IDnameSold by
{sale.sale_id}{sale.sale_name}{sale.sales_people?.map((person: any) => person.primaryDisplay)[0]}
+
+ + +
+
+
) } diff --git a/examples/nextjs-api-sales/pages/save.tsx b/examples/nextjs-api-sales/pages/save.tsx new file mode 100644 index 0000000000..5b1ab5abff --- /dev/null +++ b/examples/nextjs-api-sales/pages/save.tsx @@ -0,0 +1,81 @@ +import type { NextPage } from "next" +import { useCallback, useEffect, useState } from "react" +import styles from "../styles/save.module.css" +import Notifications from "../components/notifications" + +const Save: NextPage = () => { + const [salespeople, setSalespeople] = useState([]) + const [loaded, setLoaded] = useState(false) + + const saveSale = useCallback(async (event: any) => { + event.preventDefault() + const sale = { + sale_name: event.target.name.value, + sales_person: [event.target.soldBy.value], + } + const response = await fetch("/api/sales", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(sale), + }) + if (!response.ok) { + const error = await response.text() + Notifications.error(error, "Failed to save sale") + return + } + Notifications.success("Sale saved successfully!", "Sale saved") + }, []) + + const getSalespeople = useCallback(async () => { + const response: any = await fetch("/api/salespeople") + if (!response.ok) { + throw new Error(await response.text()) + } + const json = await response.json() + setSalespeople(json.data) + }, []) + + useEffect(() => { + getSalespeople().then(() => { + setLoaded(true) + }).catch(() => { + setSalespeople([]) + }) + }, []) + + if (!loaded) { + return null + } + return ( +
+
+

New sale

+
+
+ +
+ +
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+ ) +} + +export default Save \ No newline at end of file diff --git a/examples/nextjs-api-sales/public/bb-emblem.svg b/examples/nextjs-api-sales/public/bb-emblem.svg new file mode 100644 index 0000000000..9f4f3690d5 --- /dev/null +++ b/examples/nextjs-api-sales/public/bb-emblem.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/nextjs-api-sales/public/vercel.svg b/examples/nextjs-api-sales/public/vercel.svg deleted file mode 100644 index fbf0e25a65..0000000000 --- a/examples/nextjs-api-sales/public/vercel.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - \ No newline at end of file diff --git a/examples/nextjs-api-sales/styles/global.sass b/examples/nextjs-api-sales/styles/global.sass index 794e1ce4d8..85e46f8591 100644 --- a/examples/nextjs-api-sales/styles/global.sass +++ b/examples/nextjs-api-sales/styles/global.sass @@ -1,12 +1,25 @@ @charset "utf-8" -// Import a Google Font @import url('https://fonts.googleapis.com/css?family=Roboto:400,700') - $family-sans-serif: "Roboto", sans-serif -//$grey-dark: color -//$grey-light: color -//$primary: color -//$link: color -@import "../node_modules/bulma/bulma.sass" \ No newline at end of file +#__next + display: flex + flex-direction: column + justify-content: flex-start + align-items: stretch + height: 100vh + +.logo + padding: 0.75rem + +@import "../node_modules/bulma/bulma.sass" +@import "../node_modules/react-notifications-component/dist/theme.css" + +// applied after bulma styles are enabled +html + overflow-y: auto + +.navbar + background-color: #D3D3D3 + color: white \ No newline at end of file diff --git a/examples/nextjs-api-sales/styles/home.module.css b/examples/nextjs-api-sales/styles/home.module.css index 4906fe57f1..eb71c1072e 100644 --- a/examples/nextjs-api-sales/styles/home.module.css +++ b/examples/nextjs-api-sales/styles/home.module.css @@ -1,116 +1,30 @@ .container { - padding: 0 2rem; -} - -.main { - min-height: 100vh; - padding: 4rem 0; - flex: 1; + width: 100vw; display: flex; flex-direction: column; - justify-content: center; + padding: 5rem 2rem 0; align-items: center; + flex: 1 1 auto; } -.footer { +.buttons { display: flex; - flex: 1; - padding: 2rem 0; - border-top: 1px solid #eaeaea; - justify-content: center; - align-items: center; + flex-direction: row; + justify-content: space-between; } -.footer a { - display: flex; - justify-content: center; - align-items: center; - flex-grow: 1; -} - -.title a { - color: #0070f3; - text-decoration: none; -} - -.title a:hover, -.title a:focus, -.title a:active { - text-decoration: underline; -} - -.title { - margin: 0; - line-height: 1.15; - font-size: 4rem; -} - -.title, -.description { - text-align: center; -} - -.description { - margin: 4rem 0; - line-height: 1.5; - font-size: 1.5rem; -} - -.code { - background: #fafafa; - border-radius: 5px; - padding: 0.75rem; - font-size: 1.1rem; - font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, - Bitstream Vera Sans Mono, Courier New, monospace; -} - -.grid { - display: flex; - align-items: center; - justify-content: center; - flex-wrap: wrap; - max-width: 800px; -} - -.card { - margin: 1rem; - padding: 1.5rem; - text-align: left; - color: inherit; - text-decoration: none; - border: 1px solid #eaeaea; +.tableSection { + padding: 2rem; + background: #D3D3D3; + width: 800px; border-radius: 10px; - transition: color 0.15s ease, border-color 0.15s ease; - max-width: 300px; } -.card:hover, -.card:focus, -.card:active { - color: #0070f3; - border-color: #0070f3; -} - -.card h2 { - margin: 0 0 1rem 0; - font-size: 1.5rem; -} - -.card p { - margin: 0; - font-size: 1.25rem; - line-height: 1.5; -} - -.logo { - height: 1em; - margin-left: 0.5rem; -} - -@media (max-width: 600px) { -.grid { +.table table { width: 100%; - flex-direction: column; -} } + +.tableSection h1 { + text-align: center; + color: black; +} \ No newline at end of file diff --git a/examples/nextjs-api-sales/styles/save.module.css b/examples/nextjs-api-sales/styles/save.module.css new file mode 100644 index 0000000000..177d317afd --- /dev/null +++ b/examples/nextjs-api-sales/styles/save.module.css @@ -0,0 +1,20 @@ +.container { + width: 100vw; + display: flex; + flex-direction: column; + padding: 5rem 2rem 0; + align-items: center; + flex: 1 1 auto; +} + +.formSection { + padding: 2rem; + background: #D3D3D3; + width: 400px; + border-radius: 10px; +} + +.formSection h1 { + text-align: center; + color: black; +} \ No newline at end of file diff --git a/examples/nextjs-api-sales/yarn.lock b/examples/nextjs-api-sales/yarn.lock index b1a66a4ac5..3f32417ba8 100644 --- a/examples/nextjs-api-sales/yarn.lock +++ b/examples/nextjs-api-sales/yarn.lock @@ -2384,6 +2384,11 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-notifications-component@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/react-notifications-component/-/react-notifications-component-3.4.1.tgz#3670aa17210a4e63ba3b4f553853bd99ab6a0150" + integrity sha512-vS/RLdz+VlXZz0dbK+LCcdhgUdUPi1BvSo7mVp58AQDpixI9emGwI0uISXhiTSjqFn/cPibPlJOJQ8kcvgmUrQ== + react@17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" From ce984348a0da93a4c8bf38d9498bc7d46b167b5a Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 9 Mar 2022 16:08:55 +0100 Subject: [PATCH 028/171] fixing enrichment of relationships in patch call --- packages/server/src/api/controllers/row/internal.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/server/src/api/controllers/row/internal.js b/packages/server/src/api/controllers/row/internal.js index 068a485a8a..9ddd6328b5 100644 --- a/packages/server/src/api/controllers/row/internal.js +++ b/packages/server/src/api/controllers/row/internal.js @@ -83,7 +83,11 @@ exports.patch = async ctx => { const isUserTable = tableId === InternalTables.USER_METADATA let oldRow try { - oldRow = await db.get(inputs._id) + let dbTable = await db.get(tableId) + oldRow = await outputProcessing( + dbTable, + await findRow(ctx, tableId, inputs._id) + ) } catch (err) { if (isUserTable) { // don't include the rev, it'll be the global rev From 93df84b6713cfd067fc7854787ed9f8a1b25e945 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 9 Mar 2022 15:19:18 +0000 Subject: [PATCH 029/171] Adjusting colours, some quick fixes after changing to sales person for relationship name. --- examples/nextjs-api-sales/components/layout.tsx | 7 +++---- examples/nextjs-api-sales/pages/_app.tsx | 4 ++++ examples/nextjs-api-sales/pages/index.tsx | 2 +- examples/nextjs-api-sales/styles/global.sass | 3 ++- examples/nextjs-api-sales/styles/home.module.css | 2 +- examples/nextjs-api-sales/styles/save.module.css | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/nextjs-api-sales/components/layout.tsx b/examples/nextjs-api-sales/components/layout.tsx index 63049af025..48052028d7 100644 --- a/examples/nextjs-api-sales/components/layout.tsx +++ b/examples/nextjs-api-sales/components/layout.tsx @@ -8,21 +8,20 @@ function layout(props: any) {