diff options
177 files changed, 5552 insertions, 4506 deletions
diff --git a/ann_benchmark/src/vespa/ann_benchmark/vespa_ann_benchmark.cpp b/ann_benchmark/src/vespa/ann_benchmark/vespa_ann_benchmark.cpp index 4af30a5d9d3..f9a4d5b43cc 100644 --- a/ann_benchmark/src/vespa/ann_benchmark/vespa_ann_benchmark.cpp +++ b/ann_benchmark/src/vespa/ann_benchmark/vespa_ann_benchmark.cpp @@ -10,7 +10,7 @@ #include <vespa/searchcommon/attribute/config.h> #include <vespa/eval/eval/value.h> #include <vespa/vespalib/test/insertion_operators.h> -#include <ostream> +#include <iostream> #include <sstream> #include <limits> diff --git a/application/pom.xml b/application/pom.xml index 34bf1b56c0d..e2176d4deac 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -86,6 +86,10 @@ <artifactId>org.apache.felix.framework</artifactId> </dependency> <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.log</artifactId> + </dependency> + <dependency> <groupId>org.apache.opennlp</groupId> <artifactId>opennlp-tools</artifactId> </dependency> diff --git a/client/js/app/package.json b/client/js/app/package.json index f88c4234ad5..f2f8f6cb433 100644 --- a/client/js/app/package.json +++ b/client/js/app/package.json @@ -7,23 +7,26 @@ "build": "vite build", "preview": "vite preview", "prepare": "cd ../../../ && husky install client/js/app/.husky", + "test": "jest", "lint": "eslint '{**/*,*}.{js,jsx}'" }, "dependencies": { "react": "^18", - "react-bootstrap": "^2.4.0", "react-dom": "^18" }, "devDependencies": { + "@emotion/react": "^11", "@fortawesome/fontawesome-svg-core": "^6", "@fortawesome/free-regular-svg-icons": "^6", "@fortawesome/free-solid-svg-icons": "^6", "@fortawesome/react-fontawesome": "^0", - "@mantine/core": "^4", - "@mantine/hooks": "^4", + "@mantine/core": "^5", + "@mantine/hooks": "^5", + "@mantine/notifications": "^5", "@types/react": "^18", "@types/react-dom": "^18", "@vitejs/plugin-react": "^1", + "esbuild-jest": "^0", "eslint": "^8", "eslint-plugin-import": "^2", "eslint-plugin-prettier": "^4", @@ -32,11 +35,31 @@ "eslint-plugin-react-perf": "^3", "eslint-plugin-unused-imports": "^2", "husky": "^7", + "jest": "^28", "lodash": "^4", "prettier": "2", "pretty-quick": "^3", "react-router-dom": "^6", "use-context-selector": "^1", "vite": "^2" + }, + "jest": { + "testMatch": [ + "<rootDir>/src/**/*.test.{js,jsx,ts,tsx}" + ], + "transform": { + "^.+\\.(js|jsx|mjs|cjs|ts|tsx)$": [ + "esbuild-jest" + ] + }, + "transformIgnorePatterns": [ + "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$" + ], + "moduleNameMapper": { + "^app/(.*)$": [ + "<rootDir>/src/app/$1" + ] + }, + "resetMocks": true } } diff --git a/client/js/app/src/app/app.jsx b/client/js/app/src/app/app.jsx index 9fa912c89a5..704a5bcbeeb 100644 --- a/client/js/app/src/app/app.jsx +++ b/client/js/app/src/app/app.jsx @@ -1,8 +1,9 @@ import React from 'react'; -import { BrowserRouter, Route } from 'react-router-dom'; +import { BrowserRouter } from 'react-router-dom'; +import { NotificationsProvider as MantineNotificationsProvider } from '@mantine/notifications'; import { Layout } from 'app/components'; import { Home } from 'app/pages/home/home'; -import { QueryBuilder } from 'app/pages/querybuilder/query-builder'; +import { QueryBuilder } from 'app/pages/querybuilder'; import { QueryTracer } from 'app/pages/querytracer/query-tracer'; import { ThemeProvider } from 'app/libs/theme-provider'; import { Router } from 'app/libs/router'; @@ -11,13 +12,15 @@ export function App() { return ( <BrowserRouter> <ThemeProvider> - <Layout> - <Router> - <Route path="/" element={<Home />} /> - <Route path="querybuilder" element={<QueryBuilder />} /> - <Route path="querytracer" element={<QueryTracer />} /> - </Router> - </Layout> + <MantineNotificationsProvider> + <Layout> + <Router> + <Home path="/" title="Home" /> + <QueryBuilder path="querybuilder" title="Query Builder" /> + <QueryTracer path="querytracer" title="Query Tracer" /> + </Router> + </Layout> + </MantineNotificationsProvider> </ThemeProvider> </BrowserRouter> ); diff --git a/client/js/app/src/app/assets/index.js b/client/js/app/src/app/assets/index.js index a62869fa71b..bf132dd86a7 100644 --- a/client/js/app/src/app/assets/index.js +++ b/client/js/app/src/app/assets/index.js @@ -1,2 +1 @@ export { default as VespaLogo } from 'app/assets/img/vespa-logo.svg'; -export { default as VespaIcon } from 'app/assets/img/vespa-icon.svg'; diff --git a/client/js/app/src/app/components/icon/icon.jsx b/client/js/app/src/app/components/icon/icon.jsx index e860d293cce..edc86250b01 100644 --- a/client/js/app/src/app/components/icon/icon.jsx +++ b/client/js/app/src/app/components/icon/icon.jsx @@ -1,13 +1,47 @@ import React from 'react'; import { library } from '@fortawesome/fontawesome-svg-core'; +import { Box } from '@mantine/core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faArrowsToDot, faChartGantt } from '@fortawesome/free-solid-svg-icons'; +import { + faArrowsToDot, + faChartGantt, + faCheck, + faCircleMinus, + faCopy, + faDownload, + faPaste, + faPlus, + faXmark, + faInfo, + faExclamation, +} from '@fortawesome/free-solid-svg-icons'; // TODO: use dynamic import -library.add(faArrowsToDot, faChartGantt); +library.add( + faArrowsToDot, + faChartGantt, + faCircleMinus, + faPlus, + faPaste, + faDownload, + faCopy, + faCheck, + faXmark, + faInfo, + faExclamation +); -export function Icon({ name, type = 'solid', ...rest }) { +export function Icon({ name, type = 'solid', color, ...rest }) { const icon = `fa-${type} fa-${name}`; - return <FontAwesomeIcon icon={icon} {...rest} />; + return ( + <Box + sx={(theme) => ({ + ...(color && { color: theme.cr.getSolidBackground(color) }), + })} + component={FontAwesomeIcon} + icon={icon} + {...rest} + /> + ); } diff --git a/client/js/app/src/app/components/layout/layout.jsx b/client/js/app/src/app/components/layout/layout.jsx index f0f5a0594c0..532a9ce3630 100644 --- a/client/js/app/src/app/components/layout/layout.jsx +++ b/client/js/app/src/app/components/layout/layout.jsx @@ -3,9 +3,5 @@ import { AppShell } from '@mantine/core'; import { Header } from 'app/components/layout/header'; export function Layout({ children }) { - return ( - <AppShell header={<Header />} fixed> - {children} - </AppShell> - ); + return <AppShell header={<Header />}>{children}</AppShell>; } diff --git a/client/js/app/src/app/libs/notification/index.jsx b/client/js/app/src/app/libs/notification/index.jsx new file mode 100644 index 00000000000..9313e3c9adf --- /dev/null +++ b/client/js/app/src/app/libs/notification/index.jsx @@ -0,0 +1,2 @@ +export * from 'app/libs/notification/rest-message'; +export * from 'app/libs/notification/messages'; diff --git a/client/js/app/src/app/libs/notification/messages.jsx b/client/js/app/src/app/libs/notification/messages.jsx new file mode 100644 index 00000000000..87f94b0dda0 --- /dev/null +++ b/client/js/app/src/app/libs/notification/messages.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { showNotification } from '@mantine/notifications'; +import { Icon } from 'app/components'; +import { SHADE } from 'app/styles/theme/colors'; + +function getStyles(color) { + return (theme) => ({ + root: { + color: theme.fn.themeColor(color, SHADE.LOW_CONTRAST_TEXT), + background: theme.fn.themeColor(color, SHADE.UI_ELEMENT_BACKGROUND), + borderColor: theme.fn.themeColor( + color, + SHADE.UI_ELEMENT_BORDER_AND_FOCUS + ), + }, + title: { + fontWeight: 700, + color: theme.fn.themeColor(color, SHADE.LOW_CONTRAST_TEXT), + '&:hover': { + color: theme.fn.themeColor(color, SHADE.LOW_CONTRAST_TEXT), + }, + }, + description: { + color: theme.fn.themeColor(color, SHADE.LOW_CONTRAST_TEXT), + '&:hover': { + color: theme.fn.themeColor(color, SHADE.LOW_CONTRAST_TEXT), + }, + }, + closeButton: { + color: theme.fn.themeColor(color, SHADE.LOW_CONTRAST_TEXT), + '&:hover': { + backgroundColor: theme.fn.themeColor( + color, + SHADE.HOVERED_UI_ELEMENT_BACKGROUND + ), + }, + }, + }); +} + +const commonMessage = ({ title, icon, color, message }) => { + return showNotification({ + styles: getStyles(color), + icon: <Icon name={icon} />, + title, + color, + message, + }); +}; + +export const infoMessage = ( + message, + title = 'Info', + icon = 'info', + color = 'blue' +) => commonMessage({ title, icon, color, message }); + +export const warningMessage = ( + message, + title = 'Warning', + icon = 'exclamation', + color = 'orange' +) => commonMessage({ title, icon, color, message }); + +export const errorMessage = ( + message, + title = 'Error', + icon = 'xmark', + color = 'red' +) => commonMessage({ title, icon, color, message }); + +export const successMessage = ( + message, + title = 'Success', + icon = 'check', + color = 'green' +) => commonMessage({ title, icon, color, message }); diff --git a/client/js/app/src/app/libs/notification/rest-message.jsx b/client/js/app/src/app/libs/notification/rest-message.jsx new file mode 100644 index 00000000000..d05d28754b8 --- /dev/null +++ b/client/js/app/src/app/libs/notification/rest-message.jsx @@ -0,0 +1,43 @@ +import { + errorMessage, + infoMessage, + successMessage, +} from 'app/libs/notification/index'; + +export const restMessage = (response, prefix, code = 200) => { + // Gracefully handle various types of rest responses input + // Response can be a raw fetch request, an already decoded object or a plain string + if (typeof response === 'object') { + if (typeof response.text === 'function') { + Promise.resolve(response.text()).then((text) => { + restMessageContent(response.status || code, text, prefix); + }); + } else { + restMessageContent( + response.code || 200, + response.message || JSON.stringify(response), + prefix + ); + } + } else if (typeof response === 'string') { + restMessageContent(code, response, prefix); + } +}; + +const restMessageContent = (code, message, prefix) => { + // Trunk long messages + if (message.length > 200) message = message.substring(0, 200) + '...'; + + // Add pre-message if given + // Most of the time the message is just "Success" - so you would like + // to prefix it with eg. 'Adding user: ' + message = prefix ? prefix + message : message; + + if (code < 300) { + successMessage(message); + } else if (code < 400) { + infoMessage(message); + } else { + errorMessage(message); + } +}; diff --git a/client/js/app/src/app/libs/theme-provider.jsx b/client/js/app/src/app/libs/theme-provider.jsx index 58496ce15c2..c5e9cbee963 100644 --- a/client/js/app/src/app/libs/theme-provider.jsx +++ b/client/js/app/src/app/libs/theme-provider.jsx @@ -1,6 +1,5 @@ import React from 'react'; import { Global, MantineProvider } from '@mantine/core'; -import { defaultProps, defaultStyles } from 'app/styles/default'; import { Colors } from 'app/styles/theme/colors'; import { styles } from 'app/styles/global'; import { getTheme } from 'app/styles/theme'; @@ -12,11 +11,7 @@ function setColorResolver(theme) { export function ThemeProvider({ children }) { return ( - <MantineProvider - styles={defaultStyles} - defaultProps={defaultProps} - theme={getTheme()} - > + <MantineProvider theme={getTheme()}> <Global styles={(theme) => styles(setColorResolver(theme))} /> {children} </MantineProvider> diff --git a/client/js/app/src/app/pages/querybuilder/Components/Buttons/CopyResponseButton.jsx b/client/js/app/src/app/pages/querybuilder/Components/Buttons/CopyResponseButton.jsx deleted file mode 100644 index 2c53c4dd1e6..00000000000 --- a/client/js/app/src/app/pages/querybuilder/Components/Buttons/CopyResponseButton.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import React, { useState } from 'react'; -import { OverlayTrigger, Tooltip } from 'react-bootstrap'; -import ImageButton from './ImageButton'; -import { useQueryBuilderContext } from 'app/pages/querybuilder/Components/Contexts/QueryBuilderProvider'; -import copyImage from 'app/pages/querybuilder/assets/img/copy.svg'; - -export default function CopyResponseButton() { - const response = useQueryBuilderContext((ctx) => ctx.http.response); - const [show, setShow] = useState(false); - - const handleCopy = () => { - setShow(true); - navigator.clipboard.writeText(response); - setTimeout(() => { - setShow(false); - }, 2000); - }; - - return ( - <OverlayTrigger - placement="left-end" - overlay={ - <Tooltip>{show ? 'Response copied to clipboard' : 'Copy'}</Tooltip> - } - > - <span> - <ImageButton - className="intro-copy" - image={copyImage} - height={30} - width={30} - onClick={handleCopy} - /> - </span> - </OverlayTrigger> - ); -} diff --git a/client/js/app/src/app/pages/querybuilder/Components/Buttons/DownloadJSONButton.jsx b/client/js/app/src/app/pages/querybuilder/Components/Buttons/DownloadJSONButton.jsx deleted file mode 100644 index b89e3f14b3b..00000000000 --- a/client/js/app/src/app/pages/querybuilder/Components/Buttons/DownloadJSONButton.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import transform from 'app/pages/querybuilder/TransformVespaTrace'; - -export default function DownloadJSONButton({ children, response }) { - const handleClick = () => { - let content; - try { - content = JSON.stringify(transform(JSON.parse(response), null, 4)); - } catch (error) { - alert(`Failed to transform response to Jaeger format: ${error}`); // TODO: Change to toast - return; - } - - // copied from safakeskin´s answer on SO, link: https://stackoverflow.com/questions/55613438/reactwrite-to-json-file-or-export-download-no-server - const blob = new Blob([content], { type: 'application/json' }); - const href = URL.createObjectURL(blob); - - // create "a" HTML element with href to file - const link = document.createElement('a'); - link.href = href; - link.download = 'vespa-response.json'; - document.body.appendChild(link); - link.click(); - - // clean up "a" element & remove ObjectURL - document.body.removeChild(link); - URL.revokeObjectURL(href); - }; - - return <button onClick={handleClick}>{children}</button>; -} diff --git a/client/js/app/src/app/pages/querybuilder/Components/Buttons/ImageButton.jsx b/client/js/app/src/app/pages/querybuilder/Components/Buttons/ImageButton.jsx deleted file mode 100644 index 711229d82cd..00000000000 --- a/client/js/app/src/app/pages/querybuilder/Components/Buttons/ImageButton.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; - -export default function ImageButton({ - onClick, - children, - className, - image, - height = 15, - width = 15, - style, -}) { - return ( - <button className={className} onClick={onClick}> - <img - src={image} - height={height} - width={width} - style={style} - alt="Missing" - /> - {children} - </button> - ); -} diff --git a/client/js/app/src/app/pages/querybuilder/Components/Buttons/PasteJSONButton.jsx b/client/js/app/src/app/pages/querybuilder/Components/Buttons/PasteJSONButton.jsx deleted file mode 100644 index f01f5b177a5..00000000000 --- a/client/js/app/src/app/pages/querybuilder/Components/Buttons/PasteJSONButton.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import React, { useState } from 'react'; -import pasteImage from '../../assets/img/paste.svg'; -import ImageButton from './ImageButton'; -import { - ACTION, - dispatch, -} from 'app/pages/querybuilder/Components/Contexts/QueryBuilderProvider'; - -export default function PasteJSONButton() { - const [paste, setPaste] = useState(false); - - const handleClick = () => { - setPaste(true); - window.addEventListener('paste', handlePaste); - }; - - const handlePaste = (e) => { - setPaste(false); - // Stop data actually being pasted into div - e.stopPropagation(); - e.preventDefault(); - const pastedData = e.clipboardData.getData('text'); - window.removeEventListener('paste', handlePaste); - dispatch(ACTION.SET_QUERY, pastedData); - }; - - return ( - <> - <ImageButton - className="pasteJSON" - image={pasteImage} - onClick={handleClick} - > - {paste ? 'Press CMD + V' : 'Paste JSON'} - </ImageButton> - </> - ); -} diff --git a/client/js/app/src/app/pages/querybuilder/Components/Contexts/QueryBuilderProvider.jsx b/client/js/app/src/app/pages/querybuilder/Components/Contexts/QueryBuilderProvider.jsx deleted file mode 100644 index 2eebbb9b8b5..00000000000 --- a/client/js/app/src/app/pages/querybuilder/Components/Contexts/QueryBuilderProvider.jsx +++ /dev/null @@ -1,146 +0,0 @@ -import React, { useReducer } from 'react'; -import { createContext, useContextSelector } from 'use-context-selector'; -import { cloneDeep, last } from 'lodash'; -import parameters from 'app/pages/querybuilder/parameters'; - -let _dispatch; -const root = { type: { children: parameters } }; -const context = createContext(null); - -export const ACTION = Object.freeze({ - SET_QUERY: 0, - SET_HTTP: 1, - - INPUT_ADD: 10, - INPUT_UPDATE: 11, - INPUT_REMOVE: 12, -}); - -function inputsToJson(inputs) { - return Object.fromEntries( - inputs.map(({ children, input, type: { name, type } }) => [ - name, - children ? inputsToJson(children) : parseInput(input, type), - ]) - ); -} - -function jsonToInputs(json, parent) { - return Object.entries(json).map(([key, value], i) => { - const node = { - id: parent.id ? `${parent.id}.${i}` : i.toString(), - type: parent.type.children[key], - parent, - }; - if (typeof value === 'object') { - node.input = ''; - node.children = jsonToInputs(value, node); - } else node.input = value.toString(); - return node; - }); -} - -function parseInput(input, type) { - if (type === 'Integer' || type === 'Long') return parseInt(input); - if (type === 'Float') return parseFloat(input); - if (type === 'Boolean') return input.toLowerCase() === 'true'; - return input; -} - -function inputAdd(query, { id: parentId, type: typeName }) { - const inputs = cloneDeep(query.children); - const parent = parentId ? findInput(inputs, parentId) : query; - - const nextId = - parseInt(last(last(parent.children)?.id?.split('.')) ?? -1) + 1; - const id = parentId ? `${parentId}.${nextId}` : nextId.toString(); - const type = parent.type.children[typeName]; - - parent.children.push( - Object.assign( - { id, input: '', type, parent }, - type.children && { children: [] } - ) - ); - return { ...query, children: inputs }; -} - -function inputUpdate(query, { id, ...props }) { - const keys = Object.keys(props); - if (keys.length !== 1) - throw new Error(`Expected to update exactly 1 input prop, got: ${keys}`); - if (!['input', 'type'].includes(keys[0])) - throw new Error(`Cannot update key ${keys[0]}`); - - const inputs = cloneDeep(query.children); - const node = Object.assign(findInput(inputs, id), props); - if (node.type.children) node.children = []; - else delete node.children; - return { ...query, children: inputs }; -} - -function findInput(inputs, id, Delete = false) { - let end = -1; - while ((end = id.indexOf('.', end + 1)) > 0) - inputs = inputs.find((input) => input.id === id.substring(0, end)).children; - const index = inputs.findIndex((input) => input.id === id); - return Delete ? inputs.splice(index, 1)[0] : inputs[index]; -} - -function reducer(state, action) { - const result = preReducer(state, action); - if (state.query.children !== result.query.children) { - const json = inputsToJson(result.query.children); - result.query.input = JSON.stringify(json, null, 4); - } - - return result; -} -function preReducer(state, { action, data }) { - switch (action) { - case ACTION.SET_QUERY: { - try { - const children = jsonToInputs(JSON.parse(data), root); - return { ...state, query: { ...root, children } }; - } catch (error) { - alert(`Failed to parse query: ${error}`); // TODO: Change to toast - return state; - } - } - case ACTION.SET_HTTP: - return { ...state, http: data }; - - case ACTION.INPUT_ADD: - return { ...state, query: inputAdd(state.query, data) }; - case ACTION.INPUT_UPDATE: - return { ...state, query: inputUpdate(state.query, data) }; - case ACTION.INPUT_REMOVE: { - const inputs = cloneDeep(state.query.children); - findInput(inputs, data, true); - return { ...state, query: { ...state.query, children: inputs } }; - } - - default: - throw new Error(`Unknown action ${action}`); - } -} - -export function QueryBuilderProvider({ children }) { - const [value, dispatch] = useReducer( - reducer, - { http: {}, query: { ...root, input: '', children: [] } }, - (s) => reducer(s, { action: ACTION.SET_QUERY, data: '{"yql":""}' }) - ); - _dispatch = dispatch; - - return <context.Provider value={value}>{children}</context.Provider>; -} - -export function useQueryBuilderContext(selector) { - const func = typeof selector === 'string' ? (c) => c[selector] : selector; - return useContextSelector(context, func); -} - -export function dispatch(action, data) { - _dispatch({ action, data }); -} diff --git a/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInput.jsx b/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInput.jsx deleted file mode 100644 index 5f5a9fdbd89..00000000000 --- a/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInput.jsx +++ /dev/null @@ -1,91 +0,0 @@ -import React from 'react'; -import { OverlayTrigger, Tooltip } from 'react-bootstrap'; -import SimpleDropDownForm from 'app/pages/querybuilder/Components/Text/SimpleDropDownForm'; -import { - ACTION, - dispatch, - useQueryBuilderContext, -} from 'app/pages/querybuilder/Components/Contexts/QueryBuilderProvider'; - -export default function QueryInput() { - const { children, type } = useQueryBuilderContext('query'); - return <Inputs type={type.children} inputs={children} />; -} - -function Inputs({ id, type, inputs }) { - const usedTypes = inputs.map(({ type }) => type.name); - const remainingTypes = Object.fromEntries( - Object.entries(type).filter(([name]) => !usedTypes.includes(name)) - ); - const firstRemaining = Object.keys(remainingTypes)[0]; - return ( - <> - {inputs.map(({ id, input, type, children }) => ( - <Input - key={id} - types={remainingTypes} - {...{ id, input, type, children }} - /> - ))} - {firstRemaining && <AddPropertyButton id={id} type={firstRemaining} />} - </> - ); -} - -function Input({ id, input, types, type, children }) { - return ( - <div className="queryinput"> - <SimpleDropDownForm - onChange={({ target }) => - dispatch(ACTION.INPUT_UPDATE, { - id, - type: types[target.value], - }) - } - options={{ [type.name]: type, ...types }} - value={type.name} - /> - {children ? ( - <Inputs id={id} type={type.children} inputs={children} /> - ) : ( - <input - size="30" - onChange={({ target }) => - dispatch(ACTION.INPUT_UPDATE, { - id, - input: target.value, - }) - } - placeholder={type.type} - value={input} - /> - )} - <OverlayTrigger - placement="right" - delay={{ show: 250, hide: 400 }} - overlay={<Tooltip id="button-tooltip">Remove row</Tooltip>} - > - <span> - <button - className="removeRow" - onClick={() => dispatch(ACTION.INPUT_REMOVE, id)} - > - - - </button> - </span> - </OverlayTrigger> - <br /> - </div> - ); -} - -function AddPropertyButton({ id, type }) { - return ( - <button - className="addpropsbutton" - onClick={() => dispatch(ACTION.INPUT_ADD, { id, type })} - > - + Add property - </button> - ); -} diff --git a/client/js/app/src/app/pages/querybuilder/Components/Text/SendQuery.jsx b/client/js/app/src/app/pages/querybuilder/Components/Text/SendQuery.jsx deleted file mode 100644 index 303bc8bfc83..00000000000 --- a/client/js/app/src/app/pages/querybuilder/Components/Text/SendQuery.jsx +++ /dev/null @@ -1,56 +0,0 @@ -import React, { useState } from 'react'; -import SimpleDropDownForm from './SimpleDropDownForm'; -import { - ACTION, - dispatch, - useQueryBuilderContext, -} from 'app/pages/querybuilder/Components/Contexts/QueryBuilderProvider'; - -function send(method, url, query) { - dispatch(ACTION.SET_HTTP, { loading: true }); - fetch(url, { - method, - headers: { 'Content-Type': 'application/json;charset=utf-8' }, - body: query, - }) - .then((response) => response.json()) - .then((result) => - dispatch(ACTION.SET_HTTP, { - response: JSON.stringify(result, null, 4), - }) - ) - .catch((error) => dispatch(ACTION.SET_HTTP, { error })); -} - -export default function SendQuery() { - const messageMethods = { post: { name: 'POST' }, get: { name: 'GET' } }; - const [method, setMethod] = useState(messageMethods.post.name); - const [url, setUrl] = useState('http://localhost:8080/search/'); - const query = useQueryBuilderContext((ctx) => ctx.query.input); - - const updateMethod = (e) => { - e.preventDefault(); - const newMethod = e.target.value; - setMethod(newMethod); - }; - - return ( - <> - <SimpleDropDownForm - options={messageMethods} - value={method} - className="methodselector" - onChange={updateMethod} - /> - <input - size="30" - className="textbox" - value={url} - onChange={({ target }) => setUrl(target.value)} - /> - <button className="button" onClick={() => send(method, url, query)}> - Send - </button> - </> - ); -} diff --git a/client/js/app/src/app/pages/querybuilder/Components/Text/SimpleDropDownForm.jsx b/client/js/app/src/app/pages/querybuilder/Components/Text/SimpleDropDownForm.jsx deleted file mode 100644 index 99342a5ae81..00000000000 --- a/client/js/app/src/app/pages/querybuilder/Components/Text/SimpleDropDownForm.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; - -export default function SimpleDropDownForm({ - options, - value, - className = 'input', - ...props -}) { - return ( - <select className={className} {...props} value={value}> - {Object.values(options).map(({ name }) => ( - <option className="options" key={name} value={name}> - {name} - </option> - ))} - </select> - ); -} diff --git a/client/js/app/src/app/pages/querybuilder/assets/img/Vespa-V2.png b/client/js/app/src/app/pages/querybuilder/assets/img/Vespa-V2.png Binary files differdeleted file mode 100644 index ac87f8e94d0..00000000000 --- a/client/js/app/src/app/pages/querybuilder/assets/img/Vespa-V2.png +++ /dev/null diff --git a/client/js/app/src/app/pages/querybuilder/assets/img/VespaIcon.png b/client/js/app/src/app/pages/querybuilder/assets/img/VespaIcon.png Binary files differdeleted file mode 100644 index 33063432c20..00000000000 --- a/client/js/app/src/app/pages/querybuilder/assets/img/VespaIcon.png +++ /dev/null diff --git a/client/js/app/src/app/pages/querybuilder/assets/img/copy.svg b/client/js/app/src/app/pages/querybuilder/assets/img/copy.svg deleted file mode 100644 index eada154413a..00000000000 --- a/client/js/app/src/app/pages/querybuilder/assets/img/copy.svg +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 488.3 488.3" style="enable-background:new 0 0 488.3 488.3;" xml:space="preserve" width="512px" height="512px" class=""><g><g> - <g> - <path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z" data-original="#000000" class="active-path" data-old_color="#F8F5F5" fill="#FCFCFC"/> - <path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z" data-original="#000000" class="active-path" data-old_color="#F8F5F5" fill="#FCFCFC"/> - </g> -</g></g> </svg> diff --git a/client/js/app/src/app/pages/querybuilder/assets/img/down-arrow.svg b/client/js/app/src/app/pages/querybuilder/assets/img/down-arrow.svg deleted file mode 100644 index d78d2f9c17f..00000000000 --- a/client/js/app/src/app/pages/querybuilder/assets/img/down-arrow.svg +++ /dev/null @@ -1 +0,0 @@ -<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 36 36"><defs><style>.cls-1{clip-path:url(#clip-path);}.cls-2{clip-path:url(#clip-path-2);}.cls-3{clip-path:url(#clip-path-3);}</style><clipPath id="clip-path"><path d="M18,4.09A13.91,13.91,0,1,1,4.09,18,13.91,13.91,0,0,1,18,4.09ZM18,35A17,17,0,1,0,6,30,17,17,0,0,0,18,35Z"/></clipPath><clipPath id="clip-path-2"><rect x="-723.82" y="-837.15" width="1483.64" height="3802.85" fill="#FFFFFF"/></clipPath><clipPath id="clip-path-3"><path d="M26,13.83a1.55,1.55,0,0,0-2.16,0L18,19.75l-5.88-6A1.54,1.54,0,0,0,9.93,16L18,24.18,26.07,16a1.57,1.57,0,0,0,0-2.19Z"/></clipPath></defs><title>down-arrow</title><path d="M18,4.09A13.91,13.91,0,1,1,4.09,18,13.91,13.91,0,0,1,18,4.09ZM18,35A17,17,0,1,0,6,30,17,17,0,0,0,18,35Z"/><g class="cls-1"><rect x="-723.82" y="-837.15" width="1483.64" height="3802.85" fill="#FFFFFF"/><g class="cls-2"><rect x="-4.15" y="-4.15" width="44.3" height="44.3" fill="#FFFFFF"/></g></g><path d="M26,13.83a1.55,1.55,0,0,0-2.16,0L18,19.75l-5.88-6A1.54,1.54,0,0,0,9.93,16L18,24.18,26.07,16a1.57,1.57,0,0,0,0-2.19Z"/><g class="cls-3"><rect x="-723.82" y="-837.15" width="1483.64" height="3802.85" fill="#FFFFFF"/><g class="cls-2"><rect x="4.35" y="8.21" width="27.3" height="21.12" fill="#FFFFFF"/></g></g></svg> diff --git a/client/js/app/src/app/pages/querybuilder/assets/img/features-help.png b/client/js/app/src/app/pages/querybuilder/assets/img/features-help.png Binary files differdeleted file mode 100644 index 65702f8b91f..00000000000 --- a/client/js/app/src/app/pages/querybuilder/assets/img/features-help.png +++ /dev/null diff --git a/client/js/app/src/app/pages/querybuilder/assets/img/information.svg b/client/js/app/src/app/pages/querybuilder/assets/img/information.svg deleted file mode 100644 index da42cf2caf6..00000000000 --- a/client/js/app/src/app/pages/querybuilder/assets/img/information.svg +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0"?> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="512px" height="512px"><g><g> - <g> - <g> - <circle cx="256" cy="378.5" r="25" data-original="#000000" class="active-path" data-old_color="#898989" fill="#767474"/> - <path d="M256,0C114.516,0,0,114.497,0,256c0,141.484,114.497,256,256,256c141.484,0,256-114.497,256-256 C512,114.516,397.503,0,256,0z M256,472c-119.377,0-216-96.607-216-216c0-119.377,96.607-216,216-216 c119.377,0,216,96.607,216,216C472,375.377,375.393,472,256,472z" data-original="#000000" class="active-path" data-old_color="#898989" fill="#767474"/> - <path d="M256,128.5c-44.112,0-80,35.888-80,80c0,11.046,8.954,20,20,20s20-8.954,20-20c0-22.056,17.944-40,40-40 c22.056,0,40,17.944,40,40c0,22.056-17.944,40-40,40c-11.046,0-20,8.954-20,20v50c0,11.046,8.954,20,20,20 c11.046,0,20-8.954,20-20v-32.531c34.466-8.903,60-40.26,60-77.469C336,164.388,300.112,128.5,256,128.5z" data-original="#000000" class="active-path" data-old_color="#898989" fill="#767474"/> - </g> - </g> -</g></g> </svg> diff --git a/client/js/app/src/app/pages/querybuilder/assets/img/paste.svg b/client/js/app/src/app/pages/querybuilder/assets/img/paste.svg deleted file mode 100644 index b2edac680bf..00000000000 --- a/client/js/app/src/app/pages/querybuilder/assets/img/paste.svg +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0"?> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 561 561" style="enable-background:new 0 0 561 561;" xml:space="preserve" class=""><g><g> - <g id="content-paste"> - <path d="M459,51H351.9c-10.2-30.6-38.25-51-71.4-51c-33.15,0-61.2,20.4-71.4,51H102c-28.05,0-51,22.95-51,51v408 c0,28.05,22.95,51,51,51h357c28.05,0,51-22.95,51-51V102C510,73.95,487.05,51,459,51z M280.5,51c15.3,0,25.5,10.2,25.5,25.5 S295.8,102,280.5,102S255,91.8,255,76.5S265.2,51,280.5,51z M459,510H102V102h51v76.5h255V102h51V510z" data-original="#000000" class="active-path" data-old_color="#F9F6F6" fill="#FBF9F9"/> - </g> -</g></g> </svg> diff --git a/client/js/app/src/app/pages/querybuilder/assets/img/reload.svg b/client/js/app/src/app/pages/querybuilder/assets/img/reload.svg deleted file mode 100644 index c5381f9f232..00000000000 --- a/client/js/app/src/app/pages/querybuilder/assets/img/reload.svg +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0"?> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="512px" height="512px" class=""><g><g> - <g> - <path d="M482.195,226.196C482.195,101.471,380.725,0,256.001,0S29.805,101.471,29.805,226.196c0,7.409,6.007,13.416,13.416,13.416 s13.416-6.008,13.416-13.416c0-109.93,89.434-199.363,199.363-199.363s199.363,89.434,199.363,199.363 c0,109.928-89.434,199.362-199.363,199.362h-23.276l33.282-37.255c4.937-5.525,4.458-14.007-1.067-18.944 c-5.525-4.937-14.008-4.457-18.944,1.068l-47.576,53.255c-7.788,8.718-7.788,21.866,0,30.584l47.576,53.255 c2.651,2.968,6.322,4.478,10.01,4.478c3.181,0,6.375-1.126,8.934-3.41c5.526-4.937,6.004-13.419,1.067-18.944l-33.282-37.255 h23.276C380.725,452.39,482.195,350.919,482.195,226.196z" data-original="#000000" class="active-path" data-old_color="#F0EDED" fill="#F3F2F2"/> - </g> -</g></g> </svg> diff --git a/client/js/app/src/app/pages/querybuilder/context/__test__/query-builder-provider.test.jsx b/client/js/app/src/app/pages/querybuilder/context/__test__/query-builder-provider.test.jsx new file mode 100644 index 00000000000..5ccad2a054e --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/context/__test__/query-builder-provider.test.jsx @@ -0,0 +1,179 @@ +import { + ACTION, + reducer, +} from 'app/pages/querybuilder/context/query-builder-provider'; +import parameters from 'app/pages/querybuilder/context/parameters'; +import { cloneDeep, omitBy } from 'lodash'; + +const state = reducer(); + +test('default state', () => { + const fixed = { ...state, params: hideTypes(state.params) }; + expect(fixed).toEqual({ + http: {}, + params: { + value: [{ id: '0', value: '', type: 'yql' }], + }, + query: { + input: '{\n "yql": ""\n}', + }, + request: { + body: '{\n "yql": ""\n}', + fullUrl: 'http://localhost:8080/search/', + method: 'POST', + url: 'http://localhost:8080/search/', + }, + }); +}); + +test('manipulates inputs', () => { + function assert(state, queryJson, querySearchParams, params) { + expect(hideTypes(state.params).value).toEqual(params); + expect({ ...state.query, input: JSON.parse(state.query.input) }).toEqual( + queryJson + ); + + const spState = reducer(state, { action: ACTION.SET_METHOD, data: 'GET' }); + expect(hideTypes(spState.params).value).toEqual(params); + expect(spState.query).toEqual(querySearchParams); + } + + const s1 = reduce(state, [[ACTION.INPUT_ADD, { type: 'hits' }]]); + assert(s1, { input: { yql: '', hits: null } }, { input: 'yql=&hits=' }, [ + { id: '0', value: '', type: 'yql' }, + { id: '1', value: '', type: 'hits' }, + ]); + + const s2 = reduce(s1, [ + [ACTION.INPUT_UPDATE, { id: '1', value: '12' }], + [ACTION.INPUT_ADD, { type: 'ranking' }], + [ACTION.INPUT_UPDATE, { id: '1', type: 'offset' }], + [ACTION.INPUT_REMOVE, '0'], + [ACTION.INPUT_ADD, { id: '2', type: 'location' }], + [ACTION.INPUT_ADD, { id: '2', type: 'matchPhase' }], + [ACTION.INPUT_UPDATE, { id: '2.0', value: 'us' }], + ]); + assert( + s2, + { input: { offset: 12, ranking: { location: 'us', matchPhase: {} } } }, + { input: 'offset=12&ranking.location=us' }, + [ + { id: '1', value: '12', type: 'offset' }, + { + id: '2', + type: 'ranking', + value: [ + { id: '2.0', value: 'us', type: 'location' }, + { id: '2.1', type: 'matchPhase', value: [] }, + ], + }, + ] + ); + + assert( + reduce(s2, [[ACTION.INPUT_UPDATE, { id: '2', type: 'noCache' }]]), + { input: { offset: 12, noCache: false } }, + { input: 'offset=12&noCache=' }, + [ + { id: '1', value: '12', type: 'offset' }, + { id: '2', value: '', type: 'noCache' }, + ] + ); + + assert( + reduce(s2, [[ACTION.INPUT_REMOVE, '2']]), + { input: { offset: 12 } }, + { input: 'offset=12' }, + [{ id: '1', value: '12', type: 'offset' }] + ); +}); + +test('set query', () => { + const query = (method, input) => + reduce(state, [ + [ACTION.INPUT_REMOVE, '0'], + [ACTION.SET_METHOD, method], + [ACTION.SET_QUERY, input], + ]); + function assert(inputJson, inputSearchParams, params) { + const s2 = query('POST', inputJson); + expect(hideTypes(s2.params).value).toEqual(params); + expect(s2.query.input).toEqual(inputJson); + expect(s2.query.error).toBeUndefined(); + + if (inputSearchParams == null) return; + const s3 = query('GET', inputSearchParams); + expect(hideTypes(s3.params).value).toEqual(params); + expect(s3.query.input).toEqual(inputSearchParams); + expect(s3.query.error).toBeUndefined(); + } + + function error(method, input, error) { + const s = query(method, input); + expect(s.params.value).toEqual([]); + expect(s.query.input).toEqual(input); + expect(s.query.error).toEqual(error); + } + + assert('{"yql":"abc"}', '?yql=abc', [{ id: '0', value: 'abc', type: 'yql' }]); + + assert( + '{"hits":12,"ranking":{"location":"us","matchPhase":{"attribute":"[\\"a b\\"]"}},"noCache":true,"offset":""}', + 'hits=12&ranking.location=us&noCache=true&ranking.matchPhase.attribute=%5B%22a+b%22%5D&offset', + [ + { id: '0', value: '12', type: 'hits' }, + { + id: '1', + type: 'ranking', + value: [ + { id: '1.0', value: 'us', type: 'location' }, + { + id: '1.1', + type: 'matchPhase', + value: [{ id: '1.1.0', value: '["a b"]', type: 'attribute' }], + }, + ], + }, + { id: '2', value: 'true', type: 'noCache' }, + { id: '3', value: '', type: 'offset' }, + ] + ); + + assert('{"ranking":{"matchPhase":{}}}', null, [ + { + id: '0', + type: 'ranking', + value: [{ id: '0.0', type: 'matchPhase', value: [] }], + }, + ]); + + let msg = "Unknown property 'asd' on root level"; + error('POST', '{"asd":123}', msg); + error('GET', 'asd=123', msg); + + msg = "Unknown property 'asd' under 'matchPhase'"; + error('POST', '{"ranking":{"matchPhase":{"asd":123}}}', msg); + error('GET', 'ranking.matchPhase.asd=123', msg); + + error('POST', '{"yql":"test}', 'Unexpected end of JSON input'); + + msg = + "Property 'ranking' cannot have a value, supported children: features,freshness,listFeatures,location,matchPhase,profile,properties,queryCache,sorting"; + error('POST', '{"ranking":123}', msg); + error('GET', 'ranking=123', msg); + + error('POST', '{"yql":{}}', "Expected property 'yql' to be String"); +}); + +function hideTypes({ type, value, ...copy }) { + if (type.name) copy.type = type.name; + copy.value = type.children ? value.map(hideTypes) : value; + return copy; +} + +function reduce(state, operations) { + return operations.reduce( + (acc, [action, data]) => reducer(acc, { action, data }), + state + ); +} diff --git a/client/js/app/src/app/pages/querybuilder/parameters.jsx b/client/js/app/src/app/pages/querybuilder/context/parameters.jsx index 6557cfc0ea0..b3ca2425c9c 100644 --- a/client/js/app/src/app/pages/querybuilder/parameters.jsx +++ b/client/js/app/src/app/pages/querybuilder/context/parameters.jsx @@ -89,16 +89,6 @@ export default { timing: { name: 'timing', type: 'Boolean' }, }, }, - pos: { - name: 'pos', - type: 'Parent', - children: { - ll: { name: 'll', type: 'String' }, - radius: { name: 'radius', type: 'String' }, - bb: { name: 'bb', type: 'List' }, - attribute: { name: 'attribute', type: 'String' }, - }, - }, streaming: { name: 'streaming', type: 'Parent', diff --git a/client/js/app/src/app/pages/querybuilder/context/query-builder-provider.jsx b/client/js/app/src/app/pages/querybuilder/context/query-builder-provider.jsx new file mode 100644 index 00000000000..74585e1340c --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/context/query-builder-provider.jsx @@ -0,0 +1,217 @@ +import { last, set } from 'lodash'; +import React, { useReducer } from 'react'; +import { createContext, useContextSelector } from 'use-context-selector'; +import parameters from 'app/pages/querybuilder/context/parameters'; + +let _dispatch; +const root = { type: { children: parameters } }; +const context = createContext(null); + +export const ACTION = Object.freeze({ + SET_QUERY: 0, + SET_HTTP: 1, + SET_METHOD: 2, + SET_URL: 3, + + INPUT_ADD: 10, + INPUT_UPDATE: 11, + INPUT_REMOVE: 12, +}); + +function cloneParams(params) { + if (!Array.isArray(params.value)) return { ...params }; + return { ...params, value: params.value.map(cloneParams) }; +} + +function inputsToQuery(method, inputs) { + if (method === 'POST') { + const inputsToJson = (inputs, parent) => + Object.fromEntries( + inputs.map(({ value, type: { name, type, children } }) => [ + name, + children ? inputsToJson(value) : parseInput(value, type), + ]) + ); + return JSON.stringify(inputsToJson(inputs), null, 4); + } + + const inputsToSearchParams = (inputs, parent) => + inputs.reduce((acc, { value, type: { name, children } }) => { + const key = parent ? `${parent}.${name}` : name; + return Object.assign( + acc, + children ? inputsToSearchParams(value, key) : { [key]: value } + ); + }, {}); + return new URLSearchParams(inputsToSearchParams(inputs)).toString(); +} + +function queryToInputs(method, query) { + if (method === 'POST') return jsonToInputs(JSON.parse(query)); + + const json = [...new URLSearchParams(query).entries()].reduce( + (acc, [key, value]) => set(acc, key, value), + {} + ); + return jsonToInputs(json); +} + +function jsonToInputs(json, parent = root) { + return Object.entries(json).map(([key, value], i) => { + const node = { + id: parent.id ? `${parent.id}.${i}` : i.toString(), + type: parent.type.children[key], + }; + if (!node.type) { + const location = parent.type.name + ? `under '${parent.type.name}'` + : 'on root level'; + throw new Error(`Unknown property '${key}' ${location}`); + } + if (value != null && typeof value === 'object') { + if (!node.type.children) + throw new Error(`Expected property '${key}' to be ${node.type.type}`); + node.value = jsonToInputs(value, node); + } else { + if (node.type.children) + throw new Error( + `Property '${key}' cannot have a value, supported children: ${Object.keys( + node.type.children + ).sort()}` + ); + node.value = value?.toString(); + } + return node; + }); +} + +function parseInput(value, type) { + if (type === 'Integer' || type === 'Long') return parseInt(value); + if (type === 'Float') return parseFloat(value); + if (type === 'Boolean') return value.toLowerCase() === 'true'; + return value; +} + +function inputAdd(params, { id: parentId, type: typeName }) { + const cloned = cloneParams(params); + const parent = findInput(cloned, parentId); + + const nextId = parseInt(last(last(parent.value)?.id?.split('.')) ?? -1) + 1; + const id = parentId ? `${parentId}.${nextId}` : nextId.toString(); + const type = parent.type.children[typeName]; + + parent.value.push({ id, value: type.children ? [] : '', type }); + + return cloned; +} + +function inputUpdate(params, { id, type, value }) { + const cloned = cloneParams(params); + const node = findInput(cloned, id); + if (type) { + const parent = findInput(cloned, id.substring(0, id.lastIndexOf('.'))); + const newType = parent.type.children[type]; + if ((node.type.children != null) !== (newType.children != null)) + node.value = newType.children ? [] : ''; + node.type = newType; + } + if (value) node.value = value; + + return cloned; +} + +function findInput(params, id, Delete = false) { + if (!id) return params; + let end = -1; + while ((end = id.indexOf('.', end + 1)) > 0) + params = params.value.find((input) => input.id === id.substring(0, end)); + const index = params.value.findIndex((input) => input.id === id); + return Delete ? params.value.splice(index, 1)[0] : params.value[index]; +} + +export function reducer(state, action) { + if (state == null) { + state = { http: {}, params: {}, query: {}, request: {} }; + + return [ + [ACTION.SET_URL, 'http://localhost:8080/search/'], + [ACTION.SET_QUERY, 'yql='], + [ACTION.SET_METHOD, 'POST'], + ].reduce((s, [action, data]) => reducer(s, { action, data }), state); + } + + const result = preReducer(state, action); + const { request: sr, params: sp, query: sq } = state; + const { request: rr, params: rp, query: rq } = result; + + if ((sp.value !== rp.value && sq === rq) || sr.method !== rr.method) + result.query = { input: inputsToQuery(rr.method, rp.value) }; + + const input = result.query.input; + if (sr.url !== rr.url || sq.input !== input || sr.method !== rr.method) { + if (rr.method === 'POST') { + result.request = { ...result.request, fullUrl: rr.url, body: input }; + } else { + const url = new URL(rr.url); + url.search = input; + result.request = { + ...result.request, + fullUrl: url.toString(), + body: null, + }; + } + } + + return result; +} + +function preReducer(state, { action, data }) { + switch (action) { + case ACTION.SET_QUERY: { + try { + const value = queryToInputs(state.request.method, data); + return { + ...state, + params: { ...root, value }, + query: { input: data }, + }; + } catch (error) { + return { ...state, query: { input: data, error: error.message } }; + } + } + case ACTION.SET_HTTP: + return { ...state, http: data }; + case ACTION.SET_METHOD: + return { ...state, request: { ...state.request, method: data } }; + case ACTION.SET_URL: + return { ...state, request: { ...state.request, url: data } }; + + case ACTION.INPUT_ADD: + return { ...state, params: inputAdd(state.params, data) }; + case ACTION.INPUT_UPDATE: + return { ...state, params: inputUpdate(state.params, data) }; + case ACTION.INPUT_REMOVE: { + const cloned = cloneParams(state.params); + findInput(cloned, data, true); + return { ...state, params: cloned }; + } + + default: + throw new Error(`Unknown action ${action}`); + } +} + +export function QueryBuilderProvider({ children }) { + const [value, dispatch] = useReducer(reducer, null, reducer); + _dispatch = dispatch; + return <context.Provider value={value}>{children}</context.Provider>; +} + +export function useQueryBuilderContext(selector) { + const func = typeof selector === 'string' ? (c) => c[selector] : selector; + return useContextSelector(context, func); +} + +export function dispatch(action, data) { + _dispatch({ action, data }); +} diff --git a/client/js/app/src/app/pages/querybuilder/index.jsx b/client/js/app/src/app/pages/querybuilder/index.jsx new file mode 100644 index 00000000000..b8889dfd7c5 --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/index.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { SimpleGrid, Title } from '@mantine/core'; +import { Container, Content, Icon } from 'app/components'; +import { QueryBuilderProvider } from 'app/pages/querybuilder/context/query-builder-provider'; +import { QueryFilters } from 'app/pages/querybuilder/query-filters/query-filters'; +import { QueryDerived } from 'app/pages/querybuilder/query-derived/query-derived'; +import { QueryResponse } from 'app/pages/querybuilder/query-response/query-response'; +import QueryEndpoint from 'app/pages/querybuilder/query-endpoint/query-endpoint'; + +export function QueryBuilder() { + return ( + <QueryBuilderProvider> + <Container sx={{ rowGap: '21px' }}> + <Title order={2}> + <Icon name="arrows-to-dot" /> Query Builder + </Title> + <QueryEndpoint /> + <SimpleGrid + breakpoints={[{ maxWidth: 'sm', cols: 1 }]} + cols={3} + spacing="lg" + > + <Content> + <QueryFilters /> + </Content> + <Content> + <QueryDerived /> + </Content> + <Content> + <QueryResponse /> + </Content> + </SimpleGrid> + </Container> + </QueryBuilderProvider> + ); +} diff --git a/client/js/app/src/app/pages/querybuilder/query-builder.jsx b/client/js/app/src/app/pages/querybuilder/query-builder.jsx deleted file mode 100644 index b101e8639fb..00000000000 --- a/client/js/app/src/app/pages/querybuilder/query-builder.jsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from 'react'; -import QueryInput from './Components/Text/QueryInput'; -import SendQuery from './Components/Text/SendQuery'; -import PasteJSONButton from './Components/Buttons/PasteJSONButton'; -import CopyResponseButton from './Components/Buttons/CopyResponseButton'; -import DownloadJSONButton from './Components/Buttons/DownloadJSONButton'; -import { - QueryBuilderProvider, - useQueryBuilderContext, -} from 'app/pages/querybuilder/Components/Contexts/QueryBuilderProvider'; - -import '../../styles/agency.css'; -import '../../styles/vespa.css'; - -function QueryBox() { - const query = useQueryBuilderContext((ctx) => ctx.query.input); - return <textarea readOnly cols="70" rows="15" value={query}></textarea>; -} - -function ResponseBox() { - const response = useQueryBuilderContext((ctx) => ctx.http.response); - return ( - <> - <textarea readOnly cols="70" rows="25" value={response} /> - <CopyResponseButton /> - <DownloadJSONButton response={response}> - Download in Jeager format - </DownloadJSONButton> - </> - ); -} - -export function QueryBuilder() { - return ( - <header> - <div className="intro container"> - <p className="intro-lead-in">Vespa Search Engine</p> - <p className="intro-long"> - Select the method for sending a request and construct a query. - </p> - <QueryBuilderProvider> - <SendQuery /> - <br /> - <div id="request"> - <QueryInput /> - </div> - <br /> - <PasteJSONButton /> - <QueryBox /> - <p className="response">Response</p> - <ResponseBox /> - </QueryBuilderProvider> - <br /> - <br /> - </div> - </header> - ); -} diff --git a/client/js/app/src/app/pages/querybuilder/query-derived/query-derived.jsx b/client/js/app/src/app/pages/querybuilder/query-derived/query-derived.jsx new file mode 100644 index 00000000000..fca06defc5d --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/query-derived/query-derived.jsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { + Badge, + Group, + Stack, + Button, + CopyButton, + Textarea, +} from '@mantine/core'; +import { + ACTION, + dispatch, + useQueryBuilderContext, +} from 'app/pages/querybuilder/context/query-builder-provider'; +import { Icon } from 'app/components'; + +export function QueryDerived() { + const { input, error } = useQueryBuilderContext('query'); + + return ( + <Stack> + <Group position="apart"> + <Badge variant="filled">Query</Badge> + <Group spacing="xs"> + <CopyButton value={input}> + {({ copied, copy }) => ( + <Button + leftIcon={<Icon name={copied ? 'check' : 'copy'} />} + color={copied ? 'teal' : 'blue'} + variant="outline" + onClick={copy} + size="xs" + compact + > + Copy + </Button> + )} + </CopyButton> + </Group> + </Group> + <Textarea + styles={(theme) => ({ + input: { + fontFamily: theme.fontFamilyMonospace, + fontSize: theme.fontSizes.xs, + }, + })} + value={input} + error={error} + onChange={({ target }) => dispatch(ACTION.SET_QUERY, target.value)} + variant="unstyled" + minRows={21} + autosize + /> + </Stack> + ); +} diff --git a/client/js/app/src/app/pages/querybuilder/query-endpoint/query-endpoint.jsx b/client/js/app/src/app/pages/querybuilder/query-endpoint/query-endpoint.jsx new file mode 100644 index 00000000000..09d52640936 --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/query-endpoint/query-endpoint.jsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { Select, TextInput, Button } from '@mantine/core'; +import { errorMessage } from 'app/libs/notification'; +import { + ACTION, + dispatch, + useQueryBuilderContext, +} from 'app/pages/querybuilder/context/query-builder-provider'; +import { Container, Content } from 'app/components'; + +function send(event, method, url, body) { + event.preventDefault(); + dispatch(ACTION.SET_HTTP, { loading: true }); + fetch(url, { + method, + headers: { 'Content-Type': 'application/json;charset=utf-8' }, + body, + }) + .then((response) => response.json()) + .then((result) => + dispatch(ACTION.SET_HTTP, { + response: JSON.stringify(result, null, 4), + }) + ) + .catch((error) => { + errorMessage(error.message); + dispatch(ACTION.SET_HTTP, {}); + }); +} + +export default function QueryEndpoint() { + const { method, url, fullUrl, body } = useQueryBuilderContext('request'); + const hasError = useQueryBuilderContext((ctx) => ctx.query.error != null); + const loading = useQueryBuilderContext((ctx) => ctx.http.loading); + + return ( + <Content> + <form onSubmit={(event) => send(event, method, fullUrl, body)}> + <Container sx={{ gridTemplateColumns: 'max-content auto max-content' }}> + <Select + data={['POST', 'GET']} + onChange={(value) => dispatch(ACTION.SET_METHOD, value)} + value={method} + radius={0} + /> + <TextInput + onChange={(e) => dispatch(ACTION.SET_URL, e.currentTarget.value)} + value={url} + radius={0} + /> + <Button + radius={0} + type="submit" + loading={loading} + disabled={hasError} + > + Send + </Button> + </Container> + </form> + </Content> + ); +} diff --git a/client/js/app/src/app/pages/querybuilder/query-filters/query-filters.jsx b/client/js/app/src/app/pages/querybuilder/query-filters/query-filters.jsx new file mode 100644 index 00000000000..178270eb71f --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/query-filters/query-filters.jsx @@ -0,0 +1,128 @@ +import React from 'react'; +import { + Select, + TextInput, + ActionIcon, + Button, + Box, + Stack, + Badge, + Group, +} from '@mantine/core'; +import { Container, Content, Icon } from 'app/components'; +import { + ACTION, + dispatch, + useQueryBuilderContext, +} from 'app/pages/querybuilder/context/query-builder-provider'; +import { SHADE } from 'app/styles/theme/colors'; + +function AddProperty(props) { + return ( + <Button leftIcon={<Icon name="plus" />} {...props}> + Add property + </Button> + ); +} + +function Input({ id, value, types, type }) { + const options = { [type.name]: type, ...types }; + return ( + <> + <Box sx={{ display: 'flex', alignItems: 'center', gap: '5px' }}> + <Select + sx={{ flex: 1 }} + data={Object.values(options).map(({ name }) => name)} + onChange={(type) => dispatch(ACTION.INPUT_UPDATE, { id, type })} + value={type.name} + searchable + /> + {!type.children && ( + <TextInput + sx={{ flex: 1 }} + onChange={(event) => + dispatch(ACTION.INPUT_UPDATE, { + id, + value: event.currentTarget.value, + }) + } + placeholder={type.type} + value={value} + /> + )} + <ActionIcon onClick={() => dispatch(ACTION.INPUT_REMOVE, id)}> + <Icon name="circle-minus" /> + </ActionIcon> + </Box> + {type.children && ( + <Box + py={8} + sx={(theme) => ({ + borderLeft: `1px dashed ${theme.fn.themeColor( + 'gray', + SHADE.UI_ELEMENT_BORDER_AND_FOCUS + )}`, + marginLeft: '13px', + paddingLeft: '13px', + })} + > + <Inputs id={id} type={type.children} inputs={value} /> + </Box> + )} + </> + ); +} + +function Inputs({ id, type, inputs }) { + const usedTypes = inputs.map(({ type }) => type.name); + const remainingTypes = Object.fromEntries( + Object.entries(type).filter(([name]) => !usedTypes.includes(name)) + ); + const firstRemaining = Object.keys(remainingTypes)[0]; + return ( + <Container sx={{ rowGap: '5px' }}> + {inputs.map(({ id, value, type }) => ( + <Input key={id} types={remainingTypes} {...{ id, value, type }} /> + ))} + {firstRemaining && ( + <> + {id != null ? ( + <Container sx={{ justifyContent: 'start' }}> + <AddProperty + onClick={() => + dispatch(ACTION.INPUT_ADD, { id, type: firstRemaining }) + } + variant="subtle" + size="xs" + compact + /> + </Container> + ) : ( + <AddProperty + onClick={() => + dispatch(ACTION.INPUT_ADD, { id, type: firstRemaining }) + } + mt={13} + /> + )} + </> + )} + </Container> + ); +} + +export function QueryFilters() { + const { value, type } = useQueryBuilderContext('params'); + return ( + <Stack> + <Group> + <Badge variant="filled">Parameters</Badge> + </Group> + <Container sx={{ alignContent: 'start' }}> + <Content padding={0}> + <Inputs type={type.children} inputs={value} /> + </Content> + </Container> + </Stack> + ); +} diff --git a/client/js/app/src/app/pages/querybuilder/query-response/download-jeager.jsx b/client/js/app/src/app/pages/querybuilder/query-response/download-jeager.jsx new file mode 100644 index 00000000000..4130172a329 --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/query-response/download-jeager.jsx @@ -0,0 +1,55 @@ +import { Button } from '@mantine/core'; +import React from 'react'; +import { errorMessage } from 'app/libs/notification'; +import { Icon } from 'app/components'; +import transform from 'app/pages/querybuilder/TransformVespaTrace'; + +// copied from safakeskin´s answer on SO, link: https://stackoverflow.com/questions/55613438/reactwrite-to-json-file-or-export-download-no-server +function downloadFile(filename, blob) { + const href = URL.createObjectURL(blob); + + // create "a" HTML element with href to file + const link = document.createElement('a'); + link.href = href; + link.download = filename; + document.body.appendChild(link); + link.click(); + + // clean up "a" element & remove ObjectURL + document.body.removeChild(link); + URL.revokeObjectURL(href); +} + +export function DownloadJeager({ response, ...props }) { + const handleClick = () => { + try { + const json = JSON.parse(response); + + try { + const content = JSON.stringify(transform(json), null, 4); + downloadFile( + 'vespa-response.json', + new Blob([content], { type: 'application/json' }) + ); + } catch (error) { + errorMessage( + 'Request must be made with tracelevel ≥ 4', + 'Failed to transform response to Jaeger format' + ); + } + } catch (error) { + errorMessage(error.message); + } + }; + + return ( + <Button + {...props} + leftIcon={<Icon name="download" />} + onClick={handleClick} + disabled={!(response?.length > 0)} + > + Jaeger Format + </Button> + ); +} diff --git a/client/js/app/src/app/pages/querybuilder/query-response/query-response.jsx b/client/js/app/src/app/pages/querybuilder/query-response/query-response.jsx new file mode 100644 index 00000000000..56562ae1717 --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/query-response/query-response.jsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { + Badge, + Button, + Group, + Stack, + CopyButton, + Textarea, +} from '@mantine/core'; +import { DownloadJeager } from 'app/pages/querybuilder/query-response/download-jeager'; +import { useQueryBuilderContext } from 'app/pages/querybuilder/context/query-builder-provider'; +import { Icon } from 'app/components'; + +export function QueryResponse() { + const response = useQueryBuilderContext((ctx) => ctx.http.response); + + return ( + <Stack> + <Group position="apart"> + <Badge variant="filled">Response</Badge> + <Group spacing="xs"> + <CopyButton value={response}> + {({ copied, copy }) => ( + <Button + leftIcon={<Icon name={copied ? 'check' : 'copy'} />} + color={copied ? 'teal' : 'blue'} + variant="outline" + onClick={copy} + size="xs" + compact + > + Copy + </Button> + )} + </CopyButton> + <DownloadJeager + variant="outline" + size="xs" + compact + response={response} + /> + </Group> + </Group> + <Textarea + styles={(theme) => ({ + input: { + fontFamily: theme.fontFamilyMonospace, + fontSize: theme.fontSizes.xs, + }, + })} + value={response ?? ''} + variant="unstyled" + minRows={21} + autosize + /> + </Stack> + ); +} diff --git a/client/js/app/src/app/pages/querytracer/query-tracer.jsx b/client/js/app/src/app/pages/querytracer/query-tracer.jsx index c3212c70c8a..758182d4f3f 100644 --- a/client/js/app/src/app/pages/querytracer/query-tracer.jsx +++ b/client/js/app/src/app/pages/querytracer/query-tracer.jsx @@ -1,21 +1,25 @@ import React, { useState } from 'react'; -import DownloadJSONButton from '../querybuilder/Components/Buttons/DownloadJSONButton'; -import { Container } from 'app/components'; +import { Stack, Textarea } from '@mantine/core'; +import { DownloadJeager } from 'app/pages/querybuilder/query-response/download-jeager'; export function QueryTracer() { const [response, setResponse] = useState(''); return ( - <Container> - <textarea - cols="70" - rows="25" + <Stack> + <Textarea + styles={(theme) => ({ + input: { + fontFamily: theme.fontFamilyMonospace, + fontSize: theme.fontSizes.xs, + }, + })} + minRows={21} + autosize value={response} onChange={({ target }) => setResponse(target.value)} - ></textarea> - <DownloadJSONButton response={response}> - Download in Jeager format - </DownloadJSONButton> - </Container> + /> + <DownloadJeager fullWidth response={response} /> + </Stack> ); } diff --git a/client/js/app/src/app/styles/agency.css b/client/js/app/src/app/styles/agency.css deleted file mode 100644 index e17809338c6..00000000000 --- a/client/js/app/src/app/styles/agency.css +++ /dev/null @@ -1,895 +0,0 @@ -/*! - * Start Bootstrap - Agency Bootstrap Theme (http://startbootstrap.com) - * Code licensed under the Apache License v2.0. - * For details, see http://www.apache.org/licenses/LICENSE-2.0. - */ -:root { - --primary: #188fff; - --secondary: #003abc; - --secondary-dark: #333; - --muted: #777; - - --fontprimary: HelveticaNeue, Helvetica, Arial, sans-serif; - --fontsecondary: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; -} - -body { - overflow-x: hidden; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - color: var(--secondary-dark); -} - -.text-muted { - color: var(--muted); -} - -.text-primary { - color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -p { - font-size: 14px; - line-height: 1.75; -} - -p.large { - font-size: 16px; -} - -a, -a:hover, -a:focus, -a:active, -a.active { - outline: 0; -} - -a { - color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -a:hover, -a:focus, -a:active, -a.active { - color: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-weight: 700; -} - -.img-centered { - margin: 0 auto; -} - -.bg-light-gray { - background-color: #f7f7f7; -} - -.bg-darkest-gray { - background-color: #222; -} - -.btn-primary { - border-color: HelveticaNeue, Helvetica, Arial, sans-serif; - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-weight: 700; - color: #fff; - background-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.open .dropdown-toggle.btn-primary { - border-color: HelveticaNeue, Helvetica, Arial, sans-serif; - color: #fff; - background-color: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; -} - -.btn-primary:active, -.btn-primary.active, -.open .dropdown-toggle.btn-primary { - background-image: none; -} - -.btn-primary.disabled, -.btn-primary[disabled], -fieldset[disabled] .btn-primary, -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled:active, -.btn-primary[disabled]:active, -fieldset[disabled] .btn-primary:active, -.btn-primary.disabled.active, -.btn-primary[disabled].active, -fieldset[disabled] .btn-primary.active { - border-color: HelveticaNeue, Helvetica, Arial, sans-serif; - background-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.btn-primary .badge { - color: HelveticaNeue, Helvetica, Arial, sans-serif; - background-color: #fff; -} - -.btn-xl { - padding: 20px 40px; - border-color: HelveticaNeue, Helvetica, Arial, sans-serif; - border-radius: 3px; - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-size: 18px; - font-weight: 700; - color: #fff; - background-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.btn-xl:hover, -.btn-xl:focus, -.btn-xl:active, -.btn-xl.active, -.open .dropdown-toggle.btn-xl { - border-color: HelveticaNeue, Helvetica, Arial, sans-serif; - color: #fff; - background-color: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; -} - -.btn-xl:active, -.btn-xl.active, -.open .dropdown-toggle.btn-xl { - background-image: none; -} - -.btn-xl.disabled, -.btn-xl[disabled], -fieldset[disabled] .btn-xl, -.btn-xl.disabled:hover, -.btn-xl[disabled]:hover, -fieldset[disabled] .btn-xl:hover, -.btn-xl.disabled:focus, -.btn-xl[disabled]:focus, -fieldset[disabled] .btn-xl:focus, -.btn-xl.disabled:active, -.btn-xl[disabled]:active, -fieldset[disabled] .btn-xl:active, -.btn-xl.disabled.active, -.btn-xl[disabled].active, -fieldset[disabled] .btn-xl.active { - border-color: HelveticaNeue, Helvetica, Arial, sans-serif; - background-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.btn-xl .badge { - color: HelveticaNeue, Helvetica, Arial, sans-serif; - background-color: #fff; -} - -.navbar-default { - border-color: transparent; - background-color: #222; -} - -.navbar-default .navbar-brand { - font-family: 'Kaushan Script', 'Helvetica Neue', Helvetica, Arial, cursive; - color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.navbar-default .navbar-brand:hover, -.navbar-default .navbar-brand:focus, -.navbar-default .navbar-brand:active, -.navbar-default .navbar-brand.active { - color: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; -} - -.navbar-default .navbar-collapse { - border-color: rgba(255, 255, 255, 0.02); -} - -.navbar-default .navbar-toggle { - border-color: HelveticaNeue, Helvetica, Arial, sans-serif; - background-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.navbar-default .navbar-toggle .icon-bar { - background-color: #fff; -} - -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.navbar-default .nav li a { - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-weight: 400; - letter-spacing: 1px; - color: #fff; - -webkit-transition: all ease 0.35s; - -moz-transition: all ease 0.35s; - transition: all ease 0.35s; -} - -.navbar-default .nav li a:hover, -.navbar-default .nav li a:focus { - outline: 0; - color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.navbar-default .navbar-nav > .active > a { - border-radius: 0; - color: #fff; - background-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.navbar-default .navbar-nav > .active > a:hover, -.navbar-default .navbar-nav > .active > a:focus { - color: #fff; - background-color: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; -} - -@media (min-width: 768px) { - .navbar-default { - padding: 25px 0; - border: 0; - background-color: transparent; - -webkit-transition: padding 0.3s; - -moz-transition: padding 0.3s; - transition: padding 0.3s; - } - - .navbar-default .navbar-brand { - font-size: 2em; - -webkit-transition: all 0.3s; - -moz-transition: all 0.3s; - transition: all 0.3s; - } - - .navbar-default .navbar-nav > .active > a { - border-radius: 3px; - } - - .navbar-default.navbar-shrink { - padding: 10px 0; - background-color: #222; - } - - .navbar-default.navbar-shrink .navbar-brand { - font-size: 1.5em; - } -} - -header { - text-align: center; - color: #fff; - background-attachment: scroll; - /*background-image: url('../img/header-bg.png');*/ - background-position: center center; - background-repeat: none; - -webkit-background-size: cover; - -moz-background-size: cover; - background-size: cover; - -o-background-size: cover; -} - -header .intro-text { - padding-top: 100px; - padding-bottom: 50px; -} - -header .intro-text .intro-lead-in { - margin-bottom: 25px; - font-family: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; - font-size: 22px; - font-style: italic; - line-height: 22px; -} - -header .intro-text .intro-heading { - margin-bottom: 25px; - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-size: 50px; - font-weight: 700; - line-height: 50px; -} - -@media (min-width: 768px) { - header .intro-text { - padding-top: 300px; - padding-bottom: 200px; - } - - header .intro-text .intro-lead-in { - margin-bottom: 25px; - font-family: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; - font-size: 40px; - font-style: italic; - line-height: 40px; - } - - header .intro-text .intro-heading { - margin-bottom: 50px; - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-size: 75px; - font-weight: 700; - line-height: 75px; - } -} - -section { - padding: 100px 0; -} - -section h2.section-heading { - margin-top: 0; - margin-bottom: 15px; - font-size: 40px; -} - -section h3.section-subheading { - margin-bottom: 75px; - text-transform: none; - font-family: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; - font-size: 16px; - font-style: italic; - font-weight: 400; -} - -@media (min-width: 768px) { - section { - padding: 150px 0; - } -} - -.service-heading { - margin: 15px 0; - text-transform: none; -} - -#portfolio .portfolio-item { - right: 0; - margin: 0 0 15px; -} - -#portfolio .portfolio-item .portfolio-link { - display: block; - position: relative; - margin: 0 auto; - max-width: 400px; -} - -#portfolio .portfolio-item .portfolio-link .portfolio-hover { - position: absolute; - width: 100%; - height: 100%; - opacity: 0; - -webkit-transition: all ease 0.5s; - -moz-transition: all ease 0.5s; - transition: all ease 0.5s; - background: rgba(254, 209, 54, 0.9); /* Fallback when no plugin support */ - background: rgba(var(--primary) | hex_to_rgb | join: ','}}, 0.9); -} - -#portfolio .portfolio-item .portfolio-link .portfolio-hover:hover { - opacity: 1; -} - -#portfolio - .portfolio-item - .portfolio-link - .portfolio-hover - .portfolio-hover-content { - position: absolute; - top: 50%; - width: 100%; - height: 20px; - margin-top: -12px; - text-align: center; - font-size: 20px; - color: #fff; -} - -#portfolio - .portfolio-item - .portfolio-link - .portfolio-hover - .portfolio-hover-content - i { - margin-top: -12px; -} - -#portfolio - .portfolio-item - .portfolio-link - .portfolio-hover - .portfolio-hover-content - h3, -#portfolio - .portfolio-item - .portfolio-link - .portfolio-hover - .portfolio-hover-content - h4 { - margin: 0; -} - -#portfolio .portfolio-item .portfolio-caption { - margin: 0 auto; - padding: 25px; - max-width: 400px; - text-align: center; - background-color: #fff; -} - -#portfolio .portfolio-item .portfolio-caption h4 { - margin: 0; - text-transform: none; -} - -#portfolio .portfolio-item .portfolio-caption p { - margin: 0; - font-family: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; - font-size: 16px; - font-style: italic; -} - -#portfolio * { - z-index: 2; -} - -@media (min-width: 767px) { - #portfolio .portfolio-item { - margin: 0 0 30px; - } -} - -.timeline { - position: relative; - padding: 0; - list-style: none; -} - -.timeline:before { - content: ''; - position: absolute; - top: 0; - bottom: 0; - left: 40px; - width: 2px; - margin-left: -1.5px; - background-color: #f1f1f1; -} - -.timeline > li { - position: relative; - margin-bottom: 50px; - min-height: 50px; -} - -.timeline > li:before, -.timeline > li:after { - content: ' '; - display: table; -} - -.timeline > li:after { - clear: both; -} - -.timeline > li .timeline-panel { - float: right; - position: relative; - width: 100%; - padding: 0 20px 0 100px; - text-align: left; -} - -.timeline > li .timeline-panel:before { - right: auto; - left: -15px; - border-right-width: 15px; - border-left-width: 0; -} - -.timeline > li .timeline-panel:after { - right: auto; - left: -14px; - border-right-width: 14px; - border-left-width: 0; -} - -.timeline > li .timeline-image { - z-index: 100; - position: absolute; - left: 0; - width: 80px; - height: 80px; - margin-left: 0; - border: 7px solid #f1f1f1; - border-radius: 100%; - text-align: center; - color: #fff; - background-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.timeline > li .timeline-image h4 { - margin-top: 12px; - font-size: 10px; - line-height: 14px; -} - -.timeline > li.timeline-inverted > .timeline-panel { - float: right; - padding: 0 20px 0 100px; - text-align: left; -} - -.timeline > li.timeline-inverted > .timeline-panel:before { - right: auto; - left: -15px; - border-right-width: 15px; - border-left-width: 0; -} - -.timeline > li.timeline-inverted > .timeline-panel:after { - right: auto; - left: -14px; - border-right-width: 14px; - border-left-width: 0; -} - -.timeline > li:last-child { - margin-bottom: 0; -} - -.timeline .timeline-heading h4 { - margin-top: 0; - color: inherit; -} - -.timeline .timeline-heading h4.subheading { - text-transform: none; -} - -.timeline .timeline-body > p, -.timeline .timeline-body > ul { - margin-bottom: 0; -} - -@media (min-width: 768px) { - .timeline:before { - left: 50%; - } - - .timeline > li { - margin-bottom: 100px; - min-height: 100px; - } - - .timeline > li .timeline-panel { - float: left; - width: 41%; - padding: 0 20px 20px 30px; - text-align: right; - } - - .timeline > li .timeline-image { - left: 50%; - width: 100px; - height: 100px; - margin-left: -50px; - } - - .timeline > li .timeline-image h4 { - margin-top: 16px; - font-size: 13px; - line-height: 18px; - } - - .timeline > li.timeline-inverted > .timeline-panel { - float: right; - padding: 0 30px 20px 20px; - text-align: left; - } -} - -@media (min-width: 992px) { - .timeline > li { - min-height: 150px; - } - - .timeline > li .timeline-panel { - padding: 0 20px 20px; - } - - .timeline > li .timeline-image { - width: 150px; - height: 150px; - margin-left: -75px; - } - - .timeline > li .timeline-image h4 { - margin-top: 30px; - font-size: 18px; - line-height: 26px; - } - - .timeline > li.timeline-inverted > .timeline-panel { - padding: 0 20px 20px; - } -} - -@media (min-width: 1200px) { - .timeline > li { - min-height: 170px; - } - - .timeline > li .timeline-panel { - padding: 0 20px 20px 100px; - } - - .timeline > li .timeline-image { - width: 170px; - height: 170px; - margin-left: -85px; - } - - .timeline > li .timeline-image h4 { - margin-top: 40px; - } - - .timeline > li.timeline-inverted > .timeline-panel { - padding: 0 100px 20px 20px; - } -} - -.team-member { - margin-bottom: 50px; - text-align: center; -} - -.team-member img { - margin: 0 auto; - border: 7px solid #fff; -} - -.team-member h4 { - margin-top: 25px; - margin-bottom: 0; - text-transform: none; -} - -.team-member p { - margin-top: 0; -} - -aside.clients img { - margin: 50px auto; -} - -section#contact { - background-color: #222; - /* background-image: url('../img/map-image.png'); */ - background-position: center; - background-repeat: no-repeat; -} - -section#contact .section-heading { - color: #fff; -} - -section#contact .form-group { - margin-bottom: 25px; -} - -section#contact .form-group input, -section#contact .form-group textarea { - padding: 20px; -} - -section#contact .form-group input.form-control { - height: auto; -} - -section#contact .form-group textarea.form-control { - height: 236px; -} - -section#contact .form-control:focus { - border-color: HelveticaNeue, Helvetica, Arial, sans-serif; - box-shadow: none; -} - -section#contact::-webkit-input-placeholder { - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-weight: 700; - color: #bbb; -} - -section#contact:-moz-placeholder { - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-weight: 700; - color: #bbb; -} - -section#contact::-moz-placeholder { - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-weight: 700; - color: #bbb; -} - -section#contact:-ms-input-placeholder { - text-transform: uppercase; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - font-weight: 700; - color: #bbb; -} - -section#contact .text-danger { - color: #e74c3c; -} - -footer { - padding: 25px 0; - text-align: center; -} - -footer span.copyright { - text-transform: uppercase; - text-transform: none; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - line-height: 40px; -} - -footer ul.quicklinks { - margin-bottom: 0; - text-transform: uppercase; - text-transform: none; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; - line-height: 40px; -} - -ul.social-buttons { - margin-bottom: 0; -} - -ul.social-buttons li a { - display: block; - width: 40px; - height: 40px; - border-radius: 100%; - font-size: 20px; - line-height: 40px; - outline: 0; - color: #fff; - background-color: #222; - -webkit-transition: all 0.3s; - -moz-transition: all 0.3s; - transition: all 0.3s; -} - -ul.social-buttons li a:hover, -ul.social-buttons li a:focus, -ul.social-buttons li a:active { - background-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -.btn:focus, -.btn:active, -.btn.active, -.btn:active:focus { - outline: 0; -} - -.portfolio-modal .modal-content { - padding: 100px 0; - min-height: 100%; - border: 0; - border-radius: 0; - text-align: center; - background-clip: border-box; - -webkit-box-shadow: none; - box-shadow: none; -} - -.portfolio-modal .modal-content h2 { - margin-bottom: 15px; - font-size: 3em; -} - -.portfolio-modal .modal-content p { - margin-bottom: 30px; -} - -.portfolio-modal .modal-content p.item-intro { - margin: 20px 0 30px; - font-family: HelveticaNeue-Thin, Helvetica, Arial, sans-serif; - font-size: 16px; - font-style: italic; -} - -.portfolio-modal .modal-content ul.list-inline { - margin-top: 0; - margin-bottom: 30px; -} - -.portfolio-modal .modal-content img { - margin-bottom: 30px; -} - -.portfolio-modal .close-modal { - position: absolute; - top: 25px; - right: 25px; - width: 75px; - height: 75px; - background-color: transparent; - cursor: pointer; -} - -.portfolio-modal .close-modal:hover { - opacity: 0.3; -} - -.portfolio-modal .close-modal .lr { - z-index: 1051; - width: 1px; - height: 75px; - margin-left: 35px; - background-color: #222; - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - transform: rotate(45deg); -} - -.portfolio-modal .close-modal .lr .rl { - z-index: 1052; - width: 1px; - height: 75px; - background-color: #222; - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} - -::-moz-selection { - text-shadow: none; - background: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -::selection { - text-shadow: none; - background: HelveticaNeue, Helvetica, Arial, sans-serif; -} - -img::selection { - background: 0 0; -} - -img::-moz-selection { - background: 0 0; -} - -body { - webkit-tap-highlight-color: HelveticaNeue, Helvetica, Arial, sans-serif; -} diff --git a/client/js/app/src/app/styles/theme/components.js b/client/js/app/src/app/styles/theme/components.js new file mode 100644 index 00000000000..0994ad322d0 --- /dev/null +++ b/client/js/app/src/app/styles/theme/components.js @@ -0,0 +1,10 @@ +export const components = { + AppShell: { + styles: () => ({ + main: { + maxWidth: '1920px', + margin: '0 auto', + }, + }), + }, +}; diff --git a/client/js/app/src/app/styles/theme/index.js b/client/js/app/src/app/styles/theme/index.js index fbd74bf13fc..2c69eb2af81 100644 --- a/client/js/app/src/app/styles/theme/index.js +++ b/client/js/app/src/app/styles/theme/index.js @@ -1,6 +1,7 @@ import { common } from 'app/styles/theme/common'; +import { components } from 'app/styles/theme/components'; import { commonColors } from 'app/styles/theme/common-colors'; export const getTheme = () => { - return { ...common, colors: commonColors }; + return { ...common, components, colors: commonColors }; }; diff --git a/client/js/app/src/app/styles/vespa.css b/client/js/app/src/app/styles/vespa.css deleted file mode 100644 index 4017f0275c3..00000000000 --- a/client/js/app/src/app/styles/vespa.css +++ /dev/null @@ -1,752 +0,0 @@ -/** -* Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -* Based on vespa.css from https://github.com/vespa-engine/frontpage for header- and footer-elements -*/ -:root { - --primary: #188fff; - --secondary: #003abc; - --secondary-dark: #333; - --muted: #777; - - --fontprimary: 'Hind Madurai', Helvetica, Arial, sans-serif; - --fontsecondary: 'Hind Madurai', Helvetica, Arial, sans-serif; -} - -.bg-light-blue { - background-image: linear-gradient( - -1deg, - rgba(63, 157, 216, 0.08) 0%, - rgba(163, 195, 215, 0.08) 97% - ); -} - -.yql { -} - -.yql:focus { - outline: none; -} - -.information { - margin-left: -40px; - margin-right: 28px; - margin-top: -2.5px; - opacity: 0.6; - transition: transform 0.1s; /* Animation */ -} - -.information:hover { - transform: scale(1.05); -} - -/*** Tooltips! ***/ -.tip { - visibility: visible; - border-bottom: 1px dotted; - position: relative; - cursor: help; - text-decoration: none; - color: #fff !important; -} -.tip span { - display: none; - z-index: 100; - position: absolute; - padding: 0.6em; - padding-left: 1em; - top: 1.5em; - left: 2.4em; - width: 15em; - background-color: #4da2d6; - border: 1px solid #ffffff; - border-radius: 0.5em; -} - -.tip span td { - text-align: left; - vertical-align: top; - padding-left: 5px; -} - -.tip span a { - text-decoration: none; - color: white; -} - -.tip:hover span { - display: inline-block; -} -.sg-question-set, -.sg-type-radio ul.sg-list-vertical li, -.sg-type-checkbox ul.sg-list-vertical li, -.sg-question-options, -.sg-type-radio-likert .sg-question-options, -.sg-type-table .sg-question-options, -.sg-instructions { - overflow: visible; -} - -section h2.section-heading, -section h2.section-subheading, -section h3.section-heading, -section h3.section-subheading { - text-transform: none; - font-family: 'Hind Madurai', Helvetica, Arial, sans-serif; - font-weight: normal; - font-style: normal; -} - -section h2.section-heading, -section h3.section-heading { - font-size: 50px; - color: #3f9dd8; - margin-bottom: 5px; -} - -section h2.section-subheading, -section h3.section-subheading { - line-height: 26px; - margin-top: 0; -} - -header .help-title { - color: #ffc43c; - text-transform: uppercase; - font-weight: bold; -} - -.text-muted { - color: #303030; -} - -#banner { - background-color: #336699; - color: #ffffff; - font-weight: bold; - padding-bottom: 2px; - padding-top: 2px; - width: 100%; -} - -#banner a { - color: #ffffff; - text-decoration: underline; -} - -.navbar-default { - background-color: #005a8e; - padding: 0; - border-bottom: 2px solid rgba(255, 255, 255, 0.2); -} - -.navbar-default .navbar-header { - margin-left: 13px; -} - -.navbar-default .navbar-brand { - background: transparent url('https://vespa.ai/assets/vespa-logo.png') - no-repeat; - background-size: contain; - direction: ltr; - text-indent: -9000px; - height: 28px; - width: 100px; - display: inline-block; - font-family: 'Hind Madurai', Helvetica, Arial, sans-serif; - font-weight: bold; - color: var(--primary); - margin-top: 16px; - margin-left: 10px; -} - -.navbar-nav .nav-link { - font-weight: bold; - font-size: 14px; - letter-spacing: 1px; - color: #ffffff; - text-transform: none; - font-family: 'Hind Madurai', Helvetica, Arial, sans-serif; -} - -.navbar-default .navbar-nav > a:hover, -.navbar-default .navbar-nav > .active > a, -.navbar-default .navbar-nav > .active > a:hover { - color: #ffc43c; -} - -.navbar-default .navbar-toggler-icon { - background-image: url('data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 30 30%27%3e%3cpath stroke=%27rgba%280, 0, 0, 0.55%29%27 stroke-linecap=%27round%27 stroke-miterlimit=%2710%27 stroke-width=%272%27 d=%27M4 7h22M4 15h22M4 23h22%27/%3e%3c/svg%3e'); -} - -.navbar-default .navbar-toggler { - margin-right: 45px; - border: 1px solid; - border-color: #1a242f; -} -.navbar-toggler:hover, -.navbar-default .navbar-toggler:focus { - background-color: #1a242f; - box-shadow: 0 0 0 0; -} - -.navbar-toggle { - margin-right: 45px; -} - -/* Trick to prevent anchored links to hide heading behind navbar */ -section[id]:before { - display: block; - content: ' '; - margin-top: -80px; - height: 100px; - visibility: hidden; -} - -header { - /*background-image: linear-gradient(0deg, #98C1DB 7%, #3F9DD8 100%); */ - background-color: #005a8e; - min-height: 1150px; -} - -@media (max-height: 1150px) { - header { - min-height: 100vh; - } -} - -header .intro { - margin-top: -80px; - max-width: 350px; - padding-top: 10px; - padding-bottom: 50px; -} - -header .intro-logo { - max-width: 120px; - padding-bottom: 30px; -} - -header .intro-button { - box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); - padding-left: 50px; - padding-right: 50px; -} - -header .intro-long { - line-height: 27px; - font-size: 16px; - padding-bottom: 20px; -} - -header .intro-param { - line-height: 27px; - font-size: 16px; - padding-bottom: 0px; - margin-bottom: 5px; -} -header .response { - line-height: 27px; - font-size: 20px; - padding-top: 10px; - padding-bottom: 8px; -} - -header .methodselector { - font-size: 15px; - color: #fff; - background-color: #99c1da; - width: 70px; - height: 25px; - border-width: 0px; - -o-transition: 0.3s; - -ms-transition: 0.3s; - -moz-transition: 0.3s; - -webkit-transition: 0.3s; - transition: 0.3s; -} -header .intro-help:hover { - background-color: #4ea2d6 !important; -} -header .methodselector:hover { - background-color: #79b4d8; -} -header .button:hover { - background-color: #79b4d8; -} -header .removeRow:hover { - background-color: #79b4d8; -} -header .addRow:hover { - background-color: #79b4d8; -} -header .showJSON:hover { - background-color: #79b4d8; -} -header .copyURL:hover { - background-color: #79b4d8; -} -header .copyJSON:hover { - background-color: #79b4d8; -} -header .methodselector:focus { - outline: none; -} -header .textbox:focus { - outline: none; -} -header .input:focus { - outline: none; -} -header .responsebox::selection { - background-color: grey; -} -header .textbox::selection { - background-color: grey; -} -header .input::selection { - background-color: grey; -} -header .propvalue::selection { - background-color: grey; -} -header .responsebox:focus { - outline: none; -} -header .responseinfo:focus { - outline: none; -} -header .propvalue:focus { - outline: none; -} -header .addpropsbutton:focus { - outline: none; -} - -header .input { - color: #000; - width: 190px; - border-width: 0px; - margin-right: 2px; -} - -header .input2 { - color: #000; - width: 175px; - border-width: 0px; - margin-right: 2px; -} - -header .textbox { - color: #000; - padding-left: 2px; -} - -header .responsebox { - color: #000; - background-color: #fff; -} - -header .responseinfo { - color: #d6e6f0; - text-align: center; - border-width: 0px; - background-color: transparent; -} - -header .propvalue { - color: #000; - background-color: #fff; - width: 175px; - border-width: 0px; - margin-bottom: 3px; -} - -header .propvalue::-webkit-input-placeholder { - /* Safari, Chrome(, Opera?) */ - color: gray; - font-style: italic; -} -header .propvalue:-moz-placeholder { - /* Firefox 18- */ - color: gray; - font-style: italic; -} -header .propvalue:-moz-placeholder { - /* Firefox 19+ */ - color: gray; - font-style: italic; -} -header .propvalue-ms-input-placeholder { - /* IE (10+?) */ - color: gray; - font-style: italic; -} - -header .button { - font-size: 15px; - color: #fff; - background-color: #99c1da; - width: 70px; - height: 25px; - border-width: 0px; - border-radius: 5px; - padding: 0px; -} -header .button:focus { - outline: none; -} - -header .addpropsbutton { - font-size: 15px; - color: #fff; - background-color: #99c1da; - width: 175px; - height: 23px; - border-width: 0px; - border-radius: 5px; - padding: 0px; - margin-left: 2px; - margin-bottom: 3px; -} -header .addRow { - font-size: 15px; - color: #fff; - background-color: #99c1da; - width: 70px; - height: 25px; - border-width: 0px; - border-radius: 5px; - padding: 0px; -} -header .addRow:focus { - outline: none; -} - -header .removeRow { - font-size: 16px; - color: #fff; - background-color: #99c1da; - width: 35px; - height: 23px; - border-width: 0px; - border-radius: 5px; - padding: 0px; - padding-bottom: 2px; - margin-left: 3px; - text-align: center; - line-height: normal; -} -header .removeRow:focus { - outline: none; -} - -header .json:focus { - outline: none; -} -header .copyJSON:focus { - outline: none; -} -header .showJSON:focus { - outline: none; -} -header .copyURL:focus { - outline: none; -} -header .pasteJSON:focus { - outline: none; -} - -header .copyJSON { - font-size: 15px; - color: #fff; - background-color: #99c1da; - width: 130px; - height: 25px; - border-width: 0px; - border-radius: 5px; - padding-left: 1px; - margin-top: 10px; - margin-bottom: 20px; - margin-right: 2px; - display: none; -} - -header .showJSON { - font-size: 15px; - color: #fff; - background-color: #99c1da; - width: 140px; - height: 25px; - border-width: 0px; - border-radius: 5px; - padding: 0px; - margin-top: 5px; - margin-bottom: 10px; -} - -header .pasteJSON { - font-size: 15px; - color: #fff; - background-color: #99c1da; - width: 140px; - height: 25px; - border-width: 0px; - border-radius: 5px; - padding-left: 0px; - padding-bottom: 2px; - margin-top: 35px; - margin-bottom: 10px; -} - -header .copyURL { - font-size: 15px; - color: #fff; - background-color: #99c1da; - width: 130px; - height: 25px; - border-width: 0px; - border-radius: 5px; - padding-left: 1px; - margin-top: 25px; - margin-bottom: 10px; - margin-left: 2px; - display: none; -} - -header .intro .intro-lead-in { - font-style: normal; - font-size: 22px; - line-height: 50px; - margin-bottom: 25px; - font-family: 'Hind Madurai', Helvetica, Arial, sans-serif; -} - -header .intro .intro-heading { - font-style: normal; -} - -header .intro-button { - box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); -} - -header .intro .btn-xl { - background: #ffffff; - border: 1px solid #3f9dd8; - border-radius: 2px; - font-size: 20px; - color: #3f9dd8; - font-weight: normal; - text-transform: none; - font-family: 'Hind Madurai', Helvetica, Arial, sans-serif; -} - -header span { - display: inline-block; - position: inherit; - margin-top: 10px; - /*padding-left: 50px;*/ - transform: translateX(-50%); - background: transparent; - border: none !important; - font-size: 0; -} - -header .intro-copy { - background: transparent; - border: none !important; - font-size: 0; -} - -header .intro-help { - display: inline-block; - margin-top: 15px; - width: 134px; - height: 45px; - background-color: transparent; - border: none !important; - font-size: 0; - - border-top-left-radius: 30%; - border-top-right-radius: 29%; - border-bottom-right-radius: 24%; - border-bottom-left-radius: 26%; -} - -header .intro-refresh { - display: inline-block; - margin-top: 15px; - /* transform: translateX(-50%); */ - background: transparent; - border: none !important; - font-size: 0; -} - -@media (min-height: 1150px) { - header .intro-down-arrow { - /* Hard code top: 1150 (height of top section) - 20 (bottom) - 36 (image height) = 1094 */ - top: 1094px; - } -} - -@media (max-height: 825px) { - header .intro-down-arrow { - display: none; - } -} - -@media (min-width: 768px) { - header .intro { - padding-top: 200px; - padding-bottom: 200px; - max-width: 620px; - } - - header .intro-logo { - max-width: 238px; - padding-bottom: 70px; - } - - header .intro .intro-lead-in { - font-size: 51px; - font-style: normal; - line-height: 50px; - } - - header .intro .intro-long { - margin-left: 80px; - margin-right: 80px; - } - - header .intro .intro-heading { - margin-bottom: 25px; - font-size: 90px; - font-weight: 600; - } -} - -section { - padding: 50px 0; -} - -section h3.section-subheading { - margin-bottom: 50px; - font-weight: normal; -} - -@media (min-width: 768px) { - section { - padding: 50px 0; - } -} - -footer .row { - font-size: 12px; - text-align: left; -} - -footer .row h4 { - font-size: 14px; - padding-left: 40px; -} - -footer .row .quicklinks { - line-height: 25px; - list-style: none; - text-align: left; -} - -footer .credits { - font-size: 10px; - text-align: center; -} - -#description p { - font-weight: 300; - font-size: 25px; -} - -footer { - font-size: 14px; - color: #ffffff; - background-color: #3f9dd8; - line-height: 22px; - letter-spacing: 0; - text-align: left; - display: flex; - flex-wrap: wrap; -} - -footer .footer-row { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - flex-wrap: wrap; -} - -footer quicklinks { - font-size: 14px; - color: #ffffff; -} - -footer ul.quicklinks { - margin: 0; - padding: 0; -} - -footer .footer-title { - color: #ffc43c; - text-transform: uppercase; - font-weight: bold; -} - -footer ul.quicklinks a { - font-size: 14px; - color: #ffffff; -} - -footer .quicklink-section { - padding: 0; - min-width: 120px; -} - -footer .credits { - float: left; - font-size: 12px; - font-weight: normal; - text-align: right; - font-family: 'Hind Madurai', Helvetica, Arial, sans-serif; -} - -footer .credits a { - color: #ffffff; -} - -footer .credits span { - color: #ffc43c; -} - -footer a { - text-decoration: none; -} - -footer .table { - width: fit-content; - margin-right: auto; - margin-left: auto; - float: left; - margin-bottom: 0em; -} - -footer .table tbody th { - font-size: 13px; - padding-right: 2em; -} - -footer table thead { - color: #ffc43c; -} - -footer table tbody a { - color: #ffffff; -} diff --git a/client/js/app/yarn.lock b/client/js/app/yarn.lock index 6ef7814c807..39a2213d77c 100644 --- a/client/js/app/yarn.lock +++ b/client/js/app/yarn.lock @@ -10,335 +10,444 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: - "@babel/highlight" "^7.16.7" + "@babel/highlight" "^7.18.6" -"@babel/compat-data@^7.17.10": - version "7.18.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.5.tgz#acac0c839e317038c73137fbb6ef71a1d6238471" - integrity sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg== +"@babel/compat-data@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" + integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== -"@babel/core@^7.17.10": - version "7.18.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.5.tgz#c597fa680e58d571c28dda9827669c78cdd7f000" - integrity sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ== +"@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.12.17", "@babel/core@^7.12.3", "@babel/core@^7.17.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.10.tgz#39ad504991d77f1f3da91be0b8b949a5bc466fb8" + integrity sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw== dependencies: "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.18.2" - "@babel/helper-compilation-targets" "^7.18.2" - "@babel/helper-module-transforms" "^7.18.0" - "@babel/helpers" "^7.18.2" - "@babel/parser" "^7.18.5" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.5" - "@babel/types" "^7.18.4" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.10" + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-module-transforms" "^7.18.9" + "@babel/helpers" "^7.18.9" + "@babel/parser" "^7.18.10" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.18.10" + "@babel/types" "^7.18.10" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.1" semver "^6.3.0" -"@babel/generator@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d" - integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw== +"@babel/generator@^7.18.10", "@babel/generator@^7.7.2": + version "7.18.12" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.12.tgz#fa58daa303757bd6f5e4bbca91b342040463d9f4" + integrity sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg== dependencies: - "@babel/types" "^7.18.2" - "@jridgewell/gen-mapping" "^0.3.0" + "@babel/types" "^7.18.10" + "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" - integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-compilation-targets@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz#67a85a10cbd5fc7f1457fec2e7f45441dc6c754b" - integrity sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ== +"@babel/helper-compilation-targets@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf" + integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== dependencies: - "@babel/compat-data" "^7.17.10" - "@babel/helper-validator-option" "^7.16.7" + "@babel/compat-data" "^7.18.8" + "@babel/helper-validator-option" "^7.18.6" browserslist "^4.20.2" semver "^6.3.0" -"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd" - integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ== +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== -"@babel/helper-function-name@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12" - integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg== +"@babel/helper-function-name@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz#940e6084a55dee867d33b4e487da2676365e86b0" + integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A== dependencies: - "@babel/template" "^7.16.7" - "@babel/types" "^7.17.0" + "@babel/template" "^7.18.6" + "@babel/types" "^7.18.9" -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712" + integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.8.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f" + integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w== + +"@babel/helper-simple-access@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" + integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.18.0": - version "7.18.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz#baf05dec7a5875fb9235bd34ca18bad4e21221cd" - integrity sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA== +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.17.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.0" - "@babel/types" "^7.18.0" - -"@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.17.12": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz#86c2347da5acbf5583ba0a10aed4c9bf9da9cf96" - integrity sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA== - -"@babel/helper-simple-access@^7.17.7": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz#4dc473c2169ac3a1c9f4a51cfcd091d1c36fcff9" - integrity sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ== - dependencies: - "@babel/types" "^7.18.2" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^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/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - -"@babel/helpers@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.2.tgz#970d74f0deadc3f5a938bfa250738eb4ac889384" - integrity sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg== - dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.2" - "@babel/types" "^7.18.2" - -"@babel/highlight@^7.16.7": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" - integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" + integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== + +"@babel/helper-validator-identifier@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" + integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helpers@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9" + integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ== + dependencies: + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.16.7", "@babel/parser@^7.18.5": - version "7.18.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.5.tgz#337062363436a893a2d22faa60be5bb37091c83c" - integrity sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.18.11": + version "7.18.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.11.tgz#68bb07ab3d380affa9a3f96728df07969645d2d9" + integrity sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ== -"@babel/plugin-syntax-jsx@^7.17.12": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.17.12.tgz#834035b45061983a491f60096f61a2e7c5674a47" - integrity sha512-spyY3E3AURfxh/RHtjx5j6hs8am5NbUBGfcZ2vB3uShSpZdQyXSf5rR5Mk76vbtlAZOelyVQ71Fg0x9SG4fsog== +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-react-jsx-development@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8" - integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A== +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== dependencies: - "@babel/plugin-transform-react-jsx" "^7.16.7" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-react-jsx-self@^7.16.7": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.17.12.tgz#7f2e9b8c08d6a4204733138d8c29d4dba4bb66c2" - integrity sha512-7S9G2B44EnYOx74mue02t1uD8ckWZ/ee6Uz/qfdzc35uWHX5NgRy9i+iJSb2LFRgMd+QV9zNcStQaazzzZ3n3Q== +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-react-jsx-source@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.16.7.tgz#1879c3f23629d287cc6186a6c683154509ec70c0" - integrity sha512-rONFiQz9vgbsnaMtQlZCjIRwhJvlrPET8TabIUK2hzlXw9B9s2Ieaxte1SCOOXMbWRHodbKixNf3BLcWVOQ8Bw== +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-jsx@^7.16.7", "@babel/plugin-transform-react-jsx@^7.17.3": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.12.tgz#2aa20022709cd6a3f40b45d60603d5f269586dba" - integrity sha512-Lcaw8bxd1DKht3thfD4A12dqo1X16he1Lm8rIv8sTwjAYNInRS1qHa9aJoqvzpscItXvftKDCfaEQzwoVyXpEQ== +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/plugin-syntax-jsx" "^7.17.12" - "@babel/types" "^7.17.12" + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.17.12", "@babel/plugin-syntax-jsx@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/runtime@^7.10.2", "@babel/runtime@^7.13.10", "@babel/runtime@^7.7.6": - version "7.18.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4" - integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug== +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: - regenerator-runtime "^0.13.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz#1c09cd25795c7c2b8a4ba9ae49394576d4133285" + integrity sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-modules-commonjs@^7.12.13": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883" + integrity sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q== + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-react-jsx-development@^7.16.7": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" + integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.18.6" + +"@babel/plugin-transform-react-jsx-self@^7.16.7": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz#3849401bab7ae8ffa1e3e5687c94a753fc75bda7" + integrity sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/runtime@^7.13.16", "@babel/runtime@^7.17.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.7": +"@babel/plugin-transform-react-jsx-source@^7.16.7": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" - integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.18.6.tgz#06e9ae8a14d2bc19ce6e3c447d842032a50598fc" + integrity sha512-utZmlASneDfdaMh0m/WausbjUjEdGrQJz0vFK93d7wD3xf5wBtX219+q6IlCNZeguIcxS2f/CvLZrlLSvSHQXw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-jsx@^7.17.3", "@babel/plugin-transform-react-jsx@^7.18.6": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz#ea47b2c4197102c196cbd10db9b3bb20daa820f1" + integrity sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-jsx" "^7.18.6" + "@babel/types" "^7.18.10" + +"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.18.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.7": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" + integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2", "@babel/traverse@^7.18.5": - version "7.18.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.5.tgz#94a8195ad9642801837988ab77f36e992d9a20cd" - integrity sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.18.2" - "@babel/helper-environment-visitor" "^7.18.2" - "@babel/helper-function-name" "^7.17.9" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.18.5" - "@babel/types" "^7.18.4" +"@babel/template@^7.18.10", "@babel/template@^7.18.6", "@babel/template@^7.3.3": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + +"@babel/traverse@^7.18.10", "@babel/traverse@^7.18.9", "@babel/traverse@^7.7.2": + version "7.18.11" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.11.tgz#3d51f2afbd83ecf9912bcbb5c4d94e3d2ddaa16f" + integrity sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.10" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.18.11" + "@babel/types" "^7.18.10" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.17.12", "@babel/types@^7.18.0", "@babel/types@^7.18.2", "@babel/types@^7.18.4": - version "7.18.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354" - integrity sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw== +"@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.10.tgz#4908e81b6b339ca7c6b7a555a5fc29446f26dde6" + integrity sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ== dependencies: - "@babel/helper-validator-identifier" "^7.16.7" + "@babel/helper-string-parser" "^7.18.10" + "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" -"@emotion/cache@11.7.1": - version "11.7.1" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.7.1.tgz#08d080e396a42e0037848214e8aa7bf879065539" - integrity sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A== +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cnakazawa/watch@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + +"@emotion/babel-plugin@^11.10.0": + version "11.10.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.0.tgz#ae545b8faa6b42d3a50ec86b70b758296f3c4467" + integrity sha512-xVnpDAAbtxL1dsuSelU5A7BnY/lftws0wUexNJZTPsvX/1tM4GZJbclgODhvW4E+NH7E5VFcH0bBn30NvniPJA== dependencies: - "@emotion/memoize" "^0.7.4" - "@emotion/sheet" "^1.1.0" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" + "@babel/helper-module-imports" "^7.16.7" + "@babel/plugin-syntax-jsx" "^7.17.12" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.0" + "@emotion/memoize" "^0.8.0" + "@emotion/serialize" "^1.1.0" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" stylis "4.0.13" -"@emotion/cache@^11.7.1": - version "11.9.3" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.9.3.tgz#96638449f6929fd18062cfe04d79b29b44c0d6cb" - integrity sha512-0dgkI/JKlCXa+lEXviaMtGBL0ynpx4osh7rjOXE71q9bIF8G+XhJgvi+wDu0B0IdCVx37BffiwXlN9I3UuzFvg== +"@emotion/cache@^11.10.0": + version "11.10.1" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.1.tgz#75a157c2a6bb9220450f73ebef1df2e1467dc65d" + integrity sha512-uZTj3Yz5D69GE25iFZcIQtibnVCFsc/6+XIozyL3ycgWvEdif2uEw9wlUt6umjLr4Keg9K6xRPHmD8LGi+6p1A== dependencies: - "@emotion/memoize" "^0.7.4" - "@emotion/sheet" "^1.1.1" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" + "@emotion/memoize" "^0.8.0" + "@emotion/sheet" "^1.2.0" + "@emotion/utils" "^1.2.0" + "@emotion/weak-memoize" "^0.3.0" stylis "4.0.13" -"@emotion/hash@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" - integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== - -"@emotion/memoize@^0.7.4": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" - integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== +"@emotion/hash@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7" + integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ== -"@emotion/react@11.7.1": - version "11.7.1" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.7.1.tgz#3f800ce9b20317c13e77b8489ac4a0b922b2fe07" - integrity sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw== - dependencies: - "@babel/runtime" "^7.13.10" - "@emotion/cache" "^11.7.1" - "@emotion/serialize" "^1.0.2" - "@emotion/sheet" "^1.1.0" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" +"@emotion/memoize@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" + integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== + +"@emotion/react@^11": + version "11.10.0" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.0.tgz#53c577f063f26493f68a05188fb87528d912ff2e" + integrity sha512-K6z9zlHxxBXwN8TcpwBKcEsBsOw4JWCCmR+BeeOWgqp8GIU1yA2Odd41bwdAAr0ssbQrbJbVnndvv7oiv1bZeQ== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.10.0" + "@emotion/cache" "^11.10.0" + "@emotion/serialize" "^1.1.0" + "@emotion/utils" "^1.2.0" + "@emotion/weak-memoize" "^0.3.0" hoist-non-react-statics "^3.3.1" -"@emotion/serialize@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965" - integrity sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A== - dependencies: - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.4" - "@emotion/unitless" "^0.7.5" - "@emotion/utils" "^1.0.0" - csstype "^3.0.2" - -"@emotion/serialize@^1.0.2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.4.tgz#ff31fd11bb07999611199c2229e152faadc21a3c" - integrity sha512-1JHamSpH8PIfFwAMryO2bNka+y8+KA5yga5Ocf2d7ZEiJjb7xlLW7aknBGZqJLajuLOvJ+72vN+IBSwPlXD1Pg== +"@emotion/serialize@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.0.tgz#b1f97b1011b09346a40e9796c37a3397b4ea8ea8" + integrity sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA== dependencies: - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.4" - "@emotion/unitless" "^0.7.5" - "@emotion/utils" "^1.0.0" + "@emotion/hash" "^0.9.0" + "@emotion/memoize" "^0.8.0" + "@emotion/unitless" "^0.8.0" + "@emotion/utils" "^1.2.0" csstype "^3.0.2" -"@emotion/sheet@^1.1.0", "@emotion/sheet@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.1.1.tgz#015756e2a9a3c7c5f11d8ec22966a8dbfbfac787" - integrity sha512-J3YPccVRMiTZxYAY0IOq3kd+hUP8idY8Kz6B/Cyo+JuXq52Ek+zbPbSQUrVQp95aJ+lsAW7DPL1P2Z+U1jGkKA== +"@emotion/sheet@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.0.tgz#771b1987855839e214fc1741bde43089397f7be5" + integrity sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w== -"@emotion/unitless@^0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" - integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== +"@emotion/unitless@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db" + integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw== -"@emotion/utils@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af" - integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA== +"@emotion/utils@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561" + integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw== -"@emotion/utils@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.1.0.tgz#86b0b297f3f1a0f2bdb08eeac9a2f49afd40d0cf" - integrity sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ== +"@emotion/weak-memoize@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb" + integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg== -"@emotion/weak-memoize@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" - integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@esbuild/linux-loong64@0.14.54": + version "0.14.54" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028" + integrity sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw== "@eslint/eslintrc@^1.3.0": version "1.3.0" @@ -355,53 +464,328 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@fortawesome/fontawesome-common-types@6.1.1": - version "6.1.1" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.1.tgz#7dc996042d21fc1ae850e3173b5c67b0549f9105" - integrity sha512-wVn5WJPirFTnzN6tR95abCx+ocH+3IFLXAgyavnf9hUmN0CfWoDjPT/BAWsUVwSlYYVBeCLJxaqi7ZGe4uSjBA== +"@floating-ui/core@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86" + integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg== + +"@floating-ui/dom@^0.5.3": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1" + integrity sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg== + dependencies: + "@floating-ui/core" "^0.7.3" + +"@floating-ui/react-dom-interactions@0.6.6": + version "0.6.6" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom-interactions/-/react-dom-interactions-0.6.6.tgz#8542e8c4bcbee2cd0d512de676c6a493e0a2d168" + integrity sha512-qnao6UPjSZNHnXrF+u4/n92qVroQkx0Umlhy3Avk1oIebm/5ee6yvDm4xbHob0OjY7ya8WmUnV3rQlPwX3Atwg== + dependencies: + "@floating-ui/react-dom" "^0.7.2" + aria-hidden "^1.1.3" + use-isomorphic-layout-effect "^1.1.1" + +"@floating-ui/react-dom@^0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864" + integrity sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg== + dependencies: + "@floating-ui/dom" "^0.5.3" + use-isomorphic-layout-effect "^1.1.1" + +"@fortawesome/fontawesome-common-types@6.1.2": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.2.tgz#c1095b1bbabf19f37f9ff0719db38d92a410bcfe" + integrity sha512-wBaAPGz1Awxg05e0PBRkDRuTsy4B3dpBm+zreTTyd9TH4uUM27cAL4xWyWR0rLJCrRwzVsQ4hF3FvM6rqydKPA== "@fortawesome/fontawesome-svg-core@^6": - version "6.1.1" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.1.tgz#3424ec6182515951816be9b11665d67efdce5b5f" - integrity sha512-NCg0w2YIp81f4V6cMGD9iomfsIj7GWrqmsa0ZsPh59G7PKiGN1KymZNxmF00ssuAlo/VZmpK6xazsGOwzKYUMg== + version "6.1.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.2.tgz#11e2e8583a7dea75d734e4d0e53d91c63fae7511" + integrity sha512-853G/Htp0BOdXnPoeCPTjFrVwyrJHpe8MhjB/DYE9XjwhnNDfuBCd3aKc2YUYbEfHEcBws4UAA0kA9dymZKGjA== dependencies: - "@fortawesome/fontawesome-common-types" "6.1.1" + "@fortawesome/fontawesome-common-types" "6.1.2" "@fortawesome/free-regular-svg-icons@^6": - version "6.1.1" - resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.1.1.tgz#3f2f58262a839edf0643cbacee7a8a8230061c98" - integrity sha512-xXiW7hcpgwmWtndKPOzG+43fPH7ZjxOaoeyooptSztGmJxCAflHZxXNK0GcT0uEsR4jTGQAfGklDZE5NHoBhKg== + version "6.1.2" + resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.1.2.tgz#9f04009098addcc11d0d185126f058ed042c3099" + integrity sha512-xR4hA+tAwsaTHGfb+25H1gVU/aJ0Rzu+xIUfnyrhaL13yNQ7TWiI2RvzniAaB+VGHDU2a+Pk96Ve+pkN3/+TTQ== dependencies: - "@fortawesome/fontawesome-common-types" "6.1.1" + "@fortawesome/fontawesome-common-types" "6.1.2" "@fortawesome/free-solid-svg-icons@^6": - version "6.1.1" - resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.1.tgz#3369e673f8fe8be2fba30b1ec274d47490a830a6" - integrity sha512-0/5exxavOhI/D4Ovm2r3vxNojGZioPwmFrKg0ZUH69Q68uFhFPs6+dhAToh6VEQBntxPRYPuT5Cg1tpNa9JUPg== + version "6.1.2" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.2.tgz#491d668b8a6603698d0ce1ac620f66fd22b74c84" + integrity sha512-lTgZz+cMpzjkHmCwOG3E1ilUZrnINYdqMmrkv30EC3XbRsGlbIOL8H9LaNp5SV4g0pNJDfQ4EdTWWaMvdwyLiQ== dependencies: - "@fortawesome/fontawesome-common-types" "6.1.1" + "@fortawesome/fontawesome-common-types" "6.1.2" "@fortawesome/react-fontawesome@^0": - version "0.1.18" - resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.18.tgz#dae37f718a24e14d7a99a5496c873d69af3fbd73" - integrity sha512-RwLIB4TZw0M9gvy5u+TusAA0afbwM4JQIimNH/j3ygd6aIvYPQLqXMhC9ErY26J23rDPyDZldIfPq/HpTTJ/tQ== + version "0.2.0" + resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz#d90dd8a9211830b4e3c08e94b63a0ba7291ddcf4" + integrity sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw== dependencies: prop-types "^15.8.1" -"@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== +"@humanwhocodes/config-array@^0.10.4": + version "0.10.4" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.4.tgz#01e7366e57d2ad104feea63e72248f22015c520c" + integrity sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" minimatch "^3.0.4" +"@humanwhocodes/gitignore-to-minimatch@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d" + integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA== + "@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== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.3.tgz#2030606ec03a18c31803b8a36382762e447655df" + integrity sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw== + dependencies: + "@jest/types" "^28.1.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^28.1.3" + jest-util "^28.1.3" + slash "^3.0.0" + +"@jest/core@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-28.1.3.tgz#0ebf2bd39840f1233cd5f2d1e6fc8b71bd5a1ac7" + integrity sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA== + dependencies: + "@jest/console" "^28.1.3" + "@jest/reporters" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^28.1.3" + jest-config "^28.1.3" + jest-haste-map "^28.1.3" + jest-message-util "^28.1.3" + jest-regex-util "^28.0.2" + jest-resolve "^28.1.3" + jest-resolve-dependencies "^28.1.3" + jest-runner "^28.1.3" + jest-runtime "^28.1.3" + jest-snapshot "^28.1.3" + jest-util "^28.1.3" + jest-validate "^28.1.3" + jest-watcher "^28.1.3" + micromatch "^4.0.4" + pretty-format "^28.1.3" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.1.3.tgz#abed43a6b040a4c24fdcb69eab1f97589b2d663e" + integrity sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA== + dependencies: + "@jest/fake-timers" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + jest-mock "^28.1.3" + +"@jest/expect-utils@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.3.tgz#58561ce5db7cd253a7edddbc051fb39dda50f525" + integrity sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA== + dependencies: + jest-get-type "^28.0.2" + +"@jest/expect@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.1.3.tgz#9ac57e1d4491baca550f6bdbd232487177ad6a72" + integrity sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw== + dependencies: + expect "^28.1.3" + jest-snapshot "^28.1.3" + +"@jest/fake-timers@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-28.1.3.tgz#230255b3ad0a3d4978f1d06f70685baea91c640e" + integrity sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw== + dependencies: + "@jest/types" "^28.1.3" + "@sinonjs/fake-timers" "^9.1.2" + "@types/node" "*" + jest-message-util "^28.1.3" + jest-mock "^28.1.3" + jest-util "^28.1.3" + +"@jest/globals@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.1.3.tgz#a601d78ddc5fdef542728309894895b4a42dc333" + integrity sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA== + dependencies: + "@jest/environment" "^28.1.3" + "@jest/expect" "^28.1.3" + "@jest/types" "^28.1.3" + +"@jest/reporters@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-28.1.3.tgz#9adf6d265edafc5fc4a434cfb31e2df5a67a369a" + integrity sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + "@jridgewell/trace-mapping" "^0.3.13" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^5.1.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^28.1.3" + jest-util "^28.1.3" + jest-worker "^28.1.3" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + terminal-link "^2.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.1.3.tgz#ad8b86a66f11f33619e3d7e1dcddd7f2d40ff905" + integrity sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg== + dependencies: + "@sinclair/typebox" "^0.24.1" + +"@jest/source-map@^28.1.2": + version "28.1.2" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-28.1.2.tgz#7fe832b172b497d6663cdff6c13b0a920e139e24" + integrity sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww== + dependencies: + "@jridgewell/trace-mapping" "^0.3.13" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.3.tgz#5eae945fd9f4b8fcfce74d239e6f725b6bf076c5" + integrity sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg== + dependencies: + "@jest/console" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz#9d0c283d906ac599c74bde464bc0d7e6a82886c3" + integrity sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw== + dependencies: + "@jest/test-result" "^28.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.3" + slash "^3.0.0" + +"@jest/transform@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" + integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^26.6.2" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^26.6.2" + jest-regex-util "^26.0.0" + jest-util "^26.6.2" + micromatch "^4.0.2" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/transform@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.1.3.tgz#59d8098e50ab07950e0f2fc0fc7ec462371281b0" + integrity sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^28.1.3" + "@jridgewell/trace-mapping" "^0.3.13" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.3" + jest-regex-util "^28.0.2" + jest-util "^28.1.3" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.1" + +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@jest/types@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.3.tgz#b05de80996ff12512bc5ceb1d208285a7d11748b" + integrity sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ== + dependencies: + "@jest/schemas" "^28.1.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" @@ -410,189 +794,185 @@ "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9" - integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg== +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== dependencies: - "@jridgewell/set-array" "^1.0.0" + "@jridgewell/set-array" "^1.0.1" "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== -"@jridgewell/set-array@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" - integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.13" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" - integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w== +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.15" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" + integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== dependencies: "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@mantine/core@^4": - version "4.2.10" - resolved "https://registry.yarnpkg.com/@mantine/core/-/core-4.2.10.tgz#6b4973bc5c79cd077341ab2bbe327749ca3ed8c4" - integrity sha512-UCPhDcumygfBvik64VkMnBvqy0ZN9q+1AQ0fPdK8aAUvjRBWSyH0dJPL55vsK1ODboKktSEsyjHtb09DroL7fA== +"@mantine/core@^5": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@mantine/core/-/core-5.1.6.tgz#98c984bf08ceeb8684a8dc7146034c85e35de9f7" + integrity sha512-ZG/ccTc+LcxcUahxMu4m3hOkAss8LetETFbZ5zsDotJTvij2lzMzNcuPebLeyxNt714VEWIXNzIUotNtGXDSGg== dependencies: - "@mantine/styles" "4.2.10" - "@popperjs/core" "^2.9.3" - "@radix-ui/react-scroll-area" "^0.1.1" - react-popper "^2.2.5" - react-textarea-autosize "^8.3.2" + "@floating-ui/react-dom-interactions" "0.6.6" + "@mantine/styles" "5.1.6" + "@mantine/utils" "5.1.6" + "@radix-ui/react-scroll-area" "1.0.0" + react-textarea-autosize "8.3.4" -"@mantine/hooks@^4": - version "4.2.10" - resolved "https://registry.yarnpkg.com/@mantine/hooks/-/hooks-4.2.10.tgz#ad55d5ad3c5814eab924dfb6fd04f9ffd44e3d30" - integrity sha512-gVYWeE4Ieu6FBwh9h/3FjcrrNzKx1k6Yw07/LSngJP0uT3fLt1gvY2p4PtPpOh7z2/RpTXBR1x+dOgEUKomYUQ== +"@mantine/hooks@^5": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@mantine/hooks/-/hooks-5.1.6.tgz#07d4850d3444526268a749c965ce64eea8cb7583" + integrity sha512-wD+Cx9W00YQchudIvkiEy52e/UCB0EhTkJs2fr2JbTlfKCWfWSilE/CPbLz6NWmK58bbyB/qjdKUDwXV6qyasw== -"@mantine/styles@4.2.10": - version "4.2.10" - resolved "https://registry.yarnpkg.com/@mantine/styles/-/styles-4.2.10.tgz#967f0b09f4b3adaa23e650f9112be362ed07e953" - integrity sha512-dWwCzBLYE8CwPJSPlV3MyIuR4ET3u6O+T+VmxY0lab6w/bqflseNSh9UBIW2AUoIYtxPVDjbZfzeTw32aV8CxA== - dependencies: - "@emotion/cache" "11.7.1" - "@emotion/react" "11.7.1" - "@emotion/serialize" "1.0.2" - "@emotion/utils" "1.0.0" - clsx "^1.1.1" +"@mantine/notifications@^5": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@mantine/notifications/-/notifications-5.1.6.tgz#6311c928e821fdee6963048a698fce465482a589" + integrity sha512-JT0nLOoNO/NDuB2Xn4kVOSo+4Y4F+ogrWLN7qHgpmZlRsxc/8S1DFwgubTMwvJR38AHrOVaqp1hFsqdHDww0Ow== + dependencies: + "@mantine/utils" "5.1.6" + react-transition-group "4.4.2" + +"@mantine/styles@5.1.6": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@mantine/styles/-/styles-5.1.6.tgz#cfb4a33d4c38ffb499d51cd0af35abd436ebe831" + integrity sha512-7d112DIHauP+X0JaVh0uzlpVndWqw/muaz77C5hLlA8yP7gVuRWOhEqJDuTnZzNtj/utIJJDAyVM2+DHFqtQtg== + dependencies: + clsx "1.1.1" csstype "3.0.9" -"@popperjs/core@^2.10.1", "@popperjs/core@^2.9.3": - version "2.11.5" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64" - integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw== +"@mantine/utils@5.1.6": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@mantine/utils/-/utils-5.1.6.tgz#992cd1e8850467533aa88dc5fd933650674abf5e" + integrity sha512-y7va2keQ+TPwn2j668r889NhQWO0OhSvaxT5P8n2iBaTyPg+Xp5Jm2IE5UjI+OrZErrgmQq1sxbfg6v5vdK+0A== -"@radix-ui/number@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-0.1.0.tgz#73ad13d5cc5f75fa5e147d72e5d5d5e50d688256" - integrity sha512-rpf6QiOWLHAkM4FEMYu9i+5Jr8cKT893+R4mPpcdsy4LD7omr9JfdOqj/h/xPA5+EcVrpMMlU6rrRYpUB5UI8g== +"@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: - "@babel/runtime" "^7.13.10" + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" -"@radix-ui/primitive@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-0.1.0.tgz#6206b97d379994f0d1929809db035733b337e543" - integrity sha512-tqxZKybwN5Fa3VzZry4G6mXAAb9aAqKmPtnVbZpL0vsBwvOHTBwsjHVPXylocYLwEtBY9SCe665bYnNB515uoA== +"@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: - "@babel/runtime" "^7.13.10" + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" -"@radix-ui/react-compose-refs@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-0.1.0.tgz#cff6e780a0f73778b976acff2c2a5b6551caab95" - integrity sha512-eyclbh+b77k+69Dk72q3694OHrn9B3QsoIRx7ywX341U9RK1ThgQjMFZoPtmZNQTksXHLNEiefR8hGVeFyInGg== +"@radix-ui/number@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.0.0.tgz#4c536161d0de750b3f5d55860fc3de46264f897b" + integrity sha512-Ofwh/1HX69ZfJRiRBMTy7rgjAzHmwe4kW9C9Y99HTRUcYLUuVT0KESFj15rPjRgKJs20GPq8Bm5aEDJ8DuA3vA== dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-context@0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-0.1.1.tgz#06996829ea124d9a1bc1dbe3e51f33588fab0875" - integrity sha512-PkyVX1JsLBioeu0jB9WvRpDBBLtLZohVDT3BB5CTSJqActma8S8030P57mWZb4baZifMvN7KKWPAA40UmWKkQg== +"@radix-ui/primitive@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.0.tgz#e1d8ef30b10ea10e69c76e896f608d9276352253" + integrity sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA== dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-presence@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-0.1.2.tgz#9f11cce3df73cf65bc348e8b76d891f0d54c1fe3" - integrity sha512-3BRlFZraooIUfRlyN+b/Xs5hq1lanOOo/+3h6Pwu2GMFjkGKKa4Rd51fcqGqnVlbr3jYg+WLuGyAV4KlgqwrQw== +"@radix-ui/react-compose-refs@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz#37595b1f16ec7f228d698590e78eeed18ff218ae" + integrity sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "0.1.0" - "@radix-ui/react-use-layout-effect" "0.1.0" -"@radix-ui/react-primitive@0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-0.1.4.tgz#6c233cf08b0cb87fecd107e9efecb3f21861edc1" - integrity sha512-6gSl2IidySupIMJFjYnDIkIWRyQdbu/AHK7rbICPani+LW4b0XdxBXc46og/iZvuwW8pjCS8I2SadIerv84xYA== +"@radix-ui/react-context@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.0.tgz#f38e30c5859a9fb5e9aa9a9da452ee3ed9e0aee0" + integrity sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-slot" "0.1.2" -"@radix-ui/react-scroll-area@^0.1.1": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-0.1.4.tgz#be1d32c113ee9f64e3d2e7ee3983d98f00b42038" - integrity sha512-QHxRsjy+hsHwQYJ9cCNgSJ5+6ioZu1KhwD1UOXoHNciuFGMX08v+uJPKXIz+ySv03Rx6cOz6f/Fk5aPHRMFi/A== +"@radix-ui/react-direction@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.0.tgz#a2e0b552352459ecf96342c79949dd833c1e6e45" + integrity sha512-2HV05lGUgYcA6xgLQ4BKPDmtL+QbIZYH5fCOTAOOcJ5O0QbWS3i9lKaurLzliYUDhORI2Qr3pyjhJh44lKA3rQ== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/number" "0.1.0" - "@radix-ui/primitive" "0.1.0" - "@radix-ui/react-compose-refs" "0.1.0" - "@radix-ui/react-context" "0.1.1" - "@radix-ui/react-presence" "0.1.2" - "@radix-ui/react-primitive" "0.1.4" - "@radix-ui/react-use-callback-ref" "0.1.0" - "@radix-ui/react-use-direction" "0.1.0" - "@radix-ui/react-use-layout-effect" "0.1.0" - -"@radix-ui/react-slot@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-0.1.2.tgz#e6f7ad9caa8ce81cc8d532c854c56f9b8b6307c8" - integrity sha512-ADkqfL+agEzEguU3yS26jfB50hRrwf7U4VTwAOZEmi/g+ITcBWe12yM46ueS/UCIMI9Py+gFUaAdxgxafFvY2Q== + +"@radix-ui/react-presence@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.0.tgz#814fe46df11f9a468808a6010e3f3ca7e0b2e84a" + integrity sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" -"@radix-ui/react-use-callback-ref@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-0.1.0.tgz#934b6e123330f5b3a6b116460e6662cbc663493f" - integrity sha512-Va041McOFFl+aV+sejvl0BS2aeHx86ND9X/rVFmEFQKTXCp6xgUK0NGUAGcgBlIjnJSbMYPGEk1xKSSlVcN2Aw== +"@radix-ui/react-primitive@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.0.tgz#376cd72b0fcd5e0e04d252ed33eb1b1f025af2b0" + integrity sha512-EyXe6mnRlHZ8b6f4ilTDrXmkLShICIuOTTj0GX4w1rp+wSxf3+TD05u1UOITC8VsJ2a9nwHvdXtOXEOl0Cw/zQ== dependencies: "@babel/runtime" "^7.13.10" + "@radix-ui/react-slot" "1.0.0" -"@radix-ui/react-use-direction@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-direction/-/react-use-direction-0.1.0.tgz#97ac1d52e497c974389e7988f809238ed72e7df7" - integrity sha512-NajpY/An9TCPSfOVkgWIdXJV+VuWl67PxB6kOKYmtNAFHvObzIoh8o0n9sAuwSAyFCZVq211FEf9gvVDRhOyiA== +"@radix-ui/react-scroll-area@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.0.tgz#10d0262a52266af528798f36947145f7e3a3a52c" + integrity sha512-3SNFukAjS5remgtpAVR9m3Zgo23ZojBZ8V3TCyR3A+56x2mtVqKlPV4+e8rScZUFMuvtbjIdQCmsJBFBazKZig== dependencies: "@babel/runtime" "^7.13.10" - -"@radix-ui/react-use-layout-effect@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-0.1.0.tgz#ebf71bd6d2825de8f1fbb984abf2293823f0f223" - integrity sha512-+wdeS51Y+E1q1Wmd+1xSSbesZkpVj4jsg0BojCbopWvgq5iBvixw5vgemscdh58ep98BwUbsFYnrywFhV9yrVg== + "@radix-ui/number" "1.0.0" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + +"@radix-ui/react-slot@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.0.tgz#7fa805b99891dea1e862d8f8fbe07f4d6d0fd698" + integrity sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ== dependencies: "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" -"@react-aria/ssr@^3.0.1": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.2.0.tgz#88460384b43204f91c972d5b0de24ee44d6a2984" - integrity sha512-wwJFdkl+Q8NU5yJ4NvdAOqx5LM3QtUVoSjuK7Ey8jZ4WS4bB0EqT3Kr3IInBs257HzZ5nXCiKXKE4NGXXuIRWA== +"@radix-ui/react-use-callback-ref@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.0.tgz#9e7b8b6b4946fe3cbe8f748c82a2cce54e7b6a90" + integrity sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg== dependencies: - "@babel/runtime" "^7.6.2" + "@babel/runtime" "^7.13.10" -"@restart/hooks@^0.4.0", "@restart/hooks@^0.4.6": - version "0.4.7" - resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.7.tgz#d79ca6472c01ce04389fc73d4a79af1b5e33cd39" - integrity sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A== +"@radix-ui/react-use-layout-effect@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz#2fc19e97223a81de64cd3ba1dc42ceffd82374dc" + integrity sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ== dependencies: - dequal "^2.0.2" - -"@restart/ui@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@restart/ui/-/ui-1.2.0.tgz#fb90251aa25f99b41ccedc78a91d2a15f3c5e0fb" - integrity sha512-oIh2t3tG8drZtZ9SlaV5CY6wGsUViHk8ZajjhcI+74IQHyWy+AnxDv8rJR5wVgsgcgrPBUvGNkC1AEdcGNPaLQ== - dependencies: - "@babel/runtime" "^7.13.16" - "@popperjs/core" "^2.10.1" - "@react-aria/ssr" "^3.0.1" - "@restart/hooks" "^0.4.0" - "@types/warning" "^3.0.0" - dequal "^2.0.2" - dom-helpers "^5.2.0" - uncontrollable "^7.2.1" - warning "^4.0.3" + "@babel/runtime" "^7.13.10" "@rollup/pluginutils@^4.2.1": version "4.2.1" @@ -602,6 +982,84 @@ estree-walker "^2.0.1" picomatch "^2.2.2" +"@sinclair/typebox@^0.24.1": + version "0.24.28" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.28.tgz#15aa0b416f82c268b1573ab653e4413c965fe794" + integrity sha512-dgJd3HLOkLmz4Bw50eZx/zJwtBq65nms3N9VBYu5LTjJ883oBFkTyXRlCB/ZGGwqYpJJHA5zW2Ibhl5ngITfow== + +"@sinonjs/commons@^1.7.0": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^9.1.2": + version "9.1.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" + integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14", "@types/babel__core@^7.1.7": + version "7.1.19" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" + integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.0.tgz#8134fd78cb39567465be65b9fdc16d378095f41f" + integrity sha512-v4Vwdko+pgymgS+A2UIaJru93zQd85vIGWObM5ekZNdXCKtDYqATlEYnWgfo86Q6I1Lh0oXnksDnMU1cwmlPDw== + dependencies: + "@babel/types" "^7.3.0" + +"@types/graceful-fs@^4.1.2", "@types/graceful-fs@^4.1.3": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -612,38 +1070,37 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== +"@types/node@*": + version "18.7.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.3.tgz#432c89796eab539b7a30b7b8801a727b585238a4" + integrity sha512-LJgzOEwWuMTBxHzgBR/fhhBOWrvBjvO+zPteUgbbuQi80rYIZHrk1mNbRUqPZqSLP2H7Rwt1EFLL/tNLD1Xx/w== + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + +"@types/prettier@^2.1.5": + version "2.7.0" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.0.tgz#ea03e9f0376a4446f44797ca19d9c46c36e352dc" + integrity sha512-RI1L7N4JnW5gQw2spvL7Sllfuf1SaHdrZpCHiBlCXjIlufi1SMNnbu2teze3/QE67Fg2tBlH7W+mi4hVNk4p0A== + "@types/prop-types@*": version "15.7.5" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== "@types/react-dom@^18": - version "18.0.5" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.5.tgz#330b2d472c22f796e5531446939eacef8378444a" - integrity sha512-OWPWTUrY/NIrjsAPkAk1wW9LZeIjSvkXRhclsFO8CZcZGCOg2G0YZy4ft+rOyYxy8B7ui5iZzi9OkDebZ7/QSA== + version "18.0.6" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.6.tgz#36652900024842b74607a17786b6662dd1e103a1" + integrity sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA== dependencies: "@types/react" "*" -"@types/react-transition-group@^4.4.4": - version "4.4.4" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.4.tgz#acd4cceaa2be6b757db61ed7b432e103242d163e" - integrity sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug== - dependencies: - "@types/react" "*" - -"@types/react@*": - version "18.0.13" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.13.tgz#0f5bd24a5f26593e04e450fe85ff43f51c1524ff" - integrity sha512-psqptIYQxGUFuGYwP3KCFVtPTkMpIcrqFmtKblWEUQhLuYLpHBwJkXhjp6eHfDM5IbyskY4x7qQpLedEsPkHlA== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/react@>=16.9.11", "@types/react@^18": - version "18.0.14" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.14.tgz#e016616ffff51dba01b04945610fe3671fdbe06d" - integrity sha512-x4gGuASSiWmo0xjDLpm5mPb52syZHJx02VKbqUKdLmKtAwIh63XClGsiTI1K6DO5q7ox4xAsQrU+Gl3+gGXF9Q== +"@types/react@*", "@types/react@^18": + version "18.0.17" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.17.tgz#4583d9c322d67efe4b39a935d223edcc7050ccf4" + integrity sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -654,10 +1111,29 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== -"@types/warning@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" - integrity sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA== +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^15.0.0": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== + dependencies: + "@types/yargs-parser" "*" + +"@types/yargs@^17.0.8": + version "17.0.11" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.11.tgz#5e10ca33e219807c0eee0f08b5efcba9b6a42c06" + integrity sha512-aB4y9UDUXTSMxmM4MH+YnuR0g5Cph3FLQBoWoMB21DSvFVAxRVEHEMx3TLh+zUZYMCQtKiqazz0Q4Rre31f/OA== + dependencies: + "@types/yargs-parser" "*" "@vitejs/plugin-react@^1": version "1.3.2" @@ -678,10 +1154,10 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.7.1: - version "8.7.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" - integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== +acorn@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" @@ -693,6 +1169,13 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -705,18 +1188,68 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.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" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@^3.0.3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +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" + 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-hidden@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254" + integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA== + dependencies: + tslib "^1.0.0" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + +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 sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + array-differ@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" @@ -738,6 +1271,11 @@ array-union@^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-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + array.prototype.flat@^1.2.5: version "1.3.0" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b" @@ -763,11 +1301,142 @@ arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + +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== + +babel-jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" + integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== + dependencies: + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/babel__core" "^7.1.7" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^26.6.2" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + +babel-jest@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.3.tgz#c1187258197c099072156a0a121c11ee1e3917d5" + integrity sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q== + dependencies: + "@jest/transform" "^28.1.3" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^28.1.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-istanbul@^6.0.0, babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" + integrity sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-jest-hoist@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz#1952c4d0ea50f2d6d794353762278d1d8cca3fbe" + integrity sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + dependencies: + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" + integrity sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ== + dependencies: + babel-plugin-jest-hoist "^26.6.2" + babel-preset-current-node-syntax "^1.0.0" + +babel-preset-jest@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz#5dfc20b99abed5db994406c2b9ab94c73aaa419d" + integrity sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A== + dependencies: + babel-plugin-jest-hoist "^28.1.3" + babel-preset-current-node-syntax "^1.0.0" + 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" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -776,16 +1445,65 @@ 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" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + browserslist@^4.20.2: - version "4.20.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.4.tgz#98096c9042af689ee1e0271333dbc564b8ce4477" - integrity sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw== + version "4.21.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a" + integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ== dependencies: - caniuse-lite "^1.0.30001349" - electron-to-chromium "^1.4.147" - escalade "^3.1.1" - node-releases "^2.0.5" - picocolors "^1.0.0" + caniuse-lite "^1.0.30001370" + electron-to-chromium "^1.4.202" + node-releases "^2.0.6" + update-browserslist-db "^1.0.5" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +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" @@ -800,10 +1518,27 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -caniuse-lite@^1.0.30001349: - version "1.0.30001355" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001355.tgz#e240b7177443ed0198c737a7f609536976701c77" - integrity sha512-Sd6pjJHF27LzCB7pT7qs+kuX2ndurzCzkpJl6Qct7LPSZ9jn0bkOA8mdgMgmqnQAWLVOOGjLpc+66V57eLtb1g== +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== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001370: + version "1.0.30001375" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001375.tgz#8e73bc3d1a4c800beb39f3163bf0190d7e5d7672" + integrity sha512-kWIMkNzLYxSvnjy0hL8w1NOaWNr2rn39RTAVyIwcw8juu60bZDWiF1/loOYANzjtJmy6qPgNmn38ro5Pygagdw== + +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== + dependencies: + rsvp "^4.8.4" chalk@^2.0.0: version "2.4.2" @@ -830,16 +1565,68 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -classnames@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" - integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -clsx@^1.1.1: +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.2.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.2.tgz#6d2967ffa407466481c6c90b6e16b3098f080128" + integrity sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg== + +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + +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" + +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" + +clsx@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + dependencies: + map-visit "^1.0.0" + object-visit "^1.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" @@ -864,19 +1651,51 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +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 sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== dependencies: safe-buffer "~5.1.1" -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + +cosmiconfig@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" + integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.0, 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== @@ -895,7 +1714,7 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== -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== @@ -916,11 +1735,26 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: dependencies: ms "2.1.2" +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 sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== + 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== +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== + define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" @@ -929,10 +1763,44 @@ define-properties@^1.1.3, define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" -dequal@^2.0.2: +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + 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 sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d" - integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug== + 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" + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.1.1.tgz#9989dc731266dc2903457a70e996f3a041913ac6" + integrity sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw== + +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" @@ -948,7 +1816,7 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-helpers@^5.0.1, dom-helpers@^5.2.0, dom-helpers@^5.2.1: +dom-helpers@^5.0.1: version "5.2.1" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== @@ -956,10 +1824,20 @@ dom-helpers@^5.0.1, dom-helpers@^5.2.0, dom-helpers@^5.2.1: "@babel/runtime" "^7.8.7" csstype "^3.0.2" -electron-to-chromium@^1.4.147: - version "1.4.158" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.158.tgz#abbdaaf64676bfa4bc0307522125db34424a0ada" - integrity sha512-gppO3/+Y6sP432HtvwvuU8S+YYYLH4PmAYvQwqUtt9HDOmEsBwQfLnK9T8+1NIKwAS1BEygIjTaATC4H5EzvxQ== +electron-to-chromium@^1.4.202: + version "1.4.219" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.219.tgz#a7a672304b6aa4f376918d3f63a47f2c3906009a" + integrity sha512-zoQJsXOUw0ZA0YxbjkmzBumAJRtr6je5JySuL/bAoFs0DuLiLJ+5FzRF7/ZayihxR2QcewlRZVm5QZdUhwjOgA== + +emittery@^0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" + integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== + +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== end-of-stream@^1.1.0: version "1.4.4" @@ -968,6 +1846,13 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" +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, es-abstract@^1.19.2, es-abstract@^1.19.5: version "1.20.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" @@ -1013,131 +1898,141 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -esbuild-android-64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.44.tgz#62f5cb563d0ba318d898b6eb230c61ad3dc93619" - integrity sha512-dFPHBXmx385zuJULAD/Cmq/LyPRXiAWbf9ylZtY0wJ8iVyWfKYaCYxeJx8OAZUuj46ZwNa7MzW2GBAQLOeiemg== - -esbuild-android-arm64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.44.tgz#ee7fcc9f47855b3395dfd1abcc2c43d8c53e57db" - integrity sha512-qqaqqyxHXjZ/0ddKU3I3Nb7lAvVM69ELMhb8+91FyomAUmQPlHtxe+TTiWxXGHE72XEzcgTEGq4VauqLNkN22g== - -esbuild-darwin-64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.44.tgz#75ea7f594687a7189a8ba62070d42f13178e68d0" - integrity sha512-RBmtGKGY06+AW6IOJ1LE/dEeF7HH34C1/Ces9FSitU4bIbIpL4KEuQpTFoxwb4ry5s2hyw7vbPhhtyOd18FH9g== - -esbuild-darwin-arm64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.44.tgz#550631fd135688abda042f4039b962a27f3a5f78" - integrity sha512-Bmhx5Cfo4Hdb7WyyyDupTB8HPmnFZ8baLfPlzLdYvF6OzsIbV+CY+m/AWf0OQvY40BlkzCLJ/7Lfwbb71Tngmg== - -esbuild-freebsd-64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.44.tgz#f98069b964266ca79bb361cfb9d7454a05b7e8ca" - integrity sha512-O4HpWa5ZgxbNPQTF7URicLzYa+TidGlmGT/RAC3GjbGEQQYkd0R1Slyh69Yrmb2qmcOcPAgWHbNo1UhK4WmZ4w== - -esbuild-freebsd-arm64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.44.tgz#247a8553d6033a58b6c3ba4d539216300497d7f6" - integrity sha512-f0/jkAKccnDY7mg1F9l/AMzEm+VXWXK6c3IrOEmd13jyKfpTZKTIlt+yI04THPDCDZTzXHTRUBLozqp+m8Mg5Q== - -esbuild-linux-32@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.44.tgz#4b72747f9f367d3ee3c1d80bf75c617e6b109821" - integrity sha512-WSIhzLldMR7YUoEL7Ix319tC+NFmW9Pu7NgFWxUfOXeWsT0Wg484hm6bNgs7+oY2pGzg715y/Wrqi1uNOMmZJw== - -esbuild-linux-64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.44.tgz#6cd158fdd11f8d037c45139ccddb4fa5966f7ab6" - integrity sha512-zgscTrCMcRZRIsVugqBTP/B5lPLNchBlWjQ8sQq2Epnv+UDtYKgXEq1ctWAmibZNy2E9QRCItKMeIEqeTUT5kA== - -esbuild-linux-arm64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.44.tgz#f14f3c8c3501067f5b2cef7a79c9a0058092cb22" - integrity sha512-H0H/2/wgiScTwBve/JR8/o+Zhabx5KPk8T2mkYZFKQGl1hpUgC+AOmRyqy/Js3p66Wim4F4Akv3I3sJA1sKg0w== - -esbuild-linux-arm@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.44.tgz#625478cc6ea4f64f5335e7fb07f80d6f659aeb5c" - integrity sha512-laPBPwGfsbBxGw6F6jnqic2CPXLyC1bPrmnSOeJ9oEnx1rcKkizd4HWCRUc0xv+l4z/USRfx/sEfYlWSLeqoJQ== - -esbuild-linux-mips64le@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.44.tgz#593c909bb612998300af7f7db2809a63a0d62eec" - integrity sha512-ri3Okw0aleYy7o5n9zlIq+FCtq3tcMlctN6X1H1ucILjBJuH8pan2trJPKWeb8ppntFvE28I9eEXhwkWh6wYKg== - -esbuild-linux-ppc64le@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.44.tgz#8fc2fcee671e322a5d44fcf8da6889095a187df9" - integrity sha512-96TqL/MvFRuIVXz+GtCIXzRQ43ZwEk4XTn0RWUNJduXXMDQ/V1iOV28U6x6Oe3NesK4xkoKSaK2+F3VHcU8ZrA== - -esbuild-linux-riscv64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.44.tgz#cc2b7158c8345b67e74458a0ec020c80ca777046" - integrity sha512-rrK9qEp2M8dhilsPn4T9gxUsAumkITc1kqYbpyNMr9EWo+J5ZBj04n3GYldULrcCw4ZCHAJ+qPjqr8b6kG2inA== - -esbuild-linux-s390x@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.44.tgz#5a1e87d5d6236a8791026820936478f3b9cf8e35" - integrity sha512-2YmTm9BrW5aUwBSe8wIEARd9EcnOQmkHp4+IVaO09Ez/C5T866x+ABzhG0bwx0b+QRo9q97CRMaQx2Ngb6/hfw== - -esbuild-netbsd-64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.44.tgz#8afb16880b530264ce2ed9fb3df26071eb841312" - integrity sha512-zypdzPmZTCqYS30WHxbcvtC0E6e/ECvl4WueUdbdWhs2dfWJt5RtCBME664EpTznixR3lSN1MQ2NhwQF8MQryw== - -esbuild-openbsd-64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.44.tgz#a87455be446d6f5b07a60f060e1eafad454c9d4b" - integrity sha512-8J43ab9ByYl7KteC03HGQjr2HY1ge7sN04lFnwMFWYk2NCn8IuaeeThvLeNjzOYhyT3I6K8puJP0uVXUu+D1xw== - -esbuild-sunos-64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.44.tgz#74ce7d5fd815fa60fe0a85b9db7549b1dcb32804" - integrity sha512-OH1/09CGUJwffA+HNM6mqPkSIyHVC3ZnURU/4CCIx7IqWUBn1Sh1HRLQC8/TWNgcs0/1u7ygnc2pgf/AHZJ/Ow== - -esbuild-windows-32@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.44.tgz#499e1c6cb46c216bdcb62f5b006fec3999bb06a7" - integrity sha512-mCAOL9/rRqwfOfxTu2sjq/eAIs7eAXGiU6sPBnowggI7QS953Iq6o3/uDu010LwfN7zr18c/lEj6/PTwwTB3AA== - -esbuild-windows-64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.44.tgz#a8dae69a4615b17f62375859ce9536dd96940a06" - integrity sha512-AG6BH3+YG0s2Q/IfB1cm68FdyFnoE1P+GFbmgFO3tA4UIP8+BKsmKGGZ5I3+ZjcnzOwvT74bQRVrfnQow2KO5Q== - -esbuild-windows-arm64@0.14.44: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.44.tgz#db73bb68aa75a880bdaa938ccacc0f17e7a4bfea" - integrity sha512-ygYPfYE5By4Sd6szsNr10B0RtWVNOSGmZABSaj4YQBLqh9b9i45VAjVWa8tyIy+UAbKF7WGwybi2wTbSVliO8A== +esbuild-android-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz#505f41832884313bbaffb27704b8bcaa2d8616be" + integrity sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ== + +esbuild-android-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz#8ce69d7caba49646e009968fe5754a21a9871771" + integrity sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg== + +esbuild-darwin-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz#24ba67b9a8cb890a3c08d9018f887cc221cdda25" + integrity sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug== + +esbuild-darwin-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz#3f7cdb78888ee05e488d250a2bdaab1fa671bf73" + integrity sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw== + +esbuild-freebsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz#09250f997a56ed4650f3e1979c905ffc40bbe94d" + integrity sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg== + +esbuild-freebsd-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz#bafb46ed04fc5f97cbdb016d86947a79579f8e48" + integrity sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q== + +esbuild-jest@^0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/esbuild-jest/-/esbuild-jest-0.5.0.tgz#7a9964bfdecafca3b675a8aeb08193bcdba8b9d7" + integrity sha512-AMZZCdEpXfNVOIDvURlqYyHwC8qC1/BFjgsrOiSL1eyiIArVtHL8YAC83Shhn16cYYoAWEW17yZn0W/RJKJKHQ== + dependencies: + "@babel/core" "^7.12.17" + "@babel/plugin-transform-modules-commonjs" "^7.12.13" + babel-jest "^26.6.3" + +esbuild-linux-32@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz#e2a8c4a8efdc355405325033fcebeb941f781fe5" + integrity sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw== + +esbuild-linux-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz#de5fdba1c95666cf72369f52b40b03be71226652" + integrity sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg== + +esbuild-linux-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz#dae4cd42ae9787468b6a5c158da4c84e83b0ce8b" + integrity sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig== + +esbuild-linux-arm@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz#a2c1dff6d0f21dbe8fc6998a122675533ddfcd59" + integrity sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw== + +esbuild-linux-mips64le@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz#d9918e9e4cb972f8d6dae8e8655bf9ee131eda34" + integrity sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw== + +esbuild-linux-ppc64le@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz#3f9a0f6d41073fb1a640680845c7de52995f137e" + integrity sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ== + +esbuild-linux-riscv64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz#618853c028178a61837bc799d2013d4695e451c8" + integrity sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg== + +esbuild-linux-s390x@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz#d1885c4c5a76bbb5a0fe182e2c8c60eb9e29f2a6" + integrity sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA== + +esbuild-netbsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz#69ae917a2ff241b7df1dbf22baf04bd330349e81" + integrity sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w== + +esbuild-openbsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz#db4c8495287a350a6790de22edea247a57c5d47b" + integrity sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw== + +esbuild-sunos-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz#54287ee3da73d3844b721c21bc80c1dc7e1bf7da" + integrity sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw== + +esbuild-windows-32@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz#f8aaf9a5667630b40f0fb3aa37bf01bbd340ce31" + integrity sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w== + +esbuild-windows-64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz#bf54b51bd3e9b0f1886ffdb224a4176031ea0af4" + integrity sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ== + +esbuild-windows-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz#937d15675a15e4b0e4fafdbaa3a01a776a2be982" + integrity sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg== esbuild@^0.14.27: - version "0.14.44" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.44.tgz#27fa3cd4f55d36780650c7f32cab581abc7a4473" - integrity sha512-Rn+lRRfj60r/3svI6NgAVnetzp3vMOj17BThuhshSj/gS1LR03xrjkDYyfPmrYG/0c3D68rC6FNYMQ3yRbiXeQ== + version "0.14.54" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.54.tgz#8b44dcf2b0f1a66fc22459943dccf477535e9aa2" + integrity sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA== optionalDependencies: - esbuild-android-64 "0.14.44" - esbuild-android-arm64 "0.14.44" - esbuild-darwin-64 "0.14.44" - esbuild-darwin-arm64 "0.14.44" - esbuild-freebsd-64 "0.14.44" - esbuild-freebsd-arm64 "0.14.44" - esbuild-linux-32 "0.14.44" - esbuild-linux-64 "0.14.44" - esbuild-linux-arm "0.14.44" - esbuild-linux-arm64 "0.14.44" - esbuild-linux-mips64le "0.14.44" - esbuild-linux-ppc64le "0.14.44" - esbuild-linux-riscv64 "0.14.44" - esbuild-linux-s390x "0.14.44" - esbuild-netbsd-64 "0.14.44" - esbuild-openbsd-64 "0.14.44" - esbuild-sunos-64 "0.14.44" - esbuild-windows-32 "0.14.44" - esbuild-windows-64 "0.14.44" - esbuild-windows-arm64 "0.14.44" + "@esbuild/linux-loong64" "0.14.54" + esbuild-android-64 "0.14.54" + esbuild-android-arm64 "0.14.54" + esbuild-darwin-64 "0.14.54" + esbuild-darwin-arm64 "0.14.54" + esbuild-freebsd-64 "0.14.54" + esbuild-freebsd-arm64 "0.14.54" + esbuild-linux-32 "0.14.54" + esbuild-linux-64 "0.14.54" + esbuild-linux-arm "0.14.54" + esbuild-linux-arm64 "0.14.54" + esbuild-linux-mips64le "0.14.54" + esbuild-linux-ppc64le "0.14.54" + esbuild-linux-riscv64 "0.14.54" + esbuild-linux-s390x "0.14.54" + esbuild-netbsd-64 "0.14.54" + esbuild-openbsd-64 "0.14.54" + esbuild-sunos-64 "0.14.54" + esbuild-windows-32 "0.14.54" + esbuild-windows-64 "0.14.54" + esbuild-windows-arm64 "0.14.54" escalade@^3.1.1: version "3.1.1" @@ -1149,6 +2044,11 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -1163,12 +2063,11 @@ eslint-import-resolver-node@^0.3.6: resolve "^1.20.0" eslint-module-utils@^2.7.3: - 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== + version "2.7.4" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" + integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== dependencies: debug "^3.2.7" - find-up "^2.1.0" eslint-plugin-import@^2: version "2.26.0" @@ -1190,9 +2089,9 @@ eslint-plugin-import@^2: tsconfig-paths "^3.14.1" eslint-plugin-prettier@^4: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" - integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ== + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== dependencies: prettier-linter-helpers "^1.0.0" @@ -1207,9 +2106,9 @@ eslint-plugin-react-perf@^3: integrity sha512-iOx2UtEOH50TmQhezTS4jbBAj/2gbrUdX+ZM28c2K9mwTvtRX6gdnd2P4WPQrejITDsAMNTCz95zu5HcjCD0xg== eslint-plugin-react@^7: - version "7.30.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.0.tgz#8e7b1b2934b8426ac067a0febade1b13bd7064e3" - integrity sha512-RgwH7hjW48BleKsYyHK5vUAvxtE9SMPDKmcPRQgtRCYaZA0XQPt5FSkrU3nhz5ifzMZcA8opwmRJ2cmOO8tr5A== + version "7.30.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22" + integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg== dependencies: array-includes "^3.1.5" array.prototype.flatmap "^1.3.0" @@ -1264,12 +2163,13 @@ eslint-visitor-keys@^3.3.0: integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== eslint@^8: - version "8.18.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.18.0.tgz#78d565d16c993d0b73968c523c0446b13da784fd" - integrity sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA== + version "8.22.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.22.0.tgz#78fcb044196dfa7eef30a9d65944f6f980402c48" + integrity sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA== dependencies: "@eslint/eslintrc" "^1.3.0" - "@humanwhocodes/config-array" "^0.9.2" + "@humanwhocodes/config-array" "^0.10.4" + "@humanwhocodes/gitignore-to-minimatch" "^1.0.2" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -1279,14 +2179,17 @@ eslint@^8: eslint-scope "^7.1.1" eslint-utils "^3.0.0" eslint-visitor-keys "^3.3.0" - espree "^9.3.2" + espree "^9.3.3" esquery "^1.4.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" + find-up "^5.0.0" functional-red-black-tree "^1.0.1" glob-parent "^6.0.1" globals "^13.15.0" + globby "^11.1.0" + grapheme-splitter "^1.0.4" ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" @@ -1304,15 +2207,20 @@ eslint@^8: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^9.3.2: - version "9.3.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596" - integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA== +espree@^9.3.2, espree@^9.3.3: + version "9.3.3" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.3.tgz#2dd37c4162bb05f433ad3c1a52ddf8a49dc08e9d" + integrity sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng== dependencies: - acorn "^8.7.1" + acorn "^8.8.0" acorn-jsx "^5.3.2" eslint-visitor-keys "^3.3.0" +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" @@ -1342,6 +2250,24 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +exec-sh@^0.3.2: + version "0.3.6" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" + integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + execa@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" @@ -1357,6 +2283,79 @@ execa@^4.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + 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" + +expect@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.3.tgz#90a7c1a124f1824133dd4533cce2d2bdcb6603ec" + integrity sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g== + dependencies: + "@jest/expect-utils" "^28.1.3" + jest-get-type "^28.0.2" + jest-matcher-utils "^28.1.3" + jest-message-util "^28.1.3" + jest-util "^28.1.3" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + 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 sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + 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" + 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" @@ -1367,6 +2366,17 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== +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" @@ -1377,6 +2387,20 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +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" + +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + 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" @@ -1384,14 +2408,29 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + 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" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: - locate-path "^2.0.0" + to-regex-range "^5.0.1" + +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@^4.1.0: +find-up@^4.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== @@ -1399,6 +2438,14 @@ find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.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" @@ -1408,16 +2455,28 @@ flat-cache@^3.0.4: 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== + version "3.2.6" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" + integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + dependencies: + map-cache "^0.2.2" fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2: +fsevents@^2.1.2, fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== @@ -1452,6 +2511,11 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +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.2" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" @@ -1461,6 +2525,18 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.3" +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + get-stream@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" @@ -1468,6 +2544,11 @@ get-stream@^5.0.0: dependencies: pump "^3.0.0" +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + 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" @@ -1476,6 +2557,18 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +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 sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + +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" @@ -1483,7 +2576,7 @@ glob-parent@^6.0.1: dependencies: is-glob "^4.0.3" -glob@^7.1.3: +glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -1501,12 +2594,34 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.15.0: - version "13.15.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" - integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== + version "13.17.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" + integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== dependencies: type-fest "^0.20.2" +globby@^11.1.0: + 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" + +graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -1529,7 +2644,7 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" -has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: +has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -1541,6 +2656,37 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + 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 sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1562,11 +2708,21 @@ hoist-non-react-statics@^3.3.1: dependencies: react-is "^16.7.0" +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + husky@^7: version "7.0.4" resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535" @@ -1585,6 +2741,14 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -1612,12 +2776,24 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== +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 sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== + 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: - loose-envify "^1.0.0" + 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" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-bigint@^1.0.1: version "1.0.4" @@ -1634,18 +2810,44 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^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.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-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-core-module@^2.8.1, is-core-module@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" - integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== + version "2.10.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" + integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== 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 sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== + 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.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -1653,12 +2855,52 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" +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-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 sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +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" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-glob@^4.0.0, is-glob@^4.0.3: +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-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +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== @@ -1677,6 +2919,25 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + 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" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +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-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -1692,6 +2953,11 @@ is-shared-array-buffer@^1.0.2: dependencies: call-bind "^1.0.2" +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" @@ -1711,6 +2977,11 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: 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 sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -1718,16 +2989,501 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +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: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + 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 sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f" + integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-28.1.3.tgz#d9aeee6792be3686c47cb988a8eaf82ff4238831" + integrity sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA== + dependencies: + execa "^5.0.0" + p-limit "^3.1.0" + +jest-circus@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.3.tgz#d14bd11cf8ee1a03d69902dc47b6bd4634ee00e4" + integrity sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow== + dependencies: + "@jest/environment" "^28.1.3" + "@jest/expect" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + is-generator-fn "^2.0.0" + jest-each "^28.1.3" + jest-matcher-utils "^28.1.3" + jest-message-util "^28.1.3" + jest-runtime "^28.1.3" + jest-snapshot "^28.1.3" + jest-util "^28.1.3" + p-limit "^3.1.0" + pretty-format "^28.1.3" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.3.tgz#558b33c577d06de55087b8448d373b9f654e46b2" + integrity sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ== + dependencies: + "@jest/core" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/types" "^28.1.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + import-local "^3.0.2" + jest-config "^28.1.3" + jest-util "^28.1.3" + jest-validate "^28.1.3" + prompts "^2.0.1" + yargs "^17.3.1" + +jest-config@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.3.tgz#e315e1f73df3cac31447eed8b8740a477392ec60" + integrity sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^28.1.3" + "@jest/types" "^28.1.3" + babel-jest "^28.1.3" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^28.1.3" + jest-environment-node "^28.1.3" + jest-get-type "^28.0.2" + jest-regex-util "^28.0.2" + jest-resolve "^28.1.3" + jest-runner "^28.1.3" + jest-util "^28.1.3" + jest-validate "^28.1.3" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^28.1.3" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.3.tgz#948a192d86f4e7a64c5264ad4da4877133d8792f" + integrity sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw== + dependencies: + chalk "^4.0.0" + diff-sequences "^28.1.1" + jest-get-type "^28.0.2" + pretty-format "^28.1.3" + +jest-docblock@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-28.1.1.tgz#6f515c3bf841516d82ecd57a62eed9204c2f42a8" + integrity sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA== + dependencies: + detect-newline "^3.0.0" + +jest-each@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.3.tgz#bdd1516edbe2b1f3569cfdad9acd543040028f81" + integrity sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g== + dependencies: + "@jest/types" "^28.1.3" + chalk "^4.0.0" + jest-get-type "^28.0.2" + jest-util "^28.1.3" + pretty-format "^28.1.3" + +jest-environment-node@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.3.tgz#7e74fe40eb645b9d56c0c4b70ca4357faa349be5" + integrity sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A== + dependencies: + "@jest/environment" "^28.1.3" + "@jest/fake-timers" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + jest-mock "^28.1.3" + jest-util "^28.1.3" + +jest-get-type@^28.0.2: + version "28.0.2" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203" + integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA== + +jest-haste-map@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" + integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== + dependencies: + "@jest/types" "^26.6.2" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^26.0.0" + jest-serializer "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" + micromatch "^4.0.2" + sane "^4.0.3" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.1.2" + +jest-haste-map@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.3.tgz#abd5451129a38d9841049644f34b034308944e2b" + integrity sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA== + dependencies: + "@jest/types" "^28.1.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^28.0.2" + jest-util "^28.1.3" + jest-worker "^28.1.3" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz#a6685d9b074be99e3adee816ce84fd30795e654d" + integrity sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA== + dependencies: + jest-get-type "^28.0.2" + pretty-format "^28.1.3" + +jest-matcher-utils@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz#5a77f1c129dd5ba3b4d7fc20728806c78893146e" + integrity sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw== + dependencies: + chalk "^4.0.0" + jest-diff "^28.1.3" + jest-get-type "^28.0.2" + pretty-format "^28.1.3" + +jest-message-util@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.3.tgz#232def7f2e333f1eecc90649b5b94b0055e7c43d" + integrity sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^28.1.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^28.1.3" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.3.tgz#d4e9b1fc838bea595c77ab73672ebf513ab249da" + integrity sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA== + dependencies: + "@jest/types" "^28.1.3" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== + +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== + +jest-regex-util@^28.0.2: + version "28.0.2" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead" + integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw== + +jest-resolve-dependencies@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz#8c65d7583460df7275c6ea2791901fa975c1fe66" + integrity sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA== + dependencies: + jest-regex-util "^28.0.2" + jest-snapshot "^28.1.3" + +jest-resolve@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.3.tgz#cfb36100341ddbb061ec781426b3c31eb51aa0a8" + integrity sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.3" + jest-pnp-resolver "^1.2.2" + jest-util "^28.1.3" + jest-validate "^28.1.3" + resolve "^1.20.0" + resolve.exports "^1.1.0" + slash "^3.0.0" + +jest-runner@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.3.tgz#5eee25febd730b4713a2cdfd76bdd5557840f9a1" + integrity sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA== + dependencies: + "@jest/console" "^28.1.3" + "@jest/environment" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.10.2" + graceful-fs "^4.2.9" + jest-docblock "^28.1.1" + jest-environment-node "^28.1.3" + jest-haste-map "^28.1.3" + jest-leak-detector "^28.1.3" + jest-message-util "^28.1.3" + jest-resolve "^28.1.3" + jest-runtime "^28.1.3" + jest-util "^28.1.3" + jest-watcher "^28.1.3" + jest-worker "^28.1.3" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.3.tgz#a57643458235aa53e8ec7821949e728960d0605f" + integrity sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw== + dependencies: + "@jest/environment" "^28.1.3" + "@jest/fake-timers" "^28.1.3" + "@jest/globals" "^28.1.3" + "@jest/source-map" "^28.1.2" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + execa "^5.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.3" + jest-message-util "^28.1.3" + jest-mock "^28.1.3" + jest-regex-util "^28.0.2" + jest-resolve "^28.1.3" + jest-snapshot "^28.1.3" + jest-util "^28.1.3" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-serializer@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" + integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + +jest-snapshot@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.3.tgz#17467b3ab8ddb81e2f605db05583d69388fc0668" + integrity sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/babel__traverse" "^7.0.6" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^28.1.3" + graceful-fs "^4.2.9" + jest-diff "^28.1.3" + jest-get-type "^28.0.2" + jest-haste-map "^28.1.3" + jest-matcher-utils "^28.1.3" + jest-message-util "^28.1.3" + jest-util "^28.1.3" + natural-compare "^1.4.0" + pretty-format "^28.1.3" + semver "^7.3.5" + +jest-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" + integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^2.0.0" + micromatch "^4.0.2" + +jest-util@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.3.tgz#f4f932aa0074f0679943220ff9cbba7e497028b0" + integrity sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ== + dependencies: + "@jest/types" "^28.1.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.3.tgz#e322267fd5e7c64cea4629612c357bbda96229df" + integrity sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA== + dependencies: + "@jest/types" "^28.1.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^28.0.2" + leven "^3.1.0" + pretty-format "^28.1.3" + +jest-watcher@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.3.tgz#c6023a59ba2255e3b4c57179fc94164b3e73abd4" + integrity sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g== + dependencies: + "@jest/test-result" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.10.2" + jest-util "^28.1.3" + string-length "^4.0.1" + +jest-worker@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest-worker@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.3.tgz#7e3c4ce3fa23d1bb6accb169e7f396f98ed4bb98" + integrity sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^28: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.3.tgz#e9c6a7eecdebe3548ca2b18894a50f45b36dfc6b" + integrity sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA== + dependencies: + "@jest/core" "^28.1.3" + "@jest/types" "^28.1.3" + import-local "^3.0.2" + jest-cli "^28.1.3" + "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@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -1740,6 +3496,11 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +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" @@ -1763,12 +3524,46 @@ json5@^2.2.1: integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== "jsx-ast-utils@^2.4.1 || ^3.0.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.0.tgz#e624f259143b9062c92b6413ff92a164c80d3ccb" - integrity sha512-XzO9luP6L0xkxwhIJMTJQpZo/eeN60K08jHdexfD569AGxeNug6UketeHXEhROoM8aR7EcUoOQmIhcJQjcuq8Q== + version "3.3.3" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" + integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw== dependencies: - array-includes "^3.1.4" - object.assign "^4.1.2" + array-includes "^3.1.5" + object.assign "^4.1.3" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + 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 sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + 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: + 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== + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== levn@^0.4.1: version "0.4.1" @@ -1778,13 +3573,10 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.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@^5.0.0: version "5.0.0" @@ -1793,6 +3585,13 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -1800,21 +3599,86 @@ lodash.merge@^4.6.2: lodash@^4: version "4.17.21" - resolved "https://registry.npm.ouryahoo.com:4443/npm-registry/api/npm/npm-registry/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +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-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + dependencies: + object-visit "^1.0.0" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== +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@^3.1.4: + 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" + +micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -1827,11 +3691,19 @@ minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0, minimist@^1.2.6: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +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" + mri@^1.1.5: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -1868,17 +3740,63 @@ nanoid@^3.3.4: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +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" + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -node-releases@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" - integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -npm-run-path@^4.0.0: +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + dependencies: + path-key "^2.0.0" + +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -1890,6 +3808,15 @@ object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + object-inspect@^1.12.0, object-inspect@^1.9.0: version "1.12.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" @@ -1900,14 +3827,21 @@ 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.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== +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" + isobject "^3.0.0" + +object.assign@^4.1.0, object.assign@^4.1.2, object.assign@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.3.tgz#d36b7700ddf0019abb6b1df1bb13f6445f79051f" + integrity sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" object-keys "^1.1.1" object.entries@^1.1.5: @@ -1936,6 +3870,13 @@ object.hasown@^1.1.1: define-properties "^1.1.4" es-abstract "^1.19.5" +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + dependencies: + isobject "^3.0.1" + object.values@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" @@ -1952,7 +3893,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -1971,12 +3912,10 @@ optionator@^0.9.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-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== p-limit@^2.2.0: version "2.3.0" @@ -1985,12 +3924,12 @@ p-limit@^2.2.0: 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 sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: - p-limit "^1.1.0" + yocto-queue "^0.1.0" p-locate@^4.1.0: version "4.1.0" @@ -1999,10 +3938,12 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.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 sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" p-try@^2.0.0: version "2.2.0" @@ -2016,10 +3957,20 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== +parse-json@^5.0.0, parse-json@^5.2.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" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== path-exists@^4.0.0: version "4.0.0" @@ -2031,6 +3982,11 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -2041,20 +3997,42 @@ path-parse@^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== + 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.2: +picomatch@^2.0.4, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pirates@^4.0.1, pirates@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +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 sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + postcss@^8.4.13: - version "8.4.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" - integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== + version "8.4.16" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.16.tgz#33a1d675fac39941f5f445db0de4db2b6e01d43c" + integrity sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ== dependencies: nanoid "^3.3.4" picocolors "^1.0.0" @@ -2077,6 +4055,16 @@ prettier@2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== +pretty-format@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.3.tgz#c9fba8cedf99ce50963a11b27d982a9ae90970d5" + integrity sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q== + dependencies: + "@jest/schemas" "^28.1.3" + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^18.0.0" + pretty-quick@^3: version "3.1.3" resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.3.tgz#15281108c0ddf446675157ca40240099157b638e" @@ -2089,13 +4077,13 @@ pretty-quick@^3: mri "^1.1.5" multimatch "^4.0.0" -prop-types-extra@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" - integrity sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew== +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== dependencies: - react-is "^16.3.2" - warning "^4.0.0" + kleur "^3.0.3" + sisteransi "^1.0.5" prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" @@ -2119,23 +4107,10 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -react-bootstrap@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-2.4.0.tgz#99bf9656e2e7a23ae1ae135d18fd5ad7c344b416" - integrity sha512-dn599jNK1Fg5GGjJH+lQQDwELVzigh/MdusKpB/0el+sCjsO5MZDH5gRMmBjRhC+vb7VlCDr6OXffPIDSkNMLw== - dependencies: - "@babel/runtime" "^7.17.2" - "@restart/hooks" "^0.4.6" - "@restart/ui" "^1.2.0" - "@types/react-transition-group" "^4.4.4" - classnames "^2.3.1" - dom-helpers "^5.2.1" - invariant "^2.2.4" - prop-types "^15.8.1" - prop-types-extra "^1.1.0" - react-transition-group "^4.4.2" - uncontrollable "^7.2.1" - warning "^4.0.3" +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== react-dom@^18: version "18.2.0" @@ -2145,28 +4120,15 @@ react-dom@^18: loose-envify "^1.1.0" scheduler "^0.23.0" -react-fast-compare@^3.0.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== - -react-is@^16.13.1, react-is@^16.3.2, react-is@^16.7.0: +react-is@^16.13.1, react-is@^16.7.0: 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-lifecycles-compat@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== - -react-popper@^2.2.5: - version "2.3.0" - resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba" - integrity sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q== - dependencies: - react-fast-compare "^3.0.1" - warning "^4.0.2" +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== react-refresh@^0.13.0: version "0.13.0" @@ -2175,7 +4137,7 @@ react-refresh@^0.13.0: react-router-dom@^6: version "6.3.0" - resolved "https://registry.npm.ouryahoo.com:4443/npm-registry/api/npm/npm-registry/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d" integrity sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw== dependencies: history "^5.2.0" @@ -2188,7 +4150,7 @@ react-router@6.3.0: dependencies: history "^5.2.0" -react-textarea-autosize@^8.3.2: +react-textarea-autosize@8.3.4: version "8.3.4" resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.4.tgz#270a343de7ad350534141b02c9cb78903e553524" integrity sha512-CdtmP8Dc19xL8/R6sWvtknD/eCXkQr30dtvC4VmGInhRsfF8X/ihXCq6+9l9qbxmKRiq407/7z5fxE7cVWQNgQ== @@ -2197,7 +4159,7 @@ react-textarea-autosize@^8.3.2: use-composed-ref "^1.3.0" use-latest "^1.2.1" -react-transition-group@^4.4.2: +react-transition-group@4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470" integrity sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg== @@ -2219,6 +4181,14 @@ regenerator-runtime@^0.13.4: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +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" + regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -2233,12 +4203,54 @@ regexpp@^3.2.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== + +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 sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + 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.20.0: +resolve-from@^5.0.0: + version "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 sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + +resolve.exports@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" + integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== + +resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -2247,15 +4259,6 @@ resolve@^1.20.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.22.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.4" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" @@ -2265,25 +4268,69 @@ resolve@^2.0.0-next.3: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -rimraf@^3.0.2: +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== + +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.0, 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" -rollup@^2.59.0: - version "2.75.6" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.75.6.tgz#ac4dc8600f95942a0180f61c7c9d6200e374b439" - integrity sha512-OEf0TgpC9vU6WGROJIk1JA3LR5vk/yvqlzxqdrE2CzzXnqKXNzbAwlWUXis8RS3ZPe7LAq+YUxsRa0l3r27MLA== +"rollup@>=2.59.0 <2.78.0": + version "2.77.3" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.77.3.tgz#8f00418d3a2740036e15deb653bed1a90ee0cc12" + integrity sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g== optionalDependencies: fsevents "~2.3.2" +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== + +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.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== +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + dependencies: + ret "~0.1.10" + +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== + dependencies: + "@cnakazawa/watch" "^1.0.3" + anymatch "^2.0.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" + execa "^1.0.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -2291,11 +4338,40 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" -semver@^6.3.0: +semver@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, 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.5: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + +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" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -2303,6 +4379,11 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" @@ -2317,16 +4398,134 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.2: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, 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== +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +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-js@^1.0.2: 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-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.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + 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, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +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" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + dependencies: + escape-string-regexp "^2.0.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +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.7: version "4.0.7" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d" @@ -2359,7 +4558,7 @@ string.prototype.trimstart@^1.0.5: define-properties "^1.1.4" es-abstract "^1.19.5" -strip-ansi@^6.0.1: +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== @@ -2371,6 +4570,16 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" @@ -2393,28 +4602,97 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: +supports-color@^7.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-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" + integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== + dependencies: + has-flag "^4.0.0" + supports-color "^7.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== +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== +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 sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + 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 sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + 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" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + 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" + tsconfig-paths@^3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" @@ -2425,6 +4703,11 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@^1.0.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + 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" @@ -2432,11 +4715,28 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + 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.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -2447,15 +4747,31 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -uncontrollable@^7.2.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.2.1.tgz#1fa70ba0c57a14d5f78905d533cf63916dc75738" - integrity sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ== +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" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +update-browserslist-db@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38" + integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q== dependencies: - "@babel/runtime" "^7.6.3" - "@types/react" ">=16.9.11" - invariant "^2.2.4" - react-lifecycles-compat "^3.0.4" + escalade "^3.1.1" + picocolors "^1.0.0" uri-js@^4.2.2: version "4.4.1" @@ -2464,6 +4780,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + use-composed-ref@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" @@ -2471,7 +4792,7 @@ use-composed-ref@^1.3.0: use-context-selector@^1: version "1.4.1" - resolved "https://registry.npm.ouryahoo.com:4443/npm-registry/api/npm/npm-registry/use-context-selector/-/use-context-selector-1.4.1.tgz#eb96279965846b72915d7f899b8e6ef1d768b0ae" + resolved "https://registry.yarnpkg.com/use-context-selector/-/use-context-selector-1.4.1.tgz#eb96279965846b72915d7f899b8e6ef1d768b0ae" integrity sha512-Io2ArvcRO+6MWIhkdfMFt+WKQX+Vb++W8DS2l03z/Vw/rz3BclKpM0ynr4LYGyU85Eke+Yx5oIhTY++QR0ZDoA== use-isomorphic-layout-effect@^1.1.1: @@ -2486,29 +4807,43 @@ use-latest@^1.2.1: dependencies: use-isomorphic-layout-effect "^1.1.1" +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== + 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== +v8-to-istanbul@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" + integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + vite@^2: - version "2.9.13" - resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.13.tgz#859cb5d4c316c0d8c6ec9866045c0f7858ca6abc" - integrity sha512-AsOBAaT0AD7Mhe8DuK+/kE4aWYFMx/i0ZNi98hJclxb4e0OhQcZYUrvLjIaQ8e59Ui7txcvKMiJC1yftqpQoDw== + version "2.9.15" + resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.15.tgz#2858dd5b2be26aa394a283e62324281892546f0b" + integrity sha512-fzMt2jK4vQ3yK56te3Kqpkaeq9DkcZfBbzHwYpobasvgYmP2SoAr6Aic05CsB4CzCZbsDv4sujX3pkEGhLabVQ== dependencies: esbuild "^0.14.27" postcss "^8.4.13" resolve "^1.22.0" - rollup "^2.59.0" + rollup ">=2.59.0 <2.78.0" optionalDependencies: fsevents "~2.3.2" -warning@^4.0.0, warning@^4.0.2, warning@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" - integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== +walker@^1.0.7, walker@^1.0.8, walker@~1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: - loose-envify "^1.0.0" + makeerror "1.0.12" which-boxed-primitive@^1.0.2: version "1.0.2" @@ -2521,6 +4856,13 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -2533,7 +4875,72 @@ word-wrap@^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 sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +write-file-atomic@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.1.tgz#9faa33a964c1c85ff6f849b80b42a88c2c537c8f" + integrity sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +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== + +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== + +yargs-parser@^21.0.0: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.3.1: + version "17.5.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" + integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA== + 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" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/cloud-tenant-base-dependencies-enforcer/pom.xml b/cloud-tenant-base-dependencies-enforcer/pom.xml index 1a83afd1be5..a30cbb86299 100644 --- a/cloud-tenant-base-dependencies-enforcer/pom.xml +++ b/cloud-tenant-base-dependencies-enforcer/pom.xml @@ -189,6 +189,7 @@ <include>org.apache.commons:commons-compress:1.21:jar:test</include> <include>org.apache.commons:commons-math3:3.6.1:jar:test</include> <include>org.apache.felix:org.apache.felix.framework:[${felix.version}]:jar:test</include> + <include>org.apache.felix:org.apache.felix.log:1.0.1:jar:test</include> <include>org.apache.httpcomponents.client5:httpclient5:${httpclient5.version}:jar:test</include> <include>org.apache.httpcomponents.core5:httpcore5:${httpclient5.version}:jar:test</include> <include>org.apache.httpcomponents.core5:httpcore5-h2:${httpclient5.version}:jar:test</include> @@ -227,6 +228,8 @@ <include>org.junit.vintage:junit-vintage-engine:[${junit5.version}]:jar:test</include> <include>org.lz4:lz4-java:[${org.lz4.version}]:jar:test</include> <include>org.opentest4j:opentest4j:1.2.0:jar:test</include> + <include>org.osgi:org.osgi.compendium:4.1.0:jar:test</include> + <include>org.osgi:org.osgi.core:4.1.0:jar:test</include> <include>xerces:xercesImpl:2.12.1:jar:test</include> </allowed> </enforceDependencies> diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java index 4097810b633..29887666a1b 100644 --- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java +++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java @@ -22,7 +22,6 @@ import com.yahoo.vespa.clustercontroller.core.status.ClusterStateRequestHandler; import com.yahoo.vespa.clustercontroller.core.status.LegacyIndexPageRequestHandler; import com.yahoo.vespa.clustercontroller.core.status.LegacyNodePageRequestHandler; import com.yahoo.vespa.clustercontroller.core.status.NodeHealthRequestHandler; -import com.yahoo.vespa.clustercontroller.core.status.RunDataExtractor; import com.yahoo.vespa.clustercontroller.core.status.statuspage.StatusPageResponse; import com.yahoo.vespa.clustercontroller.core.status.statuspage.StatusPageServer; import com.yahoo.vespa.clustercontroller.core.status.statuspage.StatusPageServerInterface; @@ -101,13 +100,6 @@ public class FleetController implements NodeListener, SlobrokListener, SystemSta // deriving is done. private Set<String> configuredBucketSpaces = Collections.emptySet(); - private final RunDataExtractor dataExtractor = new RunDataExtractor() { - @Override - public FleetControllerOptions getOptions() { return options; } - @Override - public ContentCluster getCluster() { return cluster; } - }; - public FleetController(FleetControllerContext context, Timer timer, EventLog eventLog, @@ -155,8 +147,7 @@ public class FleetController implements NodeListener, SlobrokListener, SystemSta new ClusterStateRequestHandler(stateVersionTracker)); this.statusRequestRouter.addHandler( "^/$", - new LegacyIndexPageRequestHandler(timer, cluster, masterElectionHandler, stateVersionTracker, eventLog, - timer.getCurrentTimeInMillis(), dataExtractor)); + new LegacyIndexPageRequestHandler(timer, cluster, masterElectionHandler, stateVersionTracker, eventLog, options)); propagateOptions(); } @@ -1153,8 +1144,6 @@ public class FleetController implements NodeListener, SlobrokListener, SystemSta @Override public FleetController getFleetController() { return FleetController.this; } @Override - public SlobrokListener getNodeAddedOrRemovedListener() { return FleetController.this; } - @Override public NodeListener getNodeStateUpdateListener() { return FleetController.this; } }; @@ -1240,4 +1229,5 @@ public class FleetController implements NodeListener, SlobrokListener, SystemSta public EventLog getEventLog() { return eventLog; } + } diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/database/DatabaseHandler.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/database/DatabaseHandler.java index 01b8ed48c80..408c10e81b1 100644 --- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/database/DatabaseHandler.java +++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/database/DatabaseHandler.java @@ -6,14 +6,12 @@ import com.yahoo.vdslib.state.NodeState; import com.yahoo.vdslib.state.State; import com.yahoo.vespa.clustercontroller.core.ClusterStateBundle; import com.yahoo.vespa.clustercontroller.core.ContentCluster; -import com.yahoo.vespa.clustercontroller.core.FleetControllerContext; import com.yahoo.vespa.clustercontroller.core.FleetController; +import com.yahoo.vespa.clustercontroller.core.FleetControllerContext; import com.yahoo.vespa.clustercontroller.core.NodeInfo; import com.yahoo.vespa.clustercontroller.core.Timer; -import com.yahoo.vespa.clustercontroller.core.listeners.SlobrokListener; import com.yahoo.vespa.clustercontroller.core.listeners.NodeListener; import org.apache.zookeeper.KeeperException; - import java.io.PrintWriter; import java.io.StringWriter; import java.util.Map; @@ -32,7 +30,6 @@ public class DatabaseHandler { public interface DatabaseContext { ContentCluster getCluster(); FleetController getFleetController(); - SlobrokListener getNodeAddedOrRemovedListener(); NodeListener getNodeStateUpdateListener(); } @@ -179,7 +176,7 @@ public class DatabaseHandler { private boolean usingZooKeeper() { return (zooKeeperAddress != null); } - private void connect(ContentCluster cluster, long currentTime) { + private void connect(long currentTime) { try { lastZooKeeperConnectionAttempt = currentTime; synchronized (databaseMonitor) { @@ -251,7 +248,7 @@ public class DatabaseHandler { return false; // Not time to attempt connection yet. } didWork = true; - connect(databaseContext.getCluster(), currentTime); + connect(currentTime); } try { synchronized (databaseMonitor) { @@ -344,7 +341,7 @@ public class DatabaseHandler { return didWork; } - public void setMasterVote(DatabaseContext databaseContext, int wantedMasterCandidate) throws InterruptedException { + public void setMasterVote(DatabaseContext databaseContext, int wantedMasterCandidate) { fleetControllerContext.log(logger, Level.FINE, () -> "Checking if master vote has been updated and need to be stored."); // Schedule a write if one of the following is true: // - There is already a pending vote to be written, that may have been written already without our knowledge diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/status/LegacyIndexPageRequestHandler.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/status/LegacyIndexPageRequestHandler.java index 96dc114c734..4f20b3d0cdc 100644 --- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/status/LegacyIndexPageRequestHandler.java +++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/status/LegacyIndexPageRequestHandler.java @@ -36,22 +36,21 @@ public class LegacyIndexPageRequestHandler implements StatusPageServer.RequestHa private final StateVersionTracker stateVersionTracker; private final EventLog eventLog; private final long startedTime; - private final RunDataExtractor data; + private final FleetControllerOptions options; public LegacyIndexPageRequestHandler(Timer timer, ContentCluster cluster, MasterElectionHandler masterElectionHandler, StateVersionTracker stateVersionTracker, EventLog eventLog, - long startedTime, - RunDataExtractor data) { + FleetControllerOptions options) { this.timer = timer; this.cluster = cluster; this.masterElectionHandler = masterElectionHandler; this.stateVersionTracker = stateVersionTracker; this.eventLog = eventLog; - this.startedTime = startedTime; - this.data = data; + this.startedTime = timer.getCurrentTimeInMillis(); + this.options = options; } @Override @@ -63,7 +62,7 @@ public class LegacyIndexPageRequestHandler implements StatusPageServer.RequestHa response.setContentType("text/html"); StringBuilder content = new StringBuilder(); content.append("<!-- Answer to request " + request + " -->\n"); - response.writeHtmlHeader(content, cluster.getName() + " Cluster Controller " + data.getOptions().fleetControllerIndex + " Status Page"); + response.writeHtmlHeader(content, cluster.getName() + " Cluster Controller " + options.fleetControllerIndex + " Status Page"); content.append("<p><font size=\"-1\">") .append(" [ <a href=\"#config\">Current config</a>") .append(" | <a href=\"#clusterstates\">Cluster states</a>") @@ -72,19 +71,19 @@ public class LegacyIndexPageRequestHandler implements StatusPageServer.RequestHa content.append("<table><tr><td>UTC time when creating this page:</td><td align=\"right\">").append(RealTimer.printDateNoMilliSeconds(currentTime, tz)).append("</td></tr>"); //content.append("<tr><td>Fleetcontroller version:</td><td align=\"right\">" + Vtag.V_TAG_PKG + "</td></tr/>"); content.append("<tr><td>Cluster controller uptime:</td><td align=\"right\">" + RealTimer.printDuration(currentTime - startedTime) + "</td></tr></table>"); - if (masterElectionHandler.isAmongNthFirst(data.getOptions().stateGatherCount)) { + if (masterElectionHandler.isAmongNthFirst(options.stateGatherCount)) { // Table overview of all the nodes - writeHtmlState(cluster, content, timer, stateVersionTracker, data.getOptions(), eventLog); + writeHtmlState(cluster, content, timer, stateVersionTracker, options, eventLog); // Current cluster state and cluster state history writeHtmlState(stateVersionTracker, content); } else { // Overview of current config - data.getOptions().writeHtmlState(content); + options.writeHtmlState(content); } // State of master election - masterElectionHandler.writeHtmlState(content, data.getOptions().stateGatherCount); + masterElectionHandler.writeHtmlState(content, options.stateGatherCount); // Overview of current config - data.getOptions().writeHtmlState(content); + options.writeHtmlState(content); // Event log eventLog.writeHtmlState(content, null); response.writeHtmlFooter(content, ""); diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/DatabaseHandlerTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/DatabaseHandlerTest.java index 4d8c7799c58..c07a29b3c1e 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/DatabaseHandlerTest.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/DatabaseHandlerTest.java @@ -9,14 +9,12 @@ import com.yahoo.vespa.clustercontroller.core.database.Database; import com.yahoo.vespa.clustercontroller.core.database.DatabaseFactory; import com.yahoo.vespa.clustercontroller.core.database.DatabaseHandler; import com.yahoo.vespa.clustercontroller.core.listeners.NodeListener; -import com.yahoo.vespa.clustercontroller.core.listeners.SlobrokListener; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.MockitoAnnotations; - import java.util.Map; import java.util.TreeMap; @@ -71,11 +69,6 @@ public class DatabaseHandlerTest { } @Override - public SlobrokListener getNodeAddedOrRemovedListener() { - return null; - } - - @Override public NodeListener getNodeStateUpdateListener() { return null; } diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/FleetControllerTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/FleetControllerTest.java index 371a57e08c0..c39a5c52836 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/FleetControllerTest.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/FleetControllerTest.java @@ -7,7 +7,6 @@ import com.yahoo.jrt.StringValue; import com.yahoo.jrt.Supervisor; import com.yahoo.jrt.Target; import com.yahoo.jrt.Transport; -import com.yahoo.jrt.slobrok.api.BackOffPolicy; import com.yahoo.jrt.slobrok.server.Slobrok; import com.yahoo.log.LogSetup; import com.yahoo.vdslib.distribution.ConfiguredNode; @@ -42,7 +41,6 @@ import java.util.TreeMap; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -83,14 +81,6 @@ public abstract class FleetControllerTest implements Waiter { LogSetup.initVespaLogging("fleetcontroller"); } - static class BackOff implements BackOffPolicy { - private int counter = 0; - public void reset() { counter = 0; } - public double get() { ++counter; return 0.01; } - public boolean shouldWarn(double v) { return ((counter % 1000) == 10); } - public boolean shouldInform(double v) { return false; } - } - public static class CleanupZookeeperLogsOnSuccess implements TestWatcher { public CleanupZookeeperLogsOnSuccess() {} @@ -334,116 +324,6 @@ public abstract class FleetControllerTest implements Waiter { fleetController.waitForCompleteCycle(timeout); } - private static class ExpectLine { - Pattern regex; - int matchedCount = 0; - int minCount = 1; - int maxCount = 1; - boolean repeatable() { return (maxCount == 0 || maxCount > matchedCount); } - boolean optional() { return (matchedCount >= minCount); } - - boolean matches(String event) { - if (event == null) return false; - boolean m = regex.matcher(event).matches(); - if (m) ++matchedCount; - return m; - } - - ExpectLine(String pattern) { - if (pattern.charAt(0) == '?') { - pattern = pattern.substring(1); - minCount = 0; - } else if (pattern.charAt(0) == '*') { - pattern = pattern.substring(1); - minCount = 0; - maxCount = 0; - } else if (pattern.charAt(0) == '+') { - pattern = pattern.substring(1); - maxCount = 0; - } - regex = Pattern.compile(pattern); - } - - public String toString() { - return "{"+minCount+","+maxCount+"}("+matchedCount+") " + regex; - } - } - - /** - * Verifies that node event list is equal to some expected value. - * The format of the expected values is as follows: - * <ul> - * <li>Each line in the exp string specifies a pattern to match one or more events. - * <li>A line starting with ? * or + means that the line can match 0 or 1, 0 or more or 1 or more respectively. - * <li>The rest of the line is a regular expression. - * </ul> - */ - protected void verifyNodeEvents(Node n, String exp) { - List<NodeEvent> events = fleetController.getNodeEvents(n); - String[] expectLines = exp.split("\n"); - List<ExpectLine> expected = new ArrayList<>(); - for (String line : expectLines) { - expected.add(new ExpectLine(line)); - } - - boolean mismatch = false; - StringBuilder errors = new StringBuilder(); - - int gotno = 0; - int expno = 0; - - while (gotno < events.size() || expno < expected.size()) { - String eventLine = null; - if (gotno < events.size()) { - NodeEvent e = events.get(gotno); - eventLine = e.toString(); - } - - ExpectLine pattern = null; - if (expno < expected.size()) { - pattern = expected.get(expno); - } - - if (pattern == null) { - errors.append("Exhausted expected list before matching event " + gotno - + ": '" + eventLine + "'."); - mismatch = true; - break; - } - - if (pattern.matches(eventLine)) { - if (! pattern.repeatable()) { - ++expno; - } - ++gotno; - } else { - if (pattern.optional()) { - ++expno; - } else { - errors.append("Event " + gotno + ": '" + eventLine - + "' did not match regex " + expno + ": " + pattern); - mismatch = true; - break; - } - } - } - if (!mismatch && expno < expected.size()) { - errors.append("Too few entries in event log (only matched " - + expno + " of " + expected.size() + ")"); - mismatch = true; - } - if (mismatch) { - StringBuilder eventsGotten = new StringBuilder(); - for (Event e : events) { - String eventLine = e.toString(); - eventsGotten.append(eventLine).append("\n"); - } - errors.append("\nExpected events matching:\n" + exp + "\n"); - errors.append("but got the following events:\n" + eventsGotten.toString()); - fail(errors.toString()); - } - } - public static Set<ConfiguredNode> toNodes(Integer ... indexes) { return Arrays.stream(indexes) .map(i -> new ConfiguredNode(i, false)) diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/RpcServerTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/RpcServerTest.java index 641f15467a6..6a7c75c629e 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/RpcServerTest.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/RpcServerTest.java @@ -9,6 +9,7 @@ import com.yahoo.jrt.StringValue; import com.yahoo.jrt.Supervisor; import com.yahoo.jrt.Target; import com.yahoo.jrt.Transport; +import com.yahoo.jrt.slobrok.api.BackOffPolicy; import com.yahoo.jrt.slobrok.server.Slobrok; import com.yahoo.vdslib.distribution.ConfiguredNode; import com.yahoo.vdslib.distribution.Distribution; @@ -595,4 +596,12 @@ public class RpcServerTest extends FleetControllerTest { return req; } + private static class BackOff implements BackOffPolicy { + private int counter = 0; + public void reset() { counter = 0; } + public double get() { ++counter; return 0.01; } + public boolean shouldWarn(double v) { return ((counter % 1000) == 10); } + public boolean shouldInform(double v) { return false; } + } + } diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StateChangeTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StateChangeTest.java index 6ad0430b5c3..426ac42fe9e 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StateChangeTest.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StateChangeTest.java @@ -82,7 +82,7 @@ public class StateChangeTest extends FleetControllerTest { super.tearDown(); } - public void verifyNodeEvents(Node n, String correct) { + private void verifyNodeEvents(Node n, String correct) { String actual = ""; for (NodeEvent e : eventLog.getNodeEvents(n)) { actual += e.toString() + "\n"; diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/SystemStateBroadcasterTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/SystemStateBroadcasterTest.java index 0a193766df3..6bc9f434ee6 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/SystemStateBroadcasterTest.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/SystemStateBroadcasterTest.java @@ -6,11 +6,9 @@ import com.yahoo.vdslib.state.NodeState; import com.yahoo.vdslib.state.NodeType; import com.yahoo.vdslib.state.State; import com.yahoo.vespa.clustercontroller.core.database.DatabaseHandler; -import com.yahoo.vespa.clustercontroller.core.listeners.SlobrokListener; import com.yahoo.vespa.clustercontroller.core.listeners.NodeListener; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; - import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -69,11 +67,6 @@ public class SystemStateBroadcasterTest { } @Override - public SlobrokListener getNodeAddedOrRemovedListener() { - return null; - } - - @Override public NodeListener getNodeStateUpdateListener() { return null; } diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/AbstractParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/AbstractParser.java index 586d1d32d57..2d76db889b8 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/AbstractParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/AbstractParser.java @@ -5,12 +5,19 @@ import com.yahoo.language.Language; import com.yahoo.language.process.Segmenter; import com.yahoo.prelude.Index; import com.yahoo.prelude.IndexFacts; -import com.yahoo.prelude.query.*; +import com.yahoo.prelude.query.AndSegmentItem; +import com.yahoo.prelude.query.CompositeItem; +import com.yahoo.prelude.query.Item; +import com.yahoo.prelude.query.NullItem; +import com.yahoo.prelude.query.PhraseItem; +import com.yahoo.prelude.query.PhraseSegmentItem; +import com.yahoo.prelude.query.WordItem; import com.yahoo.search.query.QueryTree; import com.yahoo.search.query.parser.Parsable; import com.yahoo.search.query.parser.ParserEnvironment; -import java.util.*; +import java.util.List; +import java.util.ListIterator; /** * The Vespa query parser. @@ -20,6 +27,7 @@ import java.util.*; */ public abstract class AbstractParser implements CustomParser { + /** The current submodes of this parser */ protected Submodes submodes = new Submodes(); @@ -32,6 +40,8 @@ public abstract class AbstractParser implements CustomParser { /** The IndexFacts.Session of this query */ protected IndexFacts.Session indexFacts; + protected String defaultIndex; + /** * The counter for braces in URLs, braces in URLs are accepted so long as * they are balanced. @@ -125,38 +135,38 @@ public abstract class AbstractParser implements CustomParser { @Override public final Item parse(String queryToParse, String filterToParse, Language parsingLanguage, - IndexFacts.Session indexFacts, String defaultIndexName) { - return parse(queryToParse, filterToParse, parsingLanguage, indexFacts, defaultIndexName, null); + IndexFacts.Session indexFacts, String defaultIndex) { + return parse(queryToParse, filterToParse, parsingLanguage, indexFacts, defaultIndex, null); } private Item parse(String queryToParse, String filterToParse, Language parsingLanguage, - IndexFacts.Session indexFacts, String defaultIndexName, Parsable parsable) { + IndexFacts.Session indexFacts, String defaultIndex, Parsable parsable) { if (queryToParse == null) return null; - tokenize(queryToParse, defaultIndexName, indexFacts, parsingLanguage); + if (defaultIndex != null) + defaultIndex = indexFacts.getCanonicName(defaultIndex); + + tokenize(queryToParse, defaultIndex, indexFacts, parsingLanguage); if (parsingLanguage == null && parsable != null) { - String detectionText = generateLanguageDetectionTextFrom(tokens, indexFacts, defaultIndexName); + String detectionText = generateLanguageDetectionTextFrom(tokens, indexFacts, defaultIndex); if (detectionText.isEmpty()) // heuristic detection text extraction is fallible detectionText = queryToParse; parsingLanguage = parsable.getOrDetectLanguage(detectionText); } - setState(parsingLanguage, indexFacts); + setState(parsingLanguage, indexFacts, defaultIndex); Item root = parseItems(); + if (filterToParse != null) { AnyParser filterParser = new AnyParser(environment); if (root == null) { - root = filterParser.parseFilter(filterToParse, parsingLanguage, indexFacts); + root = filterParser.parseFilter(filterToParse, parsingLanguage, indexFacts, defaultIndex); } else { - root = filterParser.applyFilter(root, filterToParse, parsingLanguage, indexFacts); + root = filterParser.applyFilter(root, filterToParse, parsingLanguage, indexFacts, defaultIndex); } } - root = simplifyPhrases(root); - if (defaultIndexName != null) { - assignDefaultIndex(indexFacts.getCanonicName(defaultIndexName), root); - } - return root; + return simplifyPhrases(root); } /** @@ -222,31 +232,8 @@ public abstract class AbstractParser implements CustomParser { if (tokenOrNull == null) return false; return kind.equals(tokenOrNull.kind); } - - protected abstract Item parseItems(); - /** - * Assigns the default index to query terms having no default index. The - * parser _should_ have done this, for some reason it doesn't. - * - * @param defaultIndex the default index to assign - * @param item the item to check - */ - private static void assignDefaultIndex(String defaultIndex, Item item) { - if (defaultIndex == null || item == null) return; - - if (item instanceof IndexedItem) { - IndexedItem indexName = (IndexedItem) item; - - if ("".equals(indexName.getIndexName())) - indexName.setIndexName(defaultIndex); - } - else if (item instanceof CompositeItem) { - Iterator<Item> items = ((CompositeItem)item).getItemIterator(); - while (items.hasNext()) - assignDefaultIndex(defaultIndex, items.next()); - } - } + protected abstract Item parseItems(); /** * Unicode normalizes some piece of natural language text. The chosen form @@ -258,10 +245,11 @@ public abstract class AbstractParser implements CustomParser { return environment.getLinguistics().getNormalizer().normalize(input); } - protected void setState(Language queryLanguage, IndexFacts.Session indexFacts) { + protected void setState(Language queryLanguage, IndexFacts.Session indexFacts, String defaultIndex) { this.indexFacts = indexFacts; - language = queryLanguage; - submodes.reset(); + this.defaultIndex = defaultIndex; + this.language = queryLanguage; + this.submodes.reset(); } /** @@ -290,8 +278,7 @@ public abstract class AbstractParser implements CustomParser { return unwashed; } else if (unwashed instanceof PhraseItem) { return collapsePhrase((PhraseItem) unwashed); - } else if (unwashed instanceof CompositeItem) { - CompositeItem composite = (CompositeItem) unwashed; + } else if (unwashed instanceof CompositeItem composite) { ListIterator<Item> i = composite.getItemIterator(); while (i.hasNext()) { @@ -309,9 +296,8 @@ public abstract class AbstractParser implements CustomParser { } private static Item collapsePhrase(PhraseItem phrase) { - if (phrase.getItemCount() == 1 && phrase.getItem(0) instanceof WordItem) { + if (phrase.getItemCount() == 1 && phrase.getItem(0) instanceof WordItem word) { // TODO: Other stuff which needs propagation? - WordItem word = (WordItem) phrase.getItem(0); word.setWeight(phrase.getWeight()); return word; } else { diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/AdvancedParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/AdvancedParser.java index 690fc67af7e..8f98763a838 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/AdvancedParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/AdvancedParser.java @@ -1,14 +1,25 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.query.parser; -import com.yahoo.prelude.query.*; +import com.yahoo.prelude.query.AndItem; +import com.yahoo.prelude.query.CompositeItem; +import com.yahoo.prelude.query.EquivItem; +import com.yahoo.prelude.query.Item; +import com.yahoo.prelude.query.NearItem; +import com.yahoo.prelude.query.NotItem; +import com.yahoo.prelude.query.ONearItem; +import com.yahoo.prelude.query.OrItem; +import com.yahoo.prelude.query.RankItem; +import com.yahoo.prelude.query.SegmentItem; +import com.yahoo.prelude.query.WeakAndItem; +import com.yahoo.prelude.query.WordItem; import com.yahoo.search.query.parser.ParserEnvironment; import static com.yahoo.prelude.query.parser.Token.Kind.LBRACE; import static com.yahoo.prelude.query.parser.Token.Kind.NUMBER; /** - * Parser for queries of type advanced. + * Parser for queries of type 'advanced'. * * @author Steinar Knutsen * @deprecated YQL should be used for formal queries @@ -20,6 +31,7 @@ public class AdvancedParser extends StructuredParser { super(environment); } + @Override protected Item parseItems() { return advancedItems(true); } @@ -53,46 +65,40 @@ public class AdvancedParser extends StructuredParser { boolean expectingOperator = false; do { - item = null; - + item = indexableItem().getFirst(); if (item == null) { - item = indexableItem(); - if (item == null) { - item = compositeItem(); - itemIsComposite = true; - } else { - itemIsComposite = false; - } - if (item != null) { - Item newTop = null; + item = compositeItem(); + itemIsComposite = true; + } else { + itemIsComposite = false; + } + if (item != null) { + Item newTop = null; - if (expectingOperator) { - newTop = handleAdvancedOperator(topLevelItem, item, - topLevelIsClosed); - } - if (newTop != null) { // Operator found - topLevelIsClosed = false; - expectingOperator = false; - topLevelItem = newTop; - } else if (topLevelItem == null) { - topLevelItem = item; - if (itemIsComposite) { - topLevelIsClosed = true; - } - expectingOperator = true; - } else if (topLevelItem instanceof CompositeItem - && !(topLevelItem instanceof SegmentItem)) { - ((CompositeItem) topLevelItem).addItem(item); - expectingOperator = true; - } else { - AndItem and = new AndItem(); - - and.addItem(topLevelItem); - and.addItem(item); - topLevelItem = and; - topLevelIsClosed = false; - expectingOperator = true; + if (expectingOperator) { + newTop = handleAdvancedOperator(topLevelItem, item, topLevelIsClosed); + } + if (newTop != null) { // Operator found + topLevelIsClosed = false; + expectingOperator = false; + topLevelItem = newTop; + } else if (topLevelItem == null) { + topLevelItem = item; + if (itemIsComposite) { + topLevelIsClosed = true; } + expectingOperator = true; + } else if (topLevelItem instanceof CompositeItem && !(topLevelItem instanceof SegmentItem)) { + ((CompositeItem) topLevelItem).addItem(item); + expectingOperator = true; + } else { + AndItem and = new AndItem(); + + and.addItem(topLevelItem); + and.addItem(item); + topLevelItem = and; + topLevelIsClosed = false; + expectingOperator = true; } } @@ -178,7 +184,7 @@ public class AdvancedParser extends StructuredParser { int distance = consumeNumericArgument(); if (distance==0) distance=NearItem.defaultDistance; - if (topLevelIsClosed || !(topLevelItem instanceof NearItem) || distance!=((NearItem)topLevelItem).getDistance()) { + if (topLevelIsClosed || !(topLevelItem instanceof NearItem) || distance != ((NearItem)topLevelItem).getDistance()) { NearItem near = new NearItem(distance); near.addItem(topLevelItem); @@ -188,7 +194,7 @@ public class AdvancedParser extends StructuredParser { } else if (isTheWord("onear", item)) { int distance = consumeNumericArgument(); if (distance==0) - distance=ONearItem.defaultDistance; + distance= ONearItem.defaultDistance; if (topLevelIsClosed || !(topLevelItem instanceof ONearItem) || distance!=((ONearItem)topLevelItem).getDistance()) { ONearItem oNear = new ONearItem(distance); diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/AllParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/AllParser.java index 545bb8e777f..9a60eaef76b 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/AllParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/AllParser.java @@ -65,7 +65,7 @@ public class AllParser extends SimpleParser { current = positiveItem(); if (current == null) - current = indexableItem(); + current = indexableItem().getFirst(); if (current == null) current = compositeItem(); @@ -129,8 +129,9 @@ public class AllParser extends SimpleParser { try { if ( ! tokens.skip(MINUS)) return null; if (tokens.currentIsNoIgnore(SPACE)) return null; - - item = indexableItem(); + var itemAndExplicitIndex = indexableItem(); + item = itemAndExplicitIndex.getFirst(); + boolean explicitIndex = itemAndExplicitIndex.getSecond(); if (item == null) { item = compositeItem(); @@ -155,11 +156,11 @@ public class AllParser extends SimpleParser { // but interpret -(N) as a negative item matching a positive number // but interpret --N as a negative item matching a negative number if (item instanceof IntItem && - ((IntItem)item).getIndexName().isEmpty() && + ! explicitIndex && ! isComposited && - ! ((IntItem)item).getNumber().startsWith(("-"))) + ! ((IntItem)item).getNumber().startsWith(("-"))) { item = null; - + } return item; } finally { if (item == null) { @@ -204,8 +205,7 @@ public class AllParser extends SimpleParser { rank.addItem(topLevelItem); } return rank; - } else if ((item instanceof RankItem) && (((RankItem)item).getItem(0) instanceof OrItem)) { - RankItem itemAsRank = (RankItem) item; + } else if ((item instanceof RankItem itemAsRank) && (((RankItem)item).getItem(0) instanceof OrItem)) { OrItem or = (OrItem) itemAsRank.getItem(0); ((RankItem) topLevelItem).addItem(0, or); diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/AnyParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/AnyParser.java index e22043c6b8f..bf778409364 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/AnyParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/AnyParser.java @@ -14,9 +14,7 @@ import com.yahoo.prelude.query.RankItem; import com.yahoo.prelude.query.TermItem; import com.yahoo.search.query.parser.ParserEnvironment; -import java.util.Collections; import java.util.Iterator; -import java.util.Set; import static com.yahoo.prelude.query.parser.Token.Kind.*; @@ -31,12 +29,13 @@ public class AnyParser extends SimpleParser { super(environment); } + @Override protected Item parseItems() { return anyItems(true); } - Item parseFilter(String filter, Language queryLanguage, IndexFacts.Session indexFacts) { - setState(queryLanguage, indexFacts); + Item parseFilter(String filter, Language queryLanguage, IndexFacts.Session indexFacts, String defaultIndex) { + setState(queryLanguage, indexFacts, defaultIndex); tokenize(filter, null, indexFacts, queryLanguage); Item filterRoot = anyItems(true); @@ -55,7 +54,7 @@ public class AnyParser extends SimpleParser { if ( ! tokens.skipMultiple(MINUS)) return null; if (tokens.currentIsNoIgnore(SPACE)) return null; - item = indexableItem(); + item = indexableItem().getFirst(); if (item == null) { item = compositeItem(); @@ -123,8 +122,8 @@ public class AnyParser extends SimpleParser { } } - Item applyFilter(Item root, String filter, Language queryLanguage, IndexFacts.Session indexFacts) { - setState(queryLanguage, indexFacts); + Item applyFilter(Item root, String filter, Language queryLanguage, IndexFacts.Session indexFacts, String defaultIndex) { + setState(queryLanguage, indexFacts, defaultIndex); tokenize(filter, null, indexFacts, queryLanguage); return filterItems(root); } @@ -148,16 +147,14 @@ public class AnyParser extends SimpleParser { private Item filterItems(Item root) { while (tokens.hasNext()) { - Item item = null; - - item = positiveItem(); + Item item = positiveItem(); root = addAndFilter(root, item); if (item == null) { item = negativeItem(); root = addNotFilter(root, item); } if (item == null) { - item = indexableItem(); + item = indexableItem().getFirst(); root = addRankFilter(root, item); } diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/CustomParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/CustomParser.java index e867def5903..e3b2278475b 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/CustomParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/CustomParser.java @@ -7,7 +7,6 @@ import com.yahoo.prelude.query.Item; import com.yahoo.search.query.parser.Parser; import java.util.Collections; -import java.util.Objects; import java.util.Set; /** diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/ParseException.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/ParseException.java index bef2ca9ffe9..82515c51c05 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/ParseException.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/ParseException.java @@ -1,13 +1,11 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.query.parser; - /** * Parser exceptions. JavaCC legacy, never thrown. * - * @author bratseth + * @author bratseth */ -@SuppressWarnings("serial") public class ParseException extends RuntimeException { public ParseException(String message) { diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/PhraseParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/PhraseParser.java index 75edf9fbf5c..01b5b943829 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/PhraseParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/PhraseParser.java @@ -16,6 +16,7 @@ public class PhraseParser extends AbstractParser { super(environment); } + @Override protected Item parseItems() { return forcedPhrase(); } diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/ProgrammaticParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/ProgrammaticParser.java index 6a005bc0ec9..209753a596c 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/ProgrammaticParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/ProgrammaticParser.java @@ -9,8 +9,6 @@ import com.yahoo.search.query.QueryTree; import com.yahoo.search.query.parser.Parsable; import com.yahoo.search.query.textserialize.TextSerialize; -import java.util.Set; - /** * @author Simon Thoresen Hult */ @@ -32,4 +30,5 @@ public final class ProgrammaticParser implements CustomParser { if (queryToParse == null) return null; return TextSerialize.parse(queryToParse); } + } diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/SimpleParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/SimpleParser.java index 27bce6bd027..b7355c43f81 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/SimpleParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/SimpleParser.java @@ -1,7 +1,16 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.query.parser; -import com.yahoo.prelude.query.*; +import com.yahoo.prelude.query.AndItem; +import com.yahoo.prelude.query.BlockItem; +import com.yahoo.prelude.query.CompositeItem; +import com.yahoo.prelude.query.Item; +import com.yahoo.prelude.query.NotItem; +import com.yahoo.prelude.query.OrItem; +import com.yahoo.prelude.query.PhraseItem; +import com.yahoo.prelude.query.RankItem; +import com.yahoo.prelude.query.TermItem; +import com.yahoo.prelude.query.TrueItem; import com.yahoo.search.query.parser.ParserEnvironment; import java.util.Iterator; @@ -50,7 +59,7 @@ abstract class SimpleParser extends StructuredParser { private Item anyItemsBody(boolean topLevel) { Item topLevelItem = null; NotItem not = null; - Item item = null; + Item item; do { item = positiveItem(); if (item != null) { @@ -88,7 +97,7 @@ abstract class SimpleParser extends StructuredParser { } if (item == null) { - item = indexableItem(); + item = indexableItem().getFirst(); if (item != null) { if (topLevelItem == null) { topLevelItem = item; @@ -173,9 +182,7 @@ abstract class SimpleParser extends StructuredParser { return null; } - if (item == null) { - item = indexableItem(); - } + item = indexableItem().getFirst(); if (item == null) { item = compositeItem(); @@ -196,12 +203,10 @@ abstract class SimpleParser extends StructuredParser { * (+ items) are not found, but negatives are. */ private Item getItemAsPositiveItem(Item item, NotItem not) { - if (!(item instanceof RankItem)) { + if (!(item instanceof RankItem rank)) { return item; } - RankItem rank = (RankItem) item; - // Remove the not from the rank item, the rank should generally // be the first, but this is not always the case int limit = rank.getItemCount(); diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/StructuredParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/StructuredParser.java index f993c7a9e02..88490237fc7 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/StructuredParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/StructuredParser.java @@ -1,12 +1,31 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.query.parser; +import com.yahoo.collections.Pair; import com.yahoo.prelude.IndexFacts; -import com.yahoo.prelude.query.*; +import com.yahoo.prelude.query.AndItem; +import com.yahoo.prelude.query.AndSegmentItem; +import com.yahoo.prelude.query.BlockItem; +import com.yahoo.prelude.query.CompositeItem; +import com.yahoo.prelude.query.IntItem; +import com.yahoo.prelude.query.Item; +import com.yahoo.prelude.query.MarkerWordItem; +import com.yahoo.prelude.query.PhraseItem; +import com.yahoo.prelude.query.PhraseSegmentItem; +import com.yahoo.prelude.query.PrefixItem; +import com.yahoo.prelude.query.SegmentItem; +import com.yahoo.prelude.query.Substring; +import com.yahoo.prelude.query.SubstringItem; +import com.yahoo.prelude.query.SuffixItem; +import com.yahoo.prelude.query.TaggableItem; +import com.yahoo.prelude.query.TermItem; +import com.yahoo.prelude.query.UriItem; +import com.yahoo.prelude.query.WordItem; import com.yahoo.search.query.parser.ParserEnvironment; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import static com.yahoo.prelude.query.parser.Token.Kind.*; @@ -51,12 +70,22 @@ abstract class StructuredParser extends AbstractParser { submodes.setFromIndex(indexName, indexFacts); } - protected Item indexableItem() { + /** + * Returns an item and whether it had an explicit index ('indexname:' prefix). + * + * @return an item and whether it has an explicit index, or a Pair with the first element null if none + */ + protected Pair<Item, Boolean> indexableItem() { int position = tokens.getPosition(); Item item = null; try { + boolean explicitIndex = false; String indexName = indexPrefix(); + if (indexName != null) + explicitIndex = true; + else + indexName = this.defaultIndex; setSubmodeFromIndex(indexName, indexFacts); item = number(); @@ -78,7 +107,6 @@ abstract class StructuredParser extends AbstractParser { if (item != null) { weight = weightSuffix(); } - if (indexName != null && item != null) { item.setIndexName(indexName); } @@ -87,7 +115,7 @@ abstract class StructuredParser extends AbstractParser { item.setWeight(weight); } - return item; + return new Pair<>(item, explicitIndex); } finally { if (item == null) { tokens.setPosition(position); @@ -101,8 +129,7 @@ abstract class StructuredParser extends AbstractParser { if (tokens.currentIsNoIgnore(SPACE)) { return false; } - if (tokens.currentIsNoIgnore(NUMBER) - || tokens.currentIsNoIgnore(WORD)) { + if (tokens.currentIsNoIgnore(NUMBER) || tokens.currentIsNoIgnore(WORD)) { return true; } tokens.skipNoIgnore(); @@ -278,7 +305,6 @@ abstract class StructuredParser extends AbstractParser { tokens.skip(LSQUAREBRACKET); if (item == null) tokens.skipNoIgnore(SPACE); - // TODO: Better definition of start and end of numeric items if (item == null && tokens.currentIsNoIgnore(MINUS) && (tokens.currentNoIgnore(1).kind == NUMBER)) { tokens.skipNoIgnore(); @@ -584,7 +610,7 @@ abstract class StructuredParser extends AbstractParser { if (firstWord instanceof IntItem) { IntItem asInt = (IntItem) firstWord; firstWord = new WordItem(asInt.stringValue(), asInt.getIndexName(), - true, asInt.getOrigin()); + true, asInt.getOrigin()); } composite.addItem(firstWord); composite.addItem(word); diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/Token.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/Token.java index b668df9208c..3bf4d9dcf01 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/Token.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/Token.java @@ -1,7 +1,6 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.query.parser; - import com.yahoo.prelude.query.Substring; /** @@ -11,7 +10,7 @@ import com.yahoo.prelude.query.Substring; */ public class Token { - public static enum Kind { + public enum Kind { EOF("<EOF>"), NUMBER("<NUMBER>"), WORD("<WORD>"), @@ -77,31 +76,6 @@ public class Token { /** Returns whether this is a <i>special token</i> */ public boolean isSpecial() { return special; } - public String toString() { return image; } - - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (object.getClass() != this.getClass()) { - return false; - } - - Token other = (Token) object; - - if (this.kind != other.kind) { - return false; - } - if (!(this.image.equals(other.image))) { - return false; - } - - return true; - } - /** * Returns the substring containing the image ins original form (including casing), * as well as all the text surrounding the token @@ -110,6 +84,22 @@ public class Token { */ public Substring getSubstring() { return substring; } + @Override + public String toString() { return image; } + + @Override + public boolean equals(Object object) { + if (this == object) return true; + if (object == null) return false; + if (object.getClass() != this.getClass()) return false; + + Token other = (Token) object; + if (this.kind != other.kind) return false; + if (!(this.image.equals(other.image))) return false; + return true; + } + + @Override public int hashCode() { return image.hashCode() ^ kind.hashCode(); } diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/TokenPosition.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/TokenPosition.java index 9c60abab637..5ead962e430 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/TokenPosition.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/TokenPosition.java @@ -37,9 +37,7 @@ final class TokenPosition { * Returns null (no exception) if there are no more tokens. */ public Token current() { - Token token = current(0); - - return token; + return current(0); } /** diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/Tokenizer.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/Tokenizer.java index 93b8cf1ed83..c1d415b8e27 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/Tokenizer.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/Tokenizer.java @@ -84,7 +84,6 @@ public final class Tokenizer { * @param indexFacts information about the indexes we will search * @return a read-only list of tokens. This list can only be used by this thread */ - @SuppressWarnings({"deprecation"}) // To avoid this we need to pass an IndexFacts.session down instead - easily done but not without breaking API's public List<Token> tokenize(String string, String defaultIndexName, IndexFacts.Session indexFacts) { this.source = string; diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/UnicodePropertyDump.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/UnicodePropertyDump.java index b01b1295f45..8d2adfe0d78 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/UnicodePropertyDump.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/UnicodePropertyDump.java @@ -26,13 +26,13 @@ class UnicodePropertyDump { boolean debug = false; if (arg.length > 0) { - start = Integer.valueOf(arg[0]).intValue(); + start = Integer.parseInt(arg[0]); } if (arg.length > 1) { - end = Integer.valueOf(arg[1]).intValue(); + end = Integer.parseInt(arg[1]); } if (arg.length > 2) { - debug = Boolean.valueOf(arg[2]).booleanValue(); + debug = Boolean.parseBoolean(arg[2]); } dumpProperties(start, end, debug, System.out); } @@ -109,4 +109,5 @@ class UnicodePropertyDump { out.println(); } } + } diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/WebParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/WebParser.java index d7c7dec4798..aff28179050 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/parser/WebParser.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/WebParser.java @@ -45,7 +45,7 @@ public class WebParser extends AllParser { current = positiveItem(); if (current == null) - current = indexableItem(); + current = indexableItem().getFirst(); if (current != null) { if (and != null && (current instanceof WordItem) && "OR".equals(((WordItem)current).getRawWord())) { diff --git a/container-search/src/test/java/com/yahoo/prelude/test/QueryTestCase.java b/container-search/src/test/java/com/yahoo/prelude/test/QueryTestCase.java index 95ecf3c2dba..06b6eca5f84 100644 --- a/container-search/src/test/java/com/yahoo/prelude/test/QueryTestCase.java +++ b/container-search/src/test/java/com/yahoo/prelude/test/QueryTestCase.java @@ -195,7 +195,7 @@ public class QueryTestCase { assertTrue(p.hashCode() != q.hashCode()); } - /** Test using the defauultindex feature */ + /** Test using the defaultindex feature */ @Test void testDefaultIndex() { Query q = newQuery("?query=hi hello keyword:kanoo " + diff --git a/container-search/src/test/java/com/yahoo/search/test/QueryTestCase.java b/container-search/src/test/java/com/yahoo/search/test/QueryTestCase.java index f8a77445a40..a722552b7d2 100644 --- a/container-search/src/test/java/com/yahoo/search/test/QueryTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/test/QueryTestCase.java @@ -452,10 +452,34 @@ public class QueryTestCase { @Test void testDefaultIndex() { - Query q = new Query("?query=hi%20hello%20keyword:kanoo%20" + - "default:munkz%20%22phrases+too%22&default-index=def"); + Query q = new Query("?query=hi%20hello%20keyword:kanoo%20default:munkz%20%22phrases+too%22&default-index=def"); assertEquals("WEAKAND(100) def:hi def:hello keyword:kanoo default:munkz def:\"phrases too\"", - q.getModel().getQueryTree().toString()); + q.getModel().getQueryTree().toString()); + } + + @Test + void testDefaultIndexAlias() { + SearchDefinition test = new SearchDefinition("test"); + Index year = new Index("year"); + year.setNumerical(true); + year.addAlias("yearalias"); + test.addIndex(year); + test.addAlias("yearalias", "year"); + IndexModel indexModel = new IndexModel(test); + + { + Query q = new Query("?default-index=year&type=all"); + q.getModel().setExecution(new Execution(Execution.Context.createContextStub(new IndexFacts(indexModel)))); + q.getModel().setQueryString("2000"); + assertEquals("select * from sources * where year = 2000", q.yqlRepresentation()); + } + + { + Query q = new Query("?default-index=yearalias&type=all"); + q.getModel().setExecution(new Execution(Execution.Context.createContextStub(new IndexFacts(indexModel)))); + q.getModel().setQueryString("2000"); + assertEquals("select * from sources * where year = 2000", q.yqlRepresentation()); + } } @Test diff --git a/container-search/src/test/java/com/yahoo/search/yql/UserInputTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/UserInputTestCase.java index 8fe451dd095..1e3b52c23af 100644 --- a/container-search/src/test/java/com/yahoo/search/yql/UserInputTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/yql/UserInputTestCase.java @@ -3,7 +3,10 @@ package com.yahoo.search.yql; import static org.junit.jupiter.api.Assertions.*; -import com.yahoo.search.query.QueryTree; +import com.yahoo.prelude.Index; +import com.yahoo.prelude.IndexFacts; +import com.yahoo.prelude.IndexModel; +import com.yahoo.prelude.SearchDefinition; import org.apache.http.client.utils.URIBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -367,4 +370,32 @@ public class UserInputTestCase { assertEquals("select * from sources * where text_field contains \"boom\"", query.yqlRepresentation()); } + @Test + void testUserInputWithPhraseSegmentingIndex() { + execution = new Execution(searchChain, Execution.Context.createContextStub(createIndexFacts(true))); + URIBuilder builder = searchUri(); + builder.setParameter("wql", "foo&bar"); + builder.setParameter("yql", "select * from sources * where ([{\"defaultIndex\": \"text_field\",\"grammar\": \"any\"}]userInput(@wql))"); + Query query = searchAndAssertNoErrors(builder); + assertEquals("select * from sources * where text_field contains phrase(\"foo\", \"bar\")", query.yqlRepresentation()); + } + + @Test + void testUserInputWithNonPhraseSegmentingIndex() { + execution = new Execution(searchChain, Execution.Context.createContextStub(createIndexFacts(false))); + URIBuilder builder = searchUri(); + builder.setParameter("wql", "foo&bar"); + builder.setParameter("yql", "select * from sources * where ([{\"defaultIndex\": \"text_field\",\"grammar\": \"any\"}]userInput(@wql))"); + Query query = searchAndAssertNoErrors(builder); + assertEquals("select * from sources * where (text_field contains \"foo\" AND text_field contains \"bar\")", query.yqlRepresentation()); + } + + private IndexFacts createIndexFacts(boolean phraseSegmenting) { + SearchDefinition sd = new SearchDefinition("sources"); + Index test = new Index("text_field"); + test.setPhraseSegmenting(phraseSegmenting); + sd.addIndex(test); + return new IndexFacts(new IndexModel(sd)); + } + } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/RunDataStore.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/RunDataStore.java index 9cf508d37c9..3558d18f721 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/RunDataStore.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/RunDataStore.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.controller.api.integration; import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId; +import java.io.InputStream; import java.util.Optional; /** @@ -29,4 +30,10 @@ public interface RunDataStore { /** Deletes all data associated with the given application. */ void delete(ApplicationId id); + /** Stores Vespa logs for the run. */ + void putLogs(RunId id, boolean tester, InputStream logs); + + /** Fetches Vespa logs for the run. */ + InputStream getLogs(RunId id, boolean tester); + } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/Cluster.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/Cluster.java index b500cd1c133..08f975fbc29 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/Cluster.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/Cluster.java @@ -82,35 +82,47 @@ public class Cluster { public static class Utilization { - private final double cpu, idealCpu, currentCpu, memory, idealMemory, currentMemory, disk, idealDisk, currentDisk; + private final double cpu, idealCpu, currentCpu, peakCpu; + private final double memory, idealMemory, currentMemory, peakMemory; + private final double disk, idealDisk, currentDisk, peakDisk; - public Utilization(double cpu, double idealCpu, double currentCpu, - double memory, double idealMemory, double currentMemory, - double disk, double idealDisk, double currentDisk) { + public Utilization(double cpu, double idealCpu, double currentCpu, double peakCpu, + double memory, double idealMemory, double currentMemory, double peakMemory, + double disk, double idealDisk, double currentDisk, double peakDisk) { this.cpu = cpu; this.idealCpu = idealCpu; this.currentCpu = currentCpu; + this.peakCpu = peakCpu; + this.memory = memory; this.idealMemory = idealMemory; this.currentMemory = currentMemory; + this.peakMemory = peakMemory; + this.disk = disk; this.idealDisk = idealDisk; this.currentDisk = currentDisk; + this.peakDisk = peakDisk; } public double cpu() { return cpu; } public double idealCpu() { return idealCpu; } public double currentCpu() { return currentCpu; } + public double peakCpu() { return peakCpu; } public double memory() { return memory; } public double idealMemory() { return idealMemory; } public double currentMemory() { return currentMemory; } + public double peakMemory() { return peakMemory; } public double disk() { return disk; } public double idealDisk() { return idealDisk; } public double currentDisk() { return currentDisk; } + public double peakDisk() { return peakDisk; } - public static Utilization empty() { return new Utilization(0, 0, 0, 0, 0, 0, 0, 0, 0); } + public static Utilization empty() { return new Utilization(0, 0, 0, 0, 0, + 0, 0, 0, + 0, 0, 0, 0); } } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/noderepository/ClusterUtilizationData.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/noderepository/ClusterUtilizationData.java index 803daf6a8c6..6632ba47b7b 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/noderepository/ClusterUtilizationData.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/noderepository/ClusterUtilizationData.java @@ -21,6 +21,8 @@ public class ClusterUtilizationData { public Double idealCpu; @JsonProperty("currentCpu") public Double currentCpu; + @JsonProperty("peakCpu") + public Double peakCpu; @JsonProperty("memory") public Double memory; @@ -28,6 +30,8 @@ public class ClusterUtilizationData { public Double idealMemory; @JsonProperty("currentMemory") public Double currentMemory; + @JsonProperty("peakMemory") + public Double peakMemory; @JsonProperty("disk") public Double disk; @@ -35,9 +39,13 @@ public class ClusterUtilizationData { public Double idealDisk; @JsonProperty("currentDisk") public Double currentDisk; + @JsonProperty("peakDisk") + public Double peakDisk; public Cluster.Utilization toClusterUtilization() { - return new Cluster.Utilization(cpu, idealCpu, currentCpu, memory, idealMemory, currentMemory, disk, idealDisk, currentDisk); + return new Cluster.Utilization(cpu, idealCpu, currentCpu, peakCpu, + memory, idealMemory, currentMemory, peakMemory, + disk, idealDisk, currentDisk, peakDisk); } } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockRunDataStore.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockRunDataStore.java index 32591cfe4e2..cc1e084de8e 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockRunDataStore.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockRunDataStore.java @@ -5,10 +5,14 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.hosted.controller.api.integration.RunDataStore; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import static com.yahoo.yolean.Exceptions.uncheck; + /** * @author jonmv */ @@ -16,6 +20,8 @@ public class MockRunDataStore implements RunDataStore { private final Map<RunId, byte[]> logs = new ConcurrentHashMap<>(); private final Map<RunId, byte[]> reports = new ConcurrentHashMap<>(); + private final Map<RunId, byte[]> vespaLogs = new ConcurrentHashMap<>(); + private final Map<RunId, byte[]> testerLogs = new ConcurrentHashMap<>(); @Override public Optional<byte[]> get(RunId id) { @@ -49,4 +55,14 @@ public class MockRunDataStore implements RunDataStore { reports.keySet().removeIf(runId -> runId.application().equals(id)); } + @Override + public void putLogs(RunId id, boolean tester, InputStream logs) { + (tester ? testerLogs : vespaLogs).put(id, uncheck(logs::readAllBytes)); + } + + @Override + public InputStream getLogs(RunId id, boolean tester) { + return new ByteArrayInputStream((tester ? testerLogs : vespaLogs).get(id)); + } + } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java index 51da1d42926..43928b31b93 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java @@ -221,7 +221,8 @@ enum PathGroup { publicInfo("/user/v1/user", // Information about who you are. "/badge/v1/{*}", // Badges for deployment jobs. "/zone/v1/{*}", // Lists environment and regions. - "/cli/v1/{*}"), // Public information for Vespa CLI. + "/cli/v1/{*}", // Public information for Vespa CLI. + "/.well-known/{*}"), /** Paths used for deploying system-wide feature flags. */ systemFlagsDeploy("/system-flags/v1/deploy"), diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java index ac7c6319c1b..a340982bec0 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java @@ -12,6 +12,7 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.Property; import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId; import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact; import com.yahoo.vespa.hosted.controller.api.integration.secrets.TenantSecretStore; +import com.yahoo.vespa.hosted.controller.api.role.SimplePrincipal; import com.yahoo.vespa.hosted.controller.tenant.ArchiveAccess; import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; @@ -154,8 +155,11 @@ public abstract class LockedTenant { public Cloud withDeveloperKey(PublicKey key, Principal principal) { BiMap<PublicKey, Principal> keys = HashBiMap.create(developerKeys); + principal = new SimplePrincipal(principal.getName()); if (keys.containsKey(key)) throw new IllegalArgumentException("Key " + KeyUtils.toPem(key) + " is already owned by " + keys.get(key)); + if (keys.inverse().containsKey(principal)) + throw new IllegalArgumentException(principal + " is already associated with key " + KeyUtils.toPem(keys.inverse().get(principal))); keys.put(key, principal); return new Cloud(name, createdAt, lastLoginInfo, creator, keys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java index 881107fa0f9..7114402f824 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java @@ -38,6 +38,9 @@ import com.yahoo.vespa.hosted.controller.persistence.CuratorDb; import com.yahoo.vespa.hosted.controller.versions.VersionStatus; import com.yahoo.vespa.hosted.controller.versions.VespaVersion; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; import java.security.cert.X509Certificate; import java.time.Duration; import java.time.Instant; @@ -181,20 +184,30 @@ public class JobController { if ( ! run.hasStep(copyVespaLogs)) return run; + storeVespaLogs(id); + + // TODO jonmv: remove all the below around start of 2023. ZoneId zone = id.type().zone(); Optional<Deployment> deployment = Optional.ofNullable(controller.applications().requireInstance(id.application()) .deployments().get(zone)); if (deployment.isEmpty() || deployment.get().at().isBefore(run.start())) return run; - Instant deployedAt = run.stepInfo(installInitialReal).or(() -> run.stepInfo(installReal)).flatMap(StepInfo::startTime).orElseThrow(); - Instant from = run.lastVespaLogTimestamp().isAfter(run.start()) ? run.lastVespaLogTimestamp() : deployedAt.minusSeconds(10); - List<LogEntry> log = LogEntry.parseVespaLog(controller.serviceRegistry().configServer() - .getLogs(new DeploymentId(id.application(), zone), - Map.of("from", Long.toString(from.toEpochMilli()))), - from); + List<LogEntry> log; + Instant deployedAt; + Instant from; + if ( ! run.id().type().isProduction()) { + deployedAt = run.stepInfo(installInitialReal).or(() -> run.stepInfo(installReal)).flatMap(StepInfo::startTime).orElseThrow(); + from = run.lastVespaLogTimestamp().isAfter(run.start()) ? run.lastVespaLogTimestamp() : deployedAt.minusSeconds(10); + log = LogEntry.parseVespaLog(controller.serviceRegistry().configServer() + .getLogs(new DeploymentId(id.application(), zone), + Map.of("from", Long.toString(from.toEpochMilli()))), + from); + } + else + log = List.of(); - if (run.hasStep(installTester) && run.versions().targetPlatform().isAfter(new Version("7.590"))) { // todo jonmv: remove + if (id.type().isTest()) { deployedAt = run.stepInfo(installTester).flatMap(StepInfo::startTime).orElseThrow(); from = run.lastVespaLogTimestamp().isAfter(run.start()) ? run.lastVespaLogTimestamp() : deployedAt.minusSeconds(10); List<LogEntry> testerLog = LogEntry.parseVespaLog(controller.serviceRegistry().configServer() @@ -216,6 +229,47 @@ public class JobController { }); } + public InputStream getVespaLogs(RunId id, long fromMillis, boolean tester) { + Run run = run(id); + return run.stepStatus(copyVespaLogs).map(succeeded::equals).orElse(false) + ? controller.serviceRegistry().runDataStore().getLogs(id, tester) + : getVespaLogsFromLogserver(run, fromMillis, tester); + } + + public static Optional<Instant> deploymentCompletedAt(Run run, boolean tester) { + return (tester ? run.stepInfo(installTester) + : run.stepInfo(installInitialReal).or(() -> run.stepInfo(installReal))) + .flatMap(StepInfo::startTime); + } + + public void storeVespaLogs(RunId id) { + Run run = run(id); + if ( ! id.type().isProduction()) { + try (InputStream logs = getVespaLogsFromLogserver(run, 0, false)) { + controller.serviceRegistry().runDataStore().putLogs(id, false, logs); + } + catch (IOException e) { + throw new UncheckedIOException(e); + } + } + if (id.type().isTest()) { + try (InputStream logs = getVespaLogsFromLogserver(run, 0, true)) { + controller.serviceRegistry().runDataStore().putLogs(id, true, logs); + } + catch (IOException e) { + throw new UncheckedIOException(e); + } + } + } + + private InputStream getVespaLogsFromLogserver(Run run, long fromMillis, boolean tester) { + long deploymentCompletedAtMillis = deploymentCompletedAt(run, tester).orElse(Instant.EPOCH).toEpochMilli(); + return controller.serviceRegistry().configServer().getLogs(new DeploymentId(tester ? run.id().tester().id() : run.id().application(), + run.id().type().zone()), + Map.of("from", Long.toString(Math.max(fromMillis, deploymentCompletedAtMillis)), + "to", Long.toString(run.end().orElse(controller.clock().instant()).toEpochMilli()))); + } + /** Fetches any new test log entries, and records the id of the last of these, for continuation. */ public void updateTestLog(RunId id) { locked(id, run -> { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobProfile.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobProfile.java index 5f9207953ca..f0ec39b8d1c 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobProfile.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobProfile.java @@ -63,6 +63,7 @@ public enum JobProfile { installTester, startTests, endTests, + copyVespaLogs, deactivateTester, report)), diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java index 5fa90d98c18..2d0424e9f03 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java @@ -50,24 +50,8 @@ public class OsUpgradeScheduler extends ControllerMaintainer { if (upgradingToNewMajor(cloud)) return Optional.empty(); // Skip further upgrades until major version upgrade is complete Release release = releaseIn(cloud); - Instant instant = controller().clock().instant(); - Version wantedVersion = release.version(currentTarget.get(), instant); - Version currentVersion = currentTarget.get().version(); - if (release instanceof CalendarVersionedRelease) { - // Estimate the next change - while (!wantedVersion.isAfter(currentVersion)) { - instant = instant.plus(Duration.ofDays(1)); - wantedVersion = release.version(currentTarget.get(), instant); - } - } else if (!wantedVersion.isAfter(currentVersion)) { - return Optional.empty(); // No change right now, and we cannot predict the next change for this kind of release - } - // Find the earliest possible trigger time on this day - instant = instant.truncatedTo(ChronoUnit.DAYS); - while (!canTriggerAt(instant)) { - instant = instant.plus(Duration.ofHours(1)); - } - return Optional.of(new Change(wantedVersion, release.upgradeBudget(), instant)); + Instant now = controller().clock().instant(); + return release.change(currentTarget.get().version(), now); } private boolean upgradingToNewMajor(CloudName cloud) { @@ -86,22 +70,28 @@ public class OsUpgradeScheduler extends ControllerMaintainer { return new CalendarVersionedRelease(controller().system()); } - private boolean canTriggerAt(Instant instant) { + private static boolean canTriggerAt(Instant instant, boolean isCd) { ZonedDateTime dateTime = instant.atZone(ZoneOffset.UTC); int hourOfDay = dateTime.getHour(); int dayOfWeek = dateTime.getDayOfWeek().getValue(); // Upgrade can only be scheduled between 07:00 (02:00 in CD systems) and 12:59 UTC, Monday-Thursday - int startHour = controller().system().isCd() ? 2 : 7; + int startHour = isCd ? 2 : 7; return hourOfDay >= startHour && hourOfDay <= 12 && dayOfWeek < 5; } - private interface Release { + /** Returns the earliest time an upgrade can be scheduled on the day of instant, in given system */ + private static Instant schedulingInstant(Instant instant, SystemName system) { + instant = instant.truncatedTo(ChronoUnit.DAYS); + while (!canTriggerAt(instant, system.isCd())) { + instant = instant.plus(Duration.ofHours(1)); + } + return instant; + } - /** The version number of this */ - Version version(OsVersionTarget currentTarget, Instant now); + private interface Release { - /** The budget to use when upgrading to this */ - Duration upgradeBudget(); + /** The pending change for this release at given instant, if any */ + Optional<Change> change(Version currentVersion, Instant instant); } @@ -130,15 +120,11 @@ public class OsUpgradeScheduler extends ControllerMaintainer { } @Override - public Version version(OsVersionTarget currentTarget, Instant now) { - OsRelease release = artifactRepository.osRelease(currentTarget.osVersion().version().getMajor(), tag()); - boolean cooldownPassed = !release.taggedAt().plus(cooldown()).isAfter(now); - return cooldownPassed ? release.version() : currentTarget.osVersion().version(); - } - - @Override - public Duration upgradeBudget() { - return Duration.ZERO; // Upgrades to tagged releases happen in-place so no budget is required + public Optional<Change> change(Version currentVersion, Instant instant) { + OsRelease release = artifactRepository.osRelease(currentVersion.getMajor(), tag()); + if (!release.version().isAfter(currentVersion)) return Optional.empty(); + Instant scheduleAt = schedulingInstant(release.taggedAt().plus(cooldown()), system); + return Optional.of(new Change(release.version(), Duration.ZERO, scheduleAt)); } /** Returns the release tag tracked by this system */ @@ -174,14 +160,16 @@ public class OsUpgradeScheduler extends ControllerMaintainer { } @Override - public Version version(OsVersionTarget currentTarget, Instant now) { - Version currentVersion = currentTarget.osVersion().version(); - Version wantedVersion = asVersion(dateOfWantedVersion(now), currentVersion); - return wantedVersion.isAfter(currentVersion) ? wantedVersion : currentVersion; + public Optional<Change> change(Version currentVersion, Instant instant) { + Version wantedVersion = asVersion(dateOfWantedVersion(instant), currentVersion); + while (!wantedVersion.isAfter(currentVersion)) { + instant = instant.plus(Duration.ofDays(1)); + wantedVersion = asVersion(dateOfWantedVersion(instant), currentVersion); + } + return Optional.of(new Change(wantedVersion, upgradeBudget(), schedulingInstant(instant, system))); } - @Override - public Duration upgradeBudget() { + private Duration upgradeBudget() { return system.isCd() ? Duration.ZERO : Duration.ofDays(14); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java index 8d2fac84bc0..a4bb9034a85 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java @@ -272,6 +272,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler { if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job/{jobtype}/diff/{number}")) return devApplicationPackageDiff(runIdFromPath(path)); if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job/{jobtype}/test-config")) return testConfig(appIdFromPath(path), jobTypeFromPath(path)); if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job/{jobtype}/run/{number}")) return JobControllerApiHandlerHelper.runDetailsResponse(controller.jobController(), runIdFromPath(path), request.getProperty("after")); + if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job/{jobtype}/run/{number}/logs")) return JobControllerApiHandlerHelper.vespaLogsResponse(controller.jobController(), runIdFromPath(path), asLong(request.getProperty("from"), 0), request.getBooleanProperty("tester")); if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/environment/{environment}/region/{region}")) return deployment(path.get("tenant"), path.get("application"), path.get("instance"), path.get("environment"), path.get("region"), request); if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/environment/{environment}/region/{region}/reindexing")) return getReindexing(path.get("tenant"), path.get("application"), path.get("instance"), path.get("environment"), path.get("region"), request); if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/environment/{environment}/region/{region}/suspended")) return suspended(path.get("tenant"), path.get("application"), path.get("instance"), path.get("environment"), path.get("region"), request); @@ -2622,12 +2623,17 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler { utilizationObject.setDouble("cpu", utilization.cpu()); utilizationObject.setDouble("idealCpu", utilization.idealCpu()); utilizationObject.setDouble("currentCpu", utilization.currentCpu()); + utilizationObject.setDouble("peakCpu", utilization.peakCpu()); + utilizationObject.setDouble("memory", utilization.memory()); utilizationObject.setDouble("idealMemory", utilization.idealMemory()); utilizationObject.setDouble("currentMemory", utilization.currentMemory()); + utilizationObject.setDouble("peakMemory", utilization.peakMemory()); + utilizationObject.setDouble("disk", utilization.disk()); utilizationObject.setDouble("idealDisk", utilization.idealDisk()); utilizationObject.setDouble("currentDisk", utilization.currentDisk()); + utilizationObject.setDouble("peakDisk", utilization.peakDisk()); } private void scalingEventsToSlime(List<Cluster.ScalingEvent> scalingEvents, Cursor scalingEventsArray) { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java index 25953c16bf0..60f65070557 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java @@ -8,7 +8,6 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.restapi.MessageResponse; import com.yahoo.restapi.SlimeJsonResponse; -import com.yahoo.slime.ArrayTraverser; import com.yahoo.slime.Cursor; import com.yahoo.slime.Slime; import com.yahoo.slime.SlimeUtils; @@ -16,16 +15,15 @@ import com.yahoo.text.Text; import com.yahoo.vespa.hosted.controller.Application; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.NotExistsException; +import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; import com.yahoo.vespa.hosted.controller.api.integration.LogEntry; import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion; import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RevisionId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId; -import com.yahoo.vespa.hosted.controller.api.integration.deployment.SourceRevision; import com.yahoo.vespa.hosted.controller.application.Change; import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId; -import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage; import com.yahoo.vespa.hosted.controller.deployment.ConvergenceSummary; import com.yahoo.vespa.hosted.controller.deployment.DeploymentStatus; import com.yahoo.vespa.hosted.controller.deployment.JobController; @@ -39,11 +37,13 @@ import com.yahoo.vespa.hosted.controller.deployment.Versions; import com.yahoo.vespa.hosted.controller.versions.VersionStatus; import com.yahoo.vespa.hosted.controller.versions.VespaVersion; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.net.URI; import java.time.Instant; import java.time.format.TextStyle; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Locale; @@ -53,6 +53,7 @@ import java.util.stream.Stream; import static com.yahoo.config.application.api.DeploymentSpec.UpgradePolicy.canary; import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.succeeded; +import static com.yahoo.vespa.hosted.controller.deployment.Step.copyVespaLogs; import static com.yahoo.vespa.hosted.controller.deployment.Step.installInitialReal; import static com.yahoo.vespa.hosted.controller.deployment.Step.installReal; import static com.yahoo.vespa.hosted.controller.versions.VespaVersion.Confidence.broken; @@ -154,9 +155,27 @@ class JobControllerApiHandlerHelper { .map(Slime::get) .ifPresent(reportArrayCursor -> SlimeUtils.copyArray(reportArrayCursor, detailsObject.setArray("testReports"))); + boolean logsStored = run.stepStatus(copyVespaLogs).map(succeeded::equals).orElse(false); + if (run.hasStep(copyVespaLogs) && ! runId.type().isProduction() && JobController.deploymentCompletedAt(run, false).isPresent()) + detailsObject.setBool("vespaLogsActive", ! logsStored); + + if (runId.type().isTest() && JobController.deploymentCompletedAt(run, true).isPresent()) + detailsObject.setBool("testerLogsActive", ! logsStored); + return new SlimeJsonResponse(slime); } + /** Proxies a Vespa log request for a run to S3 once logs have been copied, or to logserver before this. */ + static HttpResponse vespaLogsResponse(JobController jobController, RunId runId, long fromMillis, boolean tester) { + return new HttpResponse(200) { + @Override public void render(OutputStream out) throws IOException { + try (InputStream logs = jobController.getVespaLogs(runId, fromMillis, tester)) { + logs.transferTo(out); + } + } + }; + } + private static void toSlime(Cursor summaryObject, ConvergenceSummary summary) { summaryObject.setLong("nodes", summary.nodes()); summaryObject.setLong("down", summary.down()); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandler.java new file mode 100644 index 00000000000..a8af9692bd6 --- /dev/null +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandler.java @@ -0,0 +1,44 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.restapi.controller; + +import com.yahoo.container.jdisc.HttpRequest; +import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.container.jdisc.ThreadedHttpRequestHandler; +import com.yahoo.restapi.ErrorResponse; +import com.yahoo.restapi.Path; +import com.yahoo.restapi.StringResponse; +import com.yahoo.vespa.hosted.controller.config.WellKnownFolderConfig; + + +/** + * Responsible for serving contents from the RFC 8615 well-known directory + * @author olaa + */ +public class WellKnownApiHandler extends ThreadedHttpRequestHandler { + + private final String securityTxt; + + public WellKnownApiHandler(Context context, WellKnownFolderConfig wellKnownFolderConfig) { + super(context); + this.securityTxt = wellKnownFolderConfig.securityTxt(); + } + + @Override + public HttpResponse handle(HttpRequest request) { + switch (request.getMethod()) { + case GET: return get(request); + default: return ErrorResponse.methodNotAllowed("Method '" + request.getMethod() + "' is not supported"); + } + } + + private HttpResponse get(HttpRequest request) { + Path path = new Path(request.getUri()); + if (path.matches("/.well-known/security.txt")) return securityTxt(); + return ErrorResponse.notFoundError("Nothing at " + path); + } + + private HttpResponse securityTxt() { + return new StringResponse(securityTxt); + } + +} diff --git a/controller-server/src/main/resources/configdefinitions/vespa.hosted.controller.config.well-known-folder.def b/controller-server/src/main/resources/configdefinitions/vespa.hosted.controller.config.well-known-folder.def new file mode 100644 index 00000000000..655d570bc58 --- /dev/null +++ b/controller-server/src/main/resources/configdefinitions/vespa.hosted.controller.config.well-known-folder.def @@ -0,0 +1,5 @@ +# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +# Config for serving content from .well-known directory +namespace=vespa.hosted.controller.config + +securityTxt string
\ No newline at end of file diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java index 493c0945ecc..784ea284de5 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java @@ -470,28 +470,24 @@ public class InternalStepRunnerTest { new LogEntry(lastId + 4, tester.clock().instant().minusSeconds(4), info, "17491290-v6-1.ostk.bm2.prod.ne1.yahoo.com\tcontainer\tstdout\n" + "ERROR: Bundle canary-application [71] Unable to get module class path. (java.lang.NullPointerException)"), - /* new LogEntry(lastId + 5, tester.clock().instant().minusSeconds(4), info, "17491290-v6-1.ostk.bm2.prod.ne1.yahoo.com\tcontainer\tstdout\n" + "ERROR: Bundle canary-application [71] Unable to get module class path. (java.lang.NullPointerException)"), new LogEntry(lastId + 6, tester.clock().instant().minusSeconds(4), info, "17491290-v6-1.ostk.bm2.prod.ne1.yahoo.com\tcontainer\tstdout\n" + "ERROR: Bundle canary-application [71] Unable to get module class path. (java.lang.NullPointerException)"), - */ - new LogEntry(lastId + 5, tester.clock().instant().minusSeconds(3), info, + new LogEntry(lastId + 7, tester.clock().instant().minusSeconds(3), info, "17491290-v6-1.ostk.bm2.prod.ne1.yahoo.com\tcontainer\tstdout\n" + "ERROR: Bundle canary-application [71] Unable to get module class path. (java.lang.NullPointerException)"), - new LogEntry(lastId + 6, tester.clock().instant().minusSeconds(3), warning, + new LogEntry(lastId + 8, tester.clock().instant().minusSeconds(3), warning, "17491290-v6-1.ostk.bm2.prod.ne1.yahoo.com\tcontainer\tstderr\n" + - "java.lang.NullPointerException\n\tat org.apache.felix.framework.BundleRevisionImpl.calculateContentPath(BundleRevisionImpl.java:438)\n\tat org.apache.felix.framework.BundleRevisionImpl.initializeContentPath(BundleRevisionImpl.java:371)")); - /* + "java.lang.NullPointerException\n\tat org.apache.felix.framework.BundleRevisionImpl.calculateContentPath(BundleRevisionImpl.java:438)\n\tat org.apache.felix.framework.BundleRevisionImpl.initializeContentPath(BundleRevisionImpl.java:371)"), new LogEntry(lastId + 9, tester.clock().instant().minusSeconds(3), info, "17491290-v6-1.ostk.bm2.prod.ne1.yahoo.com\tcontainer\tstdout\n" + "ERROR: Bundle canary-application [71] Unable to get module class path. (java.lang.NullPointerException)"), new LogEntry(lastId + 10, tester.clock().instant().minusSeconds(3), warning, "17491290-v6-1.ostk.bm2.prod.ne1.yahoo.com\tcontainer\tstderr\n" + "java.lang.NullPointerException\n\tat org.apache.felix.framework.BundleRevisionImpl.calculateContentPath(BundleRevisionImpl.java:438)\n\tat org.apache.felix.framework.BundleRevisionImpl.initializeContentPath(BundleRevisionImpl.java:371)")); - */ } @Test diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java index 35a12f4b6d4..d7f83979054 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java @@ -115,7 +115,9 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer current, Optional.of(new ClusterResources(2, 1, new NodeResources(3, 8, 50, 1, slow, remote))), Optional.empty(), - new Cluster.Utilization(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9), + new Cluster.Utilization(0.1, 0.2, 0.3, 0.35, + 0.4, 0.5, 0.6, 0.65, + 0.7, 0.8, 0.9, 1.0), List.of(new Cluster.ScalingEvent(new ClusterResources(0, 0, NodeResources.unspecified()), current, Instant.ofEpochMilli(1234), diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeSchedulerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeSchedulerTest.java index ddd2163b426..5ed441398fd 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeSchedulerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeSchedulerTest.java @@ -88,7 +88,7 @@ public class OsUpgradeSchedulerTest { void schedule_stable_release() { ControllerTester tester = new ControllerTester(); OsUpgradeScheduler scheduler = new OsUpgradeScheduler(tester.controller(), Duration.ofDays(1)); - Instant t0 = Instant.parse("2021-06-21T07:00:00.00Z"); // Inside trigger period + Instant t0 = Instant.parse("2021-06-21T06:00:00.00Z"); // Outside trigger period tester.clock().setInstant(t0); // Set initial target @@ -96,11 +96,13 @@ public class OsUpgradeSchedulerTest { Version version0 = Version.fromString("8.0"); tester.controller().upgradeOsIn(cloud, version0, Duration.ZERO, false); - // Stable release is scheduled immediately + // Stable release is scheduled once trigger period opens Version version1 = Version.fromString("8.1"); tester.serviceRegistry().artifactRepository().addRelease(new OsRelease(version1, OsRelease.Tag.stable, tester.clock().instant())); - scheduleUpgradeAfter(Duration.ZERO, version1, scheduler, tester); + scheduleUpgradeAfter(Duration.ZERO, version0, scheduler, tester); + assertEquals(version1, scheduler.changeIn(cloud).get().version(), "Change available"); + scheduleUpgradeAfter(Duration.ofHours(1), version1, scheduler, tester); // Inside trigger period // A newer version is triggered manually Version version3 = Version.fromString("8.3"); @@ -108,9 +110,7 @@ public class OsUpgradeSchedulerTest { // Nothing happens in next iteration as tagged release is older than manually triggered version scheduleUpgradeAfter(Duration.ofDays(7), version3, scheduler, tester); - - // Next change cannot be estimated for tagged releases - assertTrue(scheduler.changeIn(cloud).isEmpty(), "Next change is unknown"); + assertTrue(scheduler.changeIn(cloud).isEmpty()); } @Test @@ -129,6 +129,7 @@ public class OsUpgradeSchedulerTest { Version version1 = Version.fromString("8.1"); tester.serviceRegistry().artifactRepository().addRelease(new OsRelease(version1, OsRelease.Tag.latest, tester.clock().instant())); + assertEquals(version1, scheduler.changeIn(cloud).get().version(), "Change available"); scheduleUpgradeAfter(Duration.ZERO, version0, scheduler, tester); // Cooldown period passes and latest release is scheduled diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java index 324c9706df9..a927439de1c 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java @@ -80,7 +80,7 @@ public class ControllerContainerCloudTest extends ControllerContainerTest { } public RequestBuilder data(byte[] data) { this.data = data; return this; } public RequestBuilder data(String data) { this.data = data.getBytes(StandardCharsets.UTF_8); return this; } - public RequestBuilder principal(String principal) { this.principal = new SimplePrincipal(principal); return this; } + public RequestBuilder principal(String principal) { this.principal = new SimplePrincipal(principal){ }; return this; } public RequestBuilder user(User user) { this.user = user; return this; } public RequestBuilder roles(Set<Role> roles) { this.roles = roles; return this; } public RequestBuilder roles(Role... roles) { return roles(Set.of(roles)); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java index 233b460333e..168b9b374f3 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java @@ -7,6 +7,7 @@ import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.slime.SlimeUtils; import com.yahoo.vespa.hosted.controller.api.integration.configserver.ConfigServerException; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RevisionId; +import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.TestReport; import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId; import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage; @@ -144,6 +145,10 @@ public class JobControllerApiHandlerHelperTest { assertResponse(JobControllerApiHandlerHelper.runResponse(app.application(), tester.jobs().runs(userApp.instanceId(), devAwsUsEast2a), Optional.empty(), URI.create("https://some.url:43/root")), "dev-aws-us-east-2a-runs.json"); assertResponse(JobControllerApiHandlerHelper.jobTypeResponse(tester.controller(), userApp.instanceId(), URI.create("https://some.url:43/root/")), "overview-user-instance.json"); assertResponse(JobControllerApiHandlerHelper.overviewResponse(tester.controller(), app.application().id(), URI.create("https://some.url:43/root/")), "deployment-overview-2.json"); + + tester.configServer().setLogStream(() -> "no more logs"); + assertResponse(JobControllerApiHandlerHelper.vespaLogsResponse(tester.jobs(), new RunId(app.instanceId(), stagingTest, 1), 0, false), "vespa.log"); + assertResponse(JobControllerApiHandlerHelper.vespaLogsResponse(tester.jobs(), new RunId(app.instanceId(), stagingTest, 1), 0, true), "vespa.log"); } @Test @@ -197,11 +202,17 @@ public class JobControllerApiHandlerHelperTest { Path path = Paths.get("src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/").resolve(fileName); ByteArrayOutputStream baos = new ByteArrayOutputStream(); response.render(baos); - byte[] actualJson = SlimeUtils.toJsonBytes(SlimeUtils.jsonToSlimeOrThrow(baos.toByteArray()).get(), false); - // Files.write(path, actualJson); - byte[] expected = Files.readAllBytes(path); - assertEquals(new String(SlimeUtils.toJsonBytes(SlimeUtils.jsonToSlimeOrThrow(expected).get(), false), UTF_8), - new String(actualJson, UTF_8)); + if (fileName.endsWith(".json")) { + byte[] actualJson = SlimeUtils.toJsonBytes(SlimeUtils.jsonToSlimeOrThrow(baos.toByteArray()).get(), false); + // Files.write(path, actualJson); + byte[] expected = Files.readAllBytes(path); + assertEquals(new String(SlimeUtils.toJsonBytes(SlimeUtils.jsonToSlimeOrThrow(expected).get(), false), UTF_8), + new String(actualJson, UTF_8)); + } + else { + assertEquals(Files.readString(path), + baos.toString(UTF_8)); + } } catch (Exception e) { throw new RuntimeException(e); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-clusters.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-clusters.json index 3eff2ab781a..137ea64eba7 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-clusters.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-clusters.json @@ -58,12 +58,15 @@ "cpu": 0.1, "idealCpu": 0.2, "currentCpu": 0.3, + "peakCpu": 0.35, "memory": 0.4, "idealMemory": 0.5, "currentMemory": 0.6, + "peakMemory": 0.65, "disk": 0.7, "idealDisk": 0.8, - "currentDisk": 0.9 + "currentDisk": 0.9, + "peakDisk": 1.0 }, "scalingEvents": [ { diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-overview-2.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-overview-2.json index a7e2d1913cf..a02fb1fb375 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-overview-2.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-overview-2.json @@ -967,6 +967,10 @@ "status": "succeeded" }, { + "name": "copyVespaLogs", + "status": "succeeded" + }, + { "name": "deactivateTester", "status": "succeeded" }, @@ -1016,6 +1020,10 @@ "status": "succeeded" }, { + "name": "copyVespaLogs", + "status": "succeeded" + }, + { "name": "deactivateTester", "status": "succeeded" }, diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1-log-first-part.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1-log-first-part.json index 9b391196d55..3190dee06fa 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1-log-first-part.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1-log-first-part.json @@ -82,5 +82,6 @@ "copyVespaLogs": { "status": "unfinished" } - } + }, + "vespaLogsActive": true } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1-log-second-part.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1-log-second-part.json index 4ffac2bf738..cee7e0f4c92 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1-log-second-part.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1-log-second-part.json @@ -39,5 +39,6 @@ "status": "succeeded", "startMillis": 0 } - } + }, + "vespaLogsActive": false } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/staging-test-log.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/staging-test-log.json index a2f62621f5b..0b8937c31a4 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/staging-test-log.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/staging-test-log.json @@ -232,5 +232,7 @@ "status": "succeeded", "startMillis": 14503000 } - } + }, + "vespaLogsActive": false, + "testerLogsActive": false } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-details.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-details.json index a691762c40b..638a7e24ee7 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-details.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-details.json @@ -401,5 +401,7 @@ "status": "succeeded", "startMillis": 1600000000000 } - } + }, + "vespaLogsActive": false, + "testerLogsActive": false } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-log.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-log.json index 4e8737d5f67..a8b38079b6f 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-log.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-log.json @@ -404,5 +404,7 @@ "failed": 0 } } - ] + ], + "vespaLogsActive": false, + "testerLogsActive": false } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/vespa.log b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/vespa.log new file mode 100644 index 00000000000..25916d9e6df --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/vespa.log @@ -0,0 +1 @@ +INFO - All good
\ No newline at end of file diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandlerTest.java new file mode 100644 index 00000000000..d46fc3f18cc --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandlerTest.java @@ -0,0 +1,50 @@ +package com.yahoo.vespa.hosted.controller.restapi.controller; + +import com.yahoo.application.container.handler.Request; +import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; +import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * @author olaa + */ +class WellKnownApiHandlerTest extends ControllerContainerTest { + + private ContainerTester tester; + private final String SECURITY_TXT = "Mocked security txt"; + + @BeforeEach + public void before() { + tester = new ContainerTester(container, "src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/"); + } + + @Test + void securityTxt() { + tester.assertResponse(new Request("http://localhost:8080/.well-known/security.txt"), SECURITY_TXT); + } + + @Override + protected String variablePartXml() { + return String.format(""" + <component id='com.yahoo.vespa.hosted.controller.security.CloudAccessControlRequests'/> + <component id='com.yahoo.vespa.hosted.controller.security.CloudAccessControl'/> + <handler id="com.yahoo.vespa.hosted.controller.restapi.controller.WellKnownApiHandler" bundle="controller-clients" > + <config name="vespa.hosted.controller.config.well-known-folder"> + <securityTxt>%s</securityTxt> + </config> + <binding>http://*/.well-known/*</binding> + </handler> + <http> + <server id='default' port='8080' /> + <filtering> + <request-chain id='default'> + <filter id='com.yahoo.jdisc.http.filter.security.misc.NoopFilter'/> + <binding>http://*/*</binding> + </request-chain> + </filtering> + </http> + """, SECURITY_TXT); + } + +}
\ No newline at end of file diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java index 1344b106bbe..f34dd3fe629 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java @@ -136,6 +136,14 @@ public class UserApiTest extends ControllerContainerCloudTest { "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Key " + quotedPemPublicKey + " is already owned by joe@dev\"}", 400); + // POST a different developer key for an existing user is forbidden + tester.assertResponse(request("/application/v4/tenant/my-tenant/key", POST) + .principal("joe@dev") + .roles(Set.of(Role.developer(id.tenant()))) + .data("{\"key\":\"" + otherPemPublicKey + "\"}"), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"joe@dev is already associated with key " + quotedPemPublicKey + "\"}", + 400); + // POST in a different pem developer key tester.assertResponse(request("/application/v4/tenant/my-tenant/key", POST) .principal("developer@tenant") diff --git a/default_build_settings.cmake b/default_build_settings.cmake index 009cd6d615e..979b71f96b3 100644 --- a/default_build_settings.cmake +++ b/default_build_settings.cmake @@ -64,7 +64,7 @@ endfunction() function(setup_vespa_default_build_settings_darwin) message("-- Setting up default build settings for darwin") - set(DEFAULT_VESPA_LLVM_VERSION "13" PARENT_SCOPE) + set(DEFAULT_VESPA_LLVM_VERSION "14" PARENT_SCOPE) set(DEFAULT_CMAKE_PREFIX_PATH "${VESPA_DEPS}" "/usr/local/opt/bison" "/usr/local/opt/flex" "/usr/local/opt/openssl@1.1" "/usr/local/opt/openblas" "/usr/local/opt/icu4c" PARENT_SCOPE) set(DEFAULT_EXTRA_LINK_DIRECTORY "${VESPA_DEPS}/lib" "/usr/local/opt/bison/lib" "/usr/local/opt/flex/lib" "/usr/local/opt/icu4c/lib" "/usr/local/opt/openssl@1.1/lib" "/usr/local/opt/openblas/lib") list(APPEND DEFAULT_EXTRA_LINK_DIRECTORY "/usr/local/lib") @@ -351,8 +351,8 @@ function(vespa_use_default_cxx_compiler) unset(DEFAULT_CMAKE_CXX_COMPILER) if(NOT DEFINED VESPA_COMPILER_VARIANT OR VESPA_COMPILER_VARIANT STREQUAL "gcc") if(APPLE) - set(DEFAULT_CMAKE_C_COMPILER "/usr/local/bin/gcc-11") - set(DEFAULT_CMAKE_CXX_COMPILER "/usr/local/bin/g++-11") + set(DEFAULT_CMAKE_C_COMPILER "/usr/local/bin/gcc-12") + set(DEFAULT_CMAKE_CXX_COMPILER "/usr/local/bin/g++-12") elseif(VESPA_OS_DISTRO_COMBINED STREQUAL "amzn 2") set(DEFAULT_CMAKE_C_COMPILER "/usr/bin/gcc10-gcc") set(DEFAULT_CMAKE_CXX_COMPILER "/usr/bin/gcc10-g++") @@ -403,12 +403,12 @@ function(vespa_use_default_java_home) if (DEFINED JAVA_HOME) return() endif() - set(DEFAULT_JAVA_HOME "/usr/lib/jvm/java-11-openjdk") + set(DEFAULT_JAVA_HOME "/usr/lib/jvm/java-17-openjdk") if(APPLE) execute_process(COMMAND "/usr/libexec/java_home" OUTPUT_VARIABLE DEFAULT_JAVA_HOME) string(STRIP "${DEFAULT_JAVA_HOME}" DEFAULT_JAVA_HOME) - elseif(VESPA_OS_DISTRO STREQUAL "ubuntu") - set(DEFAULT_JAVA_HOME "/usr/lib/jvm/java-11-openjdk-amd64" PARENT_SCOPE) + elseif(VESPA_OS_DISTRO STREQUAL "ubuntu" OR VESPA_OS_DISTRO STREQUAL "debian") + set(DEFAULT_JAVA_HOME "/usr/lib/jvm/java-17-openjdk-amd64" PARENT_SCOPE) endif() if(COMMAND vespa_use_specific_java_home) vespa_use_specific_java_home() diff --git a/dist/vespa.spec b/dist/vespa.spec index b94a77491b8..b05a8853da1 100644 --- a/dist/vespa.spec +++ b/dist/vespa.spec @@ -111,7 +111,7 @@ BuildRequires: vespa-gtest = 1.11.0 %define _use_vespa_gtest 1 BuildRequires: vespa-icu-devel >= 65.1.0-1 BuildRequires: vespa-lz4-devel >= 1.9.2-2 -BuildRequires: vespa-onnxruntime-devel = 1.11.0 +BuildRequires: vespa-onnxruntime-devel = 1.12.1 BuildRequires: vespa-openssl-devel >= 1.1.1o-1 %define _use_vespa_openssl 1 BuildRequires: vespa-protobuf-devel = 3.19.1 @@ -139,7 +139,7 @@ BuildRequires: vespa-openssl-devel >= 1.1.1o-1 BuildRequires: vespa-gtest = 1.11.0 %define _use_vespa_gtest 1 BuildRequires: vespa-lz4-devel >= 1.9.2-2 -BuildRequires: vespa-onnxruntime-devel = 1.11.0 +BuildRequires: vespa-onnxruntime-devel = 1.12.1 BuildRequires: vespa-protobuf-devel = 3.19.1 BuildRequires: vespa-libzstd-devel >= 1.4.5-2 %endif @@ -149,7 +149,7 @@ BuildRequires: maven BuildRequires: maven-openjdk17 BuildRequires: openssl-devel BuildRequires: vespa-lz4-devel >= 1.9.2-2 -BuildRequires: vespa-onnxruntime-devel = 1.11.0 +BuildRequires: vespa-onnxruntime-devel = 1.12.1 BuildRequires: vespa-libzstd-devel >= 1.4.5-2 BuildRequires: protobuf-devel %if 0%{?_centos_stream} @@ -169,7 +169,7 @@ BuildRequires: maven-openjdk17 %endif BuildRequires: openssl-devel BuildRequires: vespa-lz4-devel >= 1.9.2-2 -BuildRequires: vespa-onnxruntime-devel = 1.11.0 +BuildRequires: vespa-onnxruntime-devel = 1.12.1 BuildRequires: vespa-libzstd-devel >= 1.4.5-2 %if 0%{?fc34} BuildRequires: protobuf-devel @@ -476,7 +476,7 @@ Requires: llvm-libs >= 14.0.0 Requires: llvm-libs >= 14.0.0 %endif %endif -Requires: vespa-onnxruntime = 1.11.0 +Requires: vespa-onnxruntime = 1.12.1 %description libs diff --git a/document/src/vespa/document/datatype/datatype.cpp b/document/src/vespa/document/datatype/datatype.cpp index 3cc7034e336..7d53679bc28 100644 --- a/document/src/vespa/document/datatype/datatype.cpp +++ b/document/src/vespa/document/datatype/datatype.cpp @@ -155,7 +155,7 @@ DataType::buildFieldPath(FieldPath & path, vespalib::stringref remainFieldName) { if ( !remainFieldName.empty() ) { path.reserve(4); // Optimize for short paths - onBuildFieldPath(path,remainFieldName); + onBuildFieldPath(path, remainFieldName); } } diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java index 1b1a5493cc5..e349165b855 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java @@ -119,7 +119,7 @@ public class Flags { public static final UnboundBooleanFlag USE_THREE_PHASE_UPDATES = defineFeatureFlag( "use-three-phase-updates", false, - List.of("vekterli"), "2020-12-02", "2022-08-15", + List.of("vekterli"), "2020-12-02", "2022-10-01", "Whether to enable the use of three-phase updates when bucket replicas are out of sync.", "Takes effect at redeployment", ZONE_ID, APPLICATION_ID); @@ -245,7 +245,7 @@ public class Flags { public static final UnboundIntFlag MAX_ACTIVATION_INHIBITED_OUT_OF_SYNC_GROUPS = defineIntFlag( "max-activation-inhibited-out-of-sync-groups", 0, - List.of("vekterli"), "2021-02-19", "2022-08-15", + List.of("vekterli"), "2021-02-19", "2022-10-01", "Allows replicas in up to N content groups to not be activated " + "for query visibility if they are out of sync with a majority of other replicas", "Takes effect at redeployment", @@ -253,14 +253,14 @@ public class Flags { public static final UnboundIntFlag MAX_CONCURRENT_MERGES_PER_NODE = defineIntFlag( "max-concurrent-merges-per-node", 16, - List.of("balder", "vekterli"), "2021-06-06", "2022-08-15", + List.of("balder", "vekterli"), "2021-06-06", "2022-10-01", "Specifies max concurrent merges per content node.", "Takes effect at redeploy", ZONE_ID, APPLICATION_ID); public static final UnboundIntFlag MAX_MERGE_QUEUE_SIZE = defineIntFlag( "max-merge-queue-size", 100, - List.of("balder", "vekterli"), "2021-06-06", "2022-08-15", + List.of("balder", "vekterli"), "2021-06-06", "2022-10-01", "Specifies max size of merge queue.", "Takes effect at redeploy", ZONE_ID, APPLICATION_ID); @@ -339,7 +339,7 @@ public class Flags { public static final UnboundStringFlag MERGE_THROTTLING_POLICY = defineStringFlag( "merge-throttling-policy", "STATIC", - List.of("vekterli"), "2022-01-25", "2022-08-15", + List.of("vekterli"), "2022-01-25", "2022-10-01", "Sets the policy used for merge throttling on the content nodes. " + "Valid values: STATIC, DYNAMIC", "Takes effect at redeployment", @@ -347,7 +347,7 @@ public class Flags { public static final UnboundDoubleFlag PERSISTENCE_THROTTLING_WS_DECREMENT_FACTOR = defineDoubleFlag( "persistence-throttling-ws-decrement-factor", 1.2, - List.of("vekterli"), "2022-01-27", "2022-08-15", + List.of("vekterli"), "2022-01-27", "2022-10-01", "Sets the dynamic throttle policy window size decrement factor for persistence " + "async throttling. Only applies if DYNAMIC policy is used.", "Takes effect on redeployment", @@ -355,7 +355,7 @@ public class Flags { public static final UnboundDoubleFlag PERSISTENCE_THROTTLING_WS_BACKOFF = defineDoubleFlag( "persistence-throttling-ws-backoff", 0.95, - List.of("vekterli"), "2022-01-27", "2022-08-15", + List.of("vekterli"), "2022-01-27", "2022-10-01", "Sets the dynamic throttle policy window size backoff for persistence " + "async throttling. Only applies if DYNAMIC policy is used. Valid range [0, 1]", "Takes effect on redeployment", diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java index 3f6801eebe7..1ff76fd45ac 100644 --- a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java +++ b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java @@ -41,6 +41,6 @@ class CorsLogic { } private static boolean requestOriginMatchesAnyAllowed(String requestOrigin, Set<String> allowedUrls) { - return allowedUrls.stream().anyMatch(requestOrigin::startsWith) || allowedUrls.contains("*"); + return allowedUrls.stream().anyMatch(requestOrigin::equals) || allowedUrls.contains("*"); } } diff --git a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilterTest.java b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilterTest.java index b5b94d5a2c2..7ba050b7cc0 100644 --- a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilterTest.java +++ b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilterTest.java @@ -43,6 +43,14 @@ public class CorsPreflightRequestFilterTest { } @Test + void extended_request_origin_does_not_yield_allow_origin_header_in_response() { + final String ALLOWED_ORIGIN = "https://allowed.origin"; + final String EXTENDED_ORIGIN = "https://allowed.origin.as.subdomain.com"; + HeaderFields headers = doFilterRequest(newRequestFilter(ALLOWED_ORIGIN), EXTENDED_ORIGIN); + assertNull(headers.getFirst(ALLOW_ORIGIN_HEADER)); + } + + @Test void allowed_wildcard_origin_yields_origin_header_in_response() { final String ALLOWED_ORIGIN = "http://allowed.origin"; HeaderFields headers = doFilterRequest(newRequestFilter("*"), ALLOWED_ORIGIN); diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/node/NodeMetricGatherer.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/node/NodeMetricGatherer.java index e18ea374fe1..148f48136f4 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/node/NodeMetricGatherer.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/node/NodeMetricGatherer.java @@ -4,6 +4,7 @@ package ai.vespa.metricsproxy.node; import ai.vespa.metricsproxy.core.MetricsManager; import ai.vespa.metricsproxy.metric.dimensions.ApplicationDimensions; import ai.vespa.metricsproxy.metric.dimensions.NodeDimensions; +import ai.vespa.metricsproxy.metric.model.ConsumerId; import ai.vespa.metricsproxy.metric.model.MetricId; import ai.vespa.metricsproxy.metric.model.MetricsPacket; import ai.vespa.metricsproxy.metric.model.ServiceId; @@ -18,6 +19,7 @@ import com.yahoo.container.jdisc.state.HostLifeGatherer; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import static ai.vespa.metricsproxy.node.ServiceHealthGatherer.gatherServiceHealthMetrics; @@ -78,6 +80,7 @@ public class NodeMetricGatherer { builder.putMetric(MetricId.toMetricId(key), metrics.get(key).asLong()); } } + builder.addConsumers(Set.of(ConsumerId.toConsumerId("Vespa"))); builders.add(builder); } diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/node/NodeMetricGathererTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/node/NodeMetricGathererTest.java index c693e9690e8..0de3526b40d 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/node/NodeMetricGathererTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/node/NodeMetricGathererTest.java @@ -1,6 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package ai.vespa.metricsproxy.node; +import ai.vespa.metricsproxy.metric.model.ConsumerId; import ai.vespa.metricsproxy.metric.model.MetricId; import ai.vespa.metricsproxy.metric.model.MetricsPacket; import com.fasterxml.jackson.databind.JsonNode; @@ -10,6 +11,7 @@ import org.junit.Test; import java.util.ArrayList; import java.util.List; +import java.util.Set; import static org.junit.Assert.assertEquals; @@ -33,6 +35,7 @@ public class NodeMetricGathererTest { assertEquals(123, packet.timestamp); assertEquals(12l, packet.metrics().get(MetricId.toMetricId("uptime"))); assertEquals(1l, packet.metrics().get(MetricId.toMetricId("alive"))); + assertEquals(Set.of(ConsumerId.toConsumerId("Vespa")), packet.consumers()); } private JsonNode generateHostLifePacket() { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/AutoscalingStatus.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/AutoscalingStatus.java index 71a6d661594..ea15b6a42cb 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/AutoscalingStatus.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/AutoscalingStatus.java @@ -46,9 +46,8 @@ public class AutoscalingStatus { @Override public boolean equals(Object o) { if (o == this) return true; - if ( ! ( o instanceof AutoscalingStatus)) return false; + if ( ! ( o instanceof AutoscalingStatus other)) return false; - AutoscalingStatus other = (AutoscalingStatus)o; if ( other.status != this.status ) return false; if ( ! other.description.equals(this.description) ) return false; return true; diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java index 7a02fa9eb7e..4d50250e61a 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java @@ -2,7 +2,6 @@ package com.yahoo.vespa.hosted.provision.autoscale; import com.yahoo.config.provision.ClusterResources; -import com.yahoo.config.provision.NodeResources; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeList; import com.yahoo.vespa.hosted.provision.NodeRepository; @@ -12,7 +11,6 @@ import com.yahoo.vespa.hosted.provision.applications.AutoscalingStatus.Status; import com.yahoo.vespa.hosted.provision.applications.Cluster; import java.time.Duration; -import java.time.Instant; import java.util.Objects; import java.util.Optional; @@ -70,24 +68,6 @@ public class Autoscaler { if ( ! clusterIsStable(clusterNodes, nodeRepository)) return Advice.none(Status.waiting, "Cluster change in progress"); - if (scaledIn(clusterModel.scalingDuration(), cluster)) - return Advice.dontScale(Status.waiting, - "Won't autoscale now: Less than " + clusterModel.scalingDuration() + - " since last resource change"); - - if (clusterModel.nodeTimeseries().measurementsPerNode() < minimumMeasurementsPerNode(clusterModel.scalingDuration())) - return Advice.none(Status.waiting, - "Collecting more data before making new scaling decisions: Need to measure for " + - clusterModel.scalingDuration() + " since the last resource change completed, " + - clusterModel.nodeTimeseries().measurementsPerNode() + " measurements per node found," + - " need at least " + minimumMeasurementsPerNode(clusterModel.scalingDuration())); - - if (clusterModel.nodeTimeseries().nodesMeasured() != clusterNodes.size()) - return Advice.none(Status.waiting, - "Collecting more data before making new scaling decisions:" + - " Have measurements from " + clusterModel.nodeTimeseries().nodesMeasured() + - " nodes, but require from " + clusterNodes.size()); - var currentAllocation = new AllocatableClusterResources(clusterNodes.asList(), nodeRepository); Optional<AllocatableClusterResources> bestAllocation = allocationOptimizer.findBestAllocation(clusterModel.loadAdjustment(), currentAllocation, clusterModel, limits); @@ -101,11 +81,6 @@ public class Autoscaler { return Advice.dontScale(Status.ideal, "Cluster is ideally scaled"); } - if (isDownscaling(bestAllocation.get(), currentAllocation) && scaledIn(clusterModel.scalingDuration().multipliedBy(3), cluster)) - return Advice.dontScale(Status.waiting, - "Waiting " + clusterModel.scalingDuration().multipliedBy(3) + - " since the last change before reducing resources"); - return Advice.scaleTo(bestAllocation.get().advertisedResources()); } @@ -134,7 +109,7 @@ public class Autoscaler { return ! similar(from.cost(), to.cost(), costDifferenceWorthReallocation); } - private static boolean meaningfulIncrease(double from, double to) { + public static boolean meaningfulIncrease(double from, double to) { return from < to && ! similar(from, to, resourceDifferenceWorthReallocation); } @@ -142,33 +117,10 @@ public class Autoscaler { return Math.abs(r1 - r2) / (( r1 + r2) / 2) < threshold; } - /** Returns true if this reduces total resources in any dimension */ - private boolean isDownscaling(AllocatableClusterResources target, AllocatableClusterResources current) { - NodeResources targetTotal = target.advertisedResources().totalResources(); - NodeResources currentTotal = current.advertisedResources().totalResources(); - return ! targetTotal.justNumbers().satisfies(currentTotal.justNumbers()); - } - - private boolean scaledIn(Duration delay, Cluster cluster) { - return cluster.lastScalingEvent().map(event -> event.at()).orElse(Instant.MIN) - .isAfter(nodeRepository.clock().instant().minus(delay)); - } - static Duration maxScalingWindow() { return Duration.ofHours(48); } - /** Returns the minimum measurements per node (average) we require to give autoscaling advice.*/ - private int minimumMeasurementsPerNode(Duration scalingWindow) { - // Measurements are ideally taken every minute, but no guarantees - // (network, nodes may be down, collecting is single threaded and may take longer than 1 minute to complete). - // Since the metric window is 5 minutes, we won't really improve from measuring more often. - long minimumMeasurements = scalingWindow.toMinutes() / 5; - minimumMeasurements = Math.round(0.8 * minimumMeasurements); // Allow 20% metrics collection blackout - if (minimumMeasurements < 1) minimumMeasurements = 1; - return (int)minimumMeasurements; - } - public static class Advice { private final boolean present; diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java index ae18e7ffb91..e6f2a1216f3 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java @@ -9,6 +9,7 @@ import com.yahoo.vespa.hosted.provision.applications.ScalingEvent; import java.time.Clock; import java.time.Duration; +import java.time.Instant; import java.util.Optional; import java.util.OptionalDouble; import java.util.logging.Level; @@ -93,16 +94,25 @@ public class ClusterModel { /** Returns the relative load adjustment that should be made to this cluster given available measurements. */ public Load loadAdjustment() { - if (nodeTimeseries().measurementsPerNode() == 0) return Load.one(); // No info, no change - /* - // Should we scale up? - Load relativePeak = nodeTimeseries().peakLoad().divide(idealLoad()); - if (relativePeak.any(v -> v > 1)) - return relativePeak.max(Load.one()); // Don't downscale any dimension if we upscale - - // Should we scale down? - */ - return averageLoad().divide(idealLoad()); + if (nodeTimeseries().isEmpty()) return Load.one(); + + Load adjustment = peakLoad().divide(idealLoad()); + if (! safeToScaleDown()) + adjustment = adjustment.map(v -> v < 1 ? 1 : v); + return adjustment; + } + + /** Are we in a position to make decisions to scale down at this point? */ + private boolean safeToScaleDown() { + if (hasScaledIn(scalingDuration().multipliedBy(3))) return false; + if (nodeTimeseries().measurementsPerNode() < 4) return false; + if (nodeTimeseries().nodesMeasured() != nodeCount()) return false; + return true; + } + + private boolean hasScaledIn(Duration period) { + return cluster.lastScalingEvent().map(event -> event.at()).orElse(Instant.MIN) + .isAfter(clock.instant().minus(period)); } /** Returns the predicted duration of a rescaling of this cluster */ @@ -127,11 +137,14 @@ public class ClusterModel { return queryFractionOfMax = clusterTimeseries().queryFractionOfMax(scalingDuration(), clock); } - /** Returns average of the last load reading from each node. */ + /** Returns the average of the last load measurement from each node. */ public Load currentLoad() { return nodeTimeseries().currentLoad(); } - /** Returns average load during the last {@link #scalingDuration()} */ - public Load averageLoad() { return nodeTimeseries().averageLoad(clock.instant().minus(scalingDuration())); } + /** Returns the average of all load measurements from all nodes*/ + public Load averageLoad() { return nodeTimeseries().averageLoad(); } + + /** Returns the average of the peak load measurement in each dimension, from each node. */ + public Load peakLoad() { return nodeTimeseries().peakLoad(); } /** The number of nodes this cluster has, or will have if not deployed yet. */ // TODO: Make this the deployed, not current count diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterNodesTimeseries.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterNodesTimeseries.java index ab5be045dd4..2eb57dcdd87 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterNodesTimeseries.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterNodesTimeseries.java @@ -48,6 +48,10 @@ public class ClusterNodesTimeseries { this.timeseries = timeseries; } + public boolean isEmpty() { + return measurementsPerNode() == 0; + } + /** Returns the average number of measurements per node */ public int measurementsPerNode() { if (clusterNodes.size() == 0) return 0; @@ -59,12 +63,11 @@ public class ClusterNodesTimeseries { public int nodesMeasured() { return timeseries.size(); } /** Returns the average load after the given instant */ - public Load averageLoad(Instant start) { + public Load averageLoad() { Load total = Load.zero(); int count = 0; for (var nodeTimeseries : timeseries) { for (var snapshot : nodeTimeseries.asList()) { - if (snapshot.at().isBefore(start)) continue; total = total.add(snapshot.load()); count++; } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Load.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Load.java index 88c7e70cd35..6ab5ff731d3 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Load.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Load.java @@ -54,11 +54,6 @@ public class Load { return new Load(divide(cpu, resources.vcpu()), divide(memory, resources.memoryGb()), divide(disk, resources.diskGb())); } - /** Returns the load having the max value of this and the given load in each dimension. */ - public Load max(Load other) { - return join(other, (a, b) -> Math.max(a, b)); - } - /** Returns the load where the given function is applied to each dimension of this. */ public Load map(DoubleUnaryOperator f) { return new Load(f.applyAsDouble(cpu), diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationSerializer.java index 1c10de8498a..3615b9afa97 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationSerializer.java @@ -90,16 +90,22 @@ public class ApplicationSerializer { Load idealLoad = clusterModel.idealLoad(); Load averageLoad = clusterModel.averageLoad(); Load currentLoad = clusterModel.currentLoad(); + Load peakLoad = clusterModel.peakLoad(); utilizationObject.setDouble("cpu", averageLoad.cpu()); utilizationObject.setDouble("idealCpu", idealLoad.cpu()); utilizationObject.setDouble("currentCpu", currentLoad.cpu()); + utilizationObject.setDouble("peakCpu", peakLoad.cpu()); + utilizationObject.setDouble("memory", averageLoad.memory()); utilizationObject.setDouble("idealMemory", idealLoad.memory()); utilizationObject.setDouble("currentMemory", currentLoad.memory()); + utilizationObject.setDouble("peakMemory", peakLoad.memory()); + utilizationObject.setDouble("disk", averageLoad.disk()); utilizationObject.setDouble("idealDisk", idealLoad.disk()); utilizationObject.setDouble("currentDisk", currentLoad.disk()); + utilizationObject.setDouble("peakDisk", peakLoad.disk()); } private static void scalingEventsToSlime(List<ScalingEvent> scalingEvents, Cursor scalingEventsArray) { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java index 28f37546eb6..e4389e84255 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java @@ -19,7 +19,6 @@ import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.Nodelike; import com.yahoo.vespa.hosted.provision.provisioning.CapacityPolicies; import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator; -import org.junit.Ignore; import org.junit.Test; import java.time.Duration; @@ -37,16 +36,9 @@ public class AutoscalingTest { public void test_autoscaling_single_content_group() { var fixture = AutoscalingTester.fixture().build(); - fixture.tester().clock().advance(Duration.ofDays(1)); - assertTrue("No measurements -> No change", fixture.autoscale().isEmpty()); - - fixture.loader().applyCpuLoad(0.7f, 59); - assertTrue("Too few measurements -> No change", fixture.autoscale().isEmpty()); - - fixture.tester().clock().advance(Duration.ofDays(1)); - fixture.loader().applyCpuLoad(0.7f, 120); + fixture.loader().applyCpuLoad(0.7f, 10); ClusterResources scaledResources = fixture.tester().assertResources("Scaling up since resource usage is too high", - 9, 1, 2.8, 5.0, 50.0, + 8, 1, 6, 5.7, 57.1, fixture.autoscale()); fixture.deploy(Capacity.from(scaledResources)); @@ -54,17 +46,16 @@ public class AutoscalingTest { fixture.deactivateRetired(Capacity.from(scaledResources)); - fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyCpuLoad(0.8f, 3); - assertTrue("Load change is large, but insufficient measurements for new config -> No change", - fixture.autoscale().isEmpty()); - - fixture.loader().applyCpuLoad(0.19f, 100); + fixture.loader().applyCpuLoad(0.19f, 10); assertEquals("Load change is small -> No change", Optional.empty(), fixture.autoscale().target()); - fixture.loader().applyCpuLoad(0.1f, 120); + fixture.loader().applyCpuLoad(0.1f, 10); + assertEquals("Too little time passed for downscaling -> No change", Optional.empty(), fixture.autoscale().target()); + + fixture.tester().clock().advance(Duration.ofDays(2)); + fixture.loader().applyCpuLoad(0.1f, 10); fixture.tester().assertResources("Scaling cpu down since usage has gone down significantly", - 9, 1, 1.0, 5.0, 50.0, + 9, 1, 1.3, 4.4, 43.7, fixture.autoscale()); } @@ -72,18 +63,48 @@ public class AutoscalingTest { @Test public void test_no_autoscaling_with_no_measurements() { var fixture = AutoscalingTester.fixture().build(); - System.out.println(fixture.autoscale()); assertTrue(fixture.autoscale().target().isEmpty()); } /** Using too many resources for a short period is proof we should scale up regardless of the time that takes. */ @Test - @Ignore // TODO public void test_autoscaling_up_is_fast() { var fixture = AutoscalingTester.fixture().build(); - fixture.loader().applyLoad(1.0, 1.0, 1.0, 1); + fixture.loader().applyLoad(new Load(1.0, 1.0, 1.0), 3); fixture.tester().assertResources("Scaling up since resource usage is too high", - 10, 1, 9.4, 8.5, 92.6, + 10, 1, 7.2, 8.5, 92.6, + fixture.autoscale()); + } + + /** When scaling up, disregard underutilized dimensions (memory here) */ + @Test + public void test_only_autoscaling_up_quickly() { + var fixture = AutoscalingTester.fixture().build(); + fixture.loader().applyLoad(new Load(1.0, 0.1, 1.0), 10); + fixture.tester().assertResources("Scaling up (only) since resource usage is too high", + 10, 1, 8.6, 4.4, 92.6, + fixture.autoscale()); + } + + /** When ok to scale down, scale in both directions simultaneously (compare to test_only_autoscaling_up_quickly) */ + @Test + public void test_scale_in_both_directions_when_ok_to_scale_down() { + var fixture = AutoscalingTester.fixture().build(); + fixture.tester.clock().advance(Duration.ofDays(2)); + fixture.loader().applyLoad(new Load(1.0, 0.1, 1.0), 10); + fixture.tester().assertResources("Scaling up (only) since resource usage is too high", + 10, 1, 8.6, 4.0, 92.6, + fixture.autoscale()); + } + + @Test + public void test_autoscaling_uses_peak() { + var fixture = AutoscalingTester.fixture().build(); + fixture.loader().applyCpuLoad(0.01, 100); + fixture.loader().applyCpuLoad(0.70, 1); + fixture.loader().applyCpuLoad(0.01, 100); + fixture.tester().assertResources("Scaling up since peak resource usage is too high", + 8, 1, 6.5, 5.7, 57.1, fixture.autoscale()); } @@ -91,14 +112,16 @@ public class AutoscalingTest { @Test public void test_autoscaling_single_container_group() { var fixture = AutoscalingTester.fixture().clusterType(ClusterSpec.Type.container).build(); + fixture.loader().applyCpuLoad(0.25f, 120); - ClusterResources scaledResources = fixture.tester().assertResources("Scaling up since cpu usage is too high", - 5, 1, 3.8, 8.0, 50.5, + ClusterResources scaledResources = fixture.tester().assertResources("Scaling cpu up", + 5, 1, 3.8, 8.0, 80.0, fixture.autoscale()); fixture.deploy(Capacity.from(scaledResources)); + fixture.deactivateRetired(Capacity.from(scaledResources)); fixture.loader().applyCpuLoad(0.1f, 120); fixture.tester().assertResources("Scaling down since cpu usage has gone down", - 4, 1, 2.5, 6.4, 25.5, + 4, 1, 2.5, 6.4, 64.0, fixture.autoscale()); } @@ -124,7 +147,7 @@ public class AutoscalingTest { new NodeResources(100, 1000, 1000, 1, DiskSpeed.any)); var capacity = Capacity.from(min, max); ClusterResources scaledResources = fixture.tester().assertResources("Scaling up", - 14, 1, 1.4, 30.8, 30.8, + 13, 1, 1.5, 26.7, 26.7, fixture.autoscale(capacity)); assertEquals("Disk speed from new capacity is used", DiskSpeed.any, scaledResources.nodeResources().diskSpeed()); @@ -165,7 +188,7 @@ public class AutoscalingTest { .capacity(Capacity.from(min, max)).build(); fixture.tester().clock().advance(Duration.ofDays(1)); - fixture.loader().applyLoad(0.25, 0.95, 0.95, 120); + fixture.loader().applyLoad(new Load(0.25, 0.95, 0.95), 120); fixture.tester().assertResources("Scaling up to limit since resource usage is too high", 6, 1, 2.4, 78.0, 79.0, fixture.autoscale()); @@ -179,7 +202,7 @@ public class AutoscalingTest { // deploy fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyLoad(0.05f, 0.05f, 0.05f, 120); + fixture.loader().applyLoad(new Load(0.05f, 0.05f, 0.05f), 120); fixture.tester().assertResources("Scaling down to limit since resource usage is low", 4, 1, 1.8, 7.4, 13.9, fixture.autoscale()); @@ -201,7 +224,7 @@ public class AutoscalingTest { 2, 1, defaultResources, fixture.nodes().toResources()); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyLoad(0.25, 0.95, 0.95, 120); + fixture.loader().applyLoad(new Load(0.25, 0.95, 0.95), 120); fixture.tester().assertResources("Scaling up", 5, 1, defaultResources.vcpu(), defaultResources.memoryGb(), defaultResources.diskGb(), @@ -218,9 +241,9 @@ public class AutoscalingTest { .capacity(Capacity.from(min, max)) .build(); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyCpuLoad(0.3, 240); - fixture.tester().assertResources("Scaling up", - 6, 6, 3.8, 8.0, 10.0, + fixture.loader().applyCpuLoad(0.4, 240); + fixture.tester().assertResources("Scaling cpu up", + 6, 6, 5.0, 8.0, 10.0, fixture.autoscale()); } @@ -249,7 +272,7 @@ public class AutoscalingTest { .build(); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyLoad(0.01, 0.01, 0.01, 120); + fixture.loader().applyLoad(new Load(0.01, 0.01, 0.01), 120); Autoscaler.Advice suggestion = fixture.suggest(); fixture.tester().assertResources("Choosing the remote disk flavor as it has less disk", 2, 1, 3.0, 100.0, 10.0, @@ -272,7 +295,7 @@ public class AutoscalingTest { .build(); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyLoad(0.01, 0.01, 0.01, 120); + fixture.loader().applyLoad(new Load(0.01, 0.01, 0.01), 120); Autoscaler.Advice suggestion = fixture.suggest(); fixture.tester().assertResources("Always prefers local disk for content", 2, 1, 3.0, 100.0, 75.0, @@ -288,7 +311,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(1.0, 120); fixture.tester().assertResources("Suggesting above capacity limit", - 8, 1, 9.3, 5.7, 57.1, + 8, 1, 9.3, 4.6, 45.7, fixture.tester().suggest(fixture.applicationId, fixture.clusterSpec.id(), min, min)); } @@ -296,18 +319,18 @@ public class AutoscalingTest { public void not_using_out_of_service_measurements() { var fixture = AutoscalingTester.fixture().build(); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyLoad(0.9, 0.6, 0.7, 1, false, true, 120); + fixture.loader().applyLoad(new Load(0.9, 0.6, 0.7), 1, false, true, 120); assertTrue("Not scaling up since nodes were measured while cluster was out of service", - fixture.autoscale().isEmpty()); + fixture.autoscale().target().isEmpty()); } @Test public void not_using_unstable_measurements() { var fixture = AutoscalingTester.fixture().build(); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyLoad(0.9, 0.6, 0.7, 1, true, false, 120); - assertTrue("Not scaling up since nodes were measured while cluster was out of service", - fixture.autoscale().isEmpty()); + fixture.loader().applyLoad(new Load(0.9, 0.6, 0.7), 1, true, false, 120); + assertTrue("Not scaling up since nodes were measured while cluster was unstable", + fixture.autoscale().target().isEmpty()); } @Test @@ -321,7 +344,7 @@ public class AutoscalingTest { .build(); fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(0.9, 120); - fixture.tester().assertResources("Scaling the number of groups, but nothing requires us to stay with 1 node per group", + fixture.tester().assertResources("Scaling up to 2 nodes, scaling memory and disk down at the same time", 10, 5, 7.7, 40.0, 40.0, fixture.autoscale()); } @@ -339,7 +362,7 @@ public class AutoscalingTest { Duration timePassed = fixture.loader().addCpuMeasurements(0.25, 120); fixture.tester().clock().advance(timePassed.negated()); fixture.loader().addLoadMeasurements(10, t -> t == 0 ? 20.0 : 10.0, t -> 1.0); - fixture.tester().assertResources("Scaling up since resource usage is too high, changing to 1 group is cheaper", + fixture.tester().assertResources("Scaling up cpu, others down, changing to 1 group is cheaper", 10, 1, 2.3, 27.8, 27.8, fixture.autoscale()); } @@ -375,7 +398,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(1)); fixture.loader().applyMemLoad(1.0, 1000); fixture.tester().assertResources("Increase group size to reduce memory load", - 8, 2, 6.5, 96.2, 62.5, + 8, 2, 4.5, 96.2, 62.5, fixture.autoscale()); } @@ -389,21 +412,21 @@ public class AutoscalingTest { .capacity(Capacity.from(min, max)) .build(); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyMemLoad(0.02, 120); + fixture.loader().applyLoad(new Load(0.16, 0.02, 0.5), 120); fixture.tester().assertResources("Scaling down", - 6, 1, 3.1, 4.0, 100.0, + 6, 1, 3.0, 4.0, 100.0, fixture.autoscale()); } @Test public void scaling_down_only_after_delay() { var fixture = AutoscalingTester.fixture().build(); - fixture.loader().applyMemLoad(0.02, 120); + fixture.loader().applyCpuLoad(0.02, 120); assertTrue("Too soon after initial deployment", fixture.autoscale().target().isEmpty()); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyMemLoad(0.02, 120); + fixture.loader().applyCpuLoad(0.02, 120); fixture.tester().assertResources("Scaling down since enough time has passed", - 6, 1, 1.2, 4.0, 80.0, + 5, 1, 1.0, 8.0, 80.0, fixture.autoscale()); } @@ -413,7 +436,7 @@ public class AutoscalingTest { var fixture = AutoscalingTester.fixture() .resourceCalculator(new OnlySubtractingWhenForecastingCalculator(0)) .build(); - fixture.loader().applyLoad(1.0, 1.0, 0.7, 1000); + fixture.loader().applyLoad(new Load(1.0, 1.0, 0.7), 1000); fixture.tester().assertResources("Scaling up", 9, 1, 5.0, 9.6, 72.9, fixture.autoscale()); @@ -423,7 +446,7 @@ public class AutoscalingTest { var fixture = AutoscalingTester.fixture() .resourceCalculator(new OnlySubtractingWhenForecastingCalculator(3)) .build(); - fixture.loader().applyLoad(1.0, 1.0, 0.7, 1000); + fixture.loader().applyLoad(new Load(1.0, 1.0, 0.7), 1000); fixture.tester().assertResources("With 3Gb memory tax, we scale up memory more", 7, 1, 6.4, 15.8, 97.2, fixture.autoscale()); @@ -448,7 +471,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyMemLoad(0.9, 120); var scaledResources = fixture.tester().assertResources("Scaling up since resource usage is too high.", - 8, 1, 3, 80, 57.1, + 8, 1, 3, 80, 45.7, fixture.autoscale()); fixture.deploy(Capacity.from(scaledResources)); fixture.deactivateRetired(Capacity.from(scaledResources)); @@ -456,7 +479,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyMemLoad(0.3, 1000); fixture.tester().assertResources("Scaling down since resource usage has gone down", - 5, 1, 3, 80, 100.0, + 5, 1, 3, 80, 70.0, fixture.autoscale()); } @@ -467,22 +490,25 @@ public class AutoscalingTest { var fixture = AutoscalingTester.fixture() .capacity(Capacity.from(min, max)) .build(); + fixture.tester.clock().advance(Duration.ofDays(1)); fixture.loader().applyCpuLoad(0.25, 120); - // (no read share stored) fixture.tester().assertResources("Advice to scale up since we set aside for bcp by default", 7, 1, 3, 100, 100, fixture.autoscale()); + fixture.loader().applyCpuLoad(0.25, 120); fixture.storeReadShare(0.25, 0.5); fixture.tester().assertResources("Half of global share is the same as the default assumption used above", 7, 1, 3, 100, 100, fixture.autoscale()); + fixture.tester.clock().advance(Duration.ofDays(1)); + fixture.loader().applyCpuLoad(0.25, 120); fixture.storeReadShare(0.5, 0.5); fixture.tester().assertResources("Advice to scale down since we don't need room for bcp", - 6, 1, 3, 100, 100, + 5, 1, 3, 100, 100, fixture.autoscale()); } @@ -496,7 +522,7 @@ public class AutoscalingTest { fixture.loader().addCpuMeasurements(0.25, 200); fixture.tester().assertResources("Scale up since we assume we need 2x cpu for growth when no data scaling time data", - 9, 1, 2.1, 5, 50, + 9, 1, 2.1, 4, 40, fixture.autoscale()); fixture.setScalingDuration(Duration.ofMinutes(5)); @@ -505,7 +531,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.25, 200); fixture.tester().assertResources("Scale down since observed growth is slower than scaling time", - 9, 1, 1.8, 5, 50, + 9, 1, 1.8, 4, 40, fixture.autoscale()); fixture.setScalingDuration(Duration.ofMinutes(60)); @@ -516,7 +542,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.25, 200); fixture.tester().assertResources("Scale up since observed growth is faster than scaling time", - 9, 1, 2.1, 5, 50, + 9, 1, 2.1, 4, 40, fixture.autoscale()); } @@ -534,7 +560,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.4, 200); fixture.tester.assertResources("Query and write load is equal -> scale up somewhat", - 9, 1, 2.4, 5, 50, + 9, 1, 2.4, 4, 40, fixture.autoscale()); fixture.tester().clock().advance(Duration.ofDays(2)); @@ -543,7 +569,7 @@ public class AutoscalingTest { fixture.loader().addCpuMeasurements(0.4, 200); // TODO: Ackhually, we scale down here - why? fixture.tester().assertResources("Query load is 4x write load -> scale up more", - 9, 1, 2.1, 5, 50, + 9, 1, 2.1, 4, 40, fixture.autoscale()); fixture.tester().clock().advance(Duration.ofDays(2)); @@ -551,7 +577,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.4, 200); fixture.tester().assertResources("Write load is 10x query load -> scale down", - 9, 1, 1.1, 5, 50, + 9, 1, 1.1, 4, 40, fixture.autoscale()); fixture.tester().clock().advance(Duration.ofDays(2)); @@ -559,7 +585,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.4, 200); fixture.tester().assertResources("Query only -> largest possible", - 8, 1, 4.9, 5.7, 57.1, + 8, 1, 4.6, 4.6, 45.7, fixture.autoscale()); fixture.tester().clock().advance(Duration.ofDays(2)); @@ -567,7 +593,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.4, 200); fixture.tester().assertResources("Write only -> smallest possible", - 6, 1, 1.0, 8, 80, + 6, 1, 1.0, 6.4, 64, fixture.autoscale()); } @@ -577,7 +603,7 @@ public class AutoscalingTest { .zone(new Zone(Environment.dev, RegionName.from("us-east"))) .build(); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyLoad(1.0, 1.0, 1.0, 200); + fixture.loader().applyLoad(new Load(1.0, 1.0, 1.0), 200); assertTrue("Not attempting to scale up because policies dictate we'll only get one node", fixture.autoscale().target().isEmpty()); } @@ -598,7 +624,7 @@ public class AutoscalingTest { .zone(new Zone(Environment.dev, RegionName.from("us-east"))) .build(); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyLoad(1.0, 1.0, 1.0, 200); + fixture.loader().applyLoad(new Load(1.0, 1.0, 1.0), 200); fixture.tester().assertResources("We scale even in dev because resources are required", 3, 1, 1.0, 7.7, 83.3, fixture.autoscale()); @@ -617,7 +643,7 @@ public class AutoscalingTest { .zone(new Zone(Environment.dev, RegionName.from("us-east"))) .build(); fixture.tester().clock().advance(Duration.ofDays(2)); - fixture.loader().applyLoad(1.0, 1.0, 1.0, 200); + fixture.loader().applyLoad(new Load(1.0, 1.0, 1.0), 200); fixture.tester().assertResources("We scale even in dev because resources are required", 3, 1, 1.5, 8, 50, fixture.autoscale()); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java index c0203f5f202..7aaaceb0fdd 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java @@ -19,6 +19,7 @@ import java.util.function.IntFunction; public class Loader { private final Fixture fixture; + private final Duration samplingInterval = Duration.ofSeconds(150L); public Loader(Fixture fixture) { this.fixture = fixture; @@ -33,16 +34,14 @@ public class Loader { * @param count the number of measurements */ public Duration addCpuMeasurements(double value, int count) { - var idealLoad = fixture.clusterModel().idealLoad(); // TODO: Use this + var idealLoad = fixture.clusterModel().idealLoad(); NodeList nodes = fixture.nodes(); float oneExtraNodeFactor = (float)(nodes.size() - 1.0) / (nodes.size()); + Load load = new Load(value, idealLoad.memory(), idealLoad.disk()).multiply(oneExtraNodeFactor); Instant initialTime = fixture.tester().clock().instant(); for (int i = 0; i < count; i++) { - fixture.tester().clock().advance(Duration.ofSeconds(150)); + fixture.tester().clock().advance(samplingInterval); for (Node node : nodes) { - Load load = new Load(value, - ClusterModel.idealMemoryLoad, - ClusterModel.idealContentDiskLoad).multiply(oneExtraNodeFactor); fixture.tester().nodeMetricsDb().addNodeMetrics(List.of(new Pair<>(node.hostname(), new NodeMetricSnapshot(fixture.tester().clock().instant(), load, @@ -63,23 +62,21 @@ public class Loader { Map.of(fixture.clusterId(), new ClusterMetricSnapshot(fixture.tester().clock().instant(), queryRate.apply(i), writeRate.apply(i)))); - fixture.tester().clock().advance(Duration.ofMinutes(5)); + fixture.tester().clock().advance(samplingInterval); } return Duration.between(initialTime, fixture.tester().clock().instant()); } public void applyCpuLoad(double cpuLoad, int measurements) { - Duration samplingInterval = Duration.ofSeconds(150L); // in addCpuMeasurements addCpuMeasurements((float)cpuLoad, measurements); fixture.tester().clock().advance(samplingInterval.negated().multipliedBy(measurements)); - addQueryRateMeasurements(measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only + addQueryRateMeasurements(measurements, t -> t == 0 ? 20.0 : 10.0); // Query traffic only } public void applyMemLoad(double memLoad, int measurements) { - Duration samplingInterval = Duration.ofSeconds(150L); // in addMemMeasurements addMemMeasurements(memLoad, measurements); fixture.tester().clock().advance(samplingInterval.negated().multipliedBy(measurements)); - addQueryRateMeasurements(measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only + addQueryRateMeasurements(measurements, t -> t == 0 ? 20.0 : 10.0); // Query traffic only } /** @@ -89,15 +86,13 @@ public class Loader { * wanting to see the ideal load with one node missing.) */ public void addMemMeasurements(double value, int count) { - var idealLoad = fixture.clusterModel().idealLoad(); // TODO: Use this + var idealLoad = fixture.clusterModel().idealLoad(); NodeList nodes = fixture.nodes(); float oneExtraNodeFactor = (float)(nodes.size() - 1.0) / (nodes.size()); + Load load = new Load(idealLoad.cpu(), value, idealLoad.disk()).multiply(oneExtraNodeFactor); for (int i = 0; i < count; i++) { - fixture.tester().clock().advance(Duration.ofMinutes(1)); + fixture.tester().clock().advance(samplingInterval); for (Node node : nodes) { - Load load = new Load(0.2, - value, - ClusterModel.idealContentDiskLoad).multiply(oneExtraNodeFactor); fixture.tester().nodeMetricsDb().addNodeMetrics(List.of(new Pair<>(node.hostname(), new NodeMetricSnapshot(fixture.tester().clock().instant(), load, @@ -109,19 +104,18 @@ public class Loader { } } - public Duration addMeasurements(double cpu, double memory, double disk, int count) { - return addMeasurements(cpu, memory, disk, 0, true, true, count); + public Duration addMeasurements(Load load, int count) { + return addMeasurements(load, 0, true, true, count); } - public Duration addMeasurements(double cpu, double memory, double disk, int generation, boolean inService, boolean stable, - int count) { + public Duration addMeasurements(Load load, int generation, boolean inService, boolean stable, int count) { Instant initialTime = fixture.tester().clock().instant(); for (int i = 0; i < count; i++) { - fixture.tester().clock().advance(Duration.ofMinutes(1)); + fixture.tester().clock().advance(samplingInterval); for (Node node : fixture.nodes()) { fixture.tester().nodeMetricsDb().addNodeMetrics(List.of(new Pair<>(node.hostname(), new NodeMetricSnapshot(fixture.tester().clock().instant(), - new Load(cpu, memory, disk), + load, generation, inService, stable, @@ -131,21 +125,19 @@ public class Loader { return Duration.between(initialTime, fixture.tester().clock().instant()); } - public void applyLoad(double cpuLoad, double memoryLoad, double diskLoad, int measurements) { - Duration samplingInterval = Duration.ofSeconds(150L); // in addCpuMeasurements - addMeasurements(cpuLoad, memoryLoad, diskLoad, measurements); + public void applyLoad(Load load, int measurements) { + addMeasurements(load, measurements); fixture.tester().clock().advance(samplingInterval.negated().multipliedBy(measurements)); - addQueryRateMeasurements(measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only + addQueryRateMeasurements(measurements, t -> t == 0 ? 20.0 : 10.0); // Query traffic only } - public void applyLoad(double cpuLoad, double memoryLoad, double diskLoad, int generation, boolean inService, boolean stable, int measurements) { - Duration samplingInterval = Duration.ofSeconds(150L); // in addCpuMeasurements - addMeasurements(cpuLoad, memoryLoad, diskLoad, generation, inService, stable, measurements); + public void applyLoad(Load load, int generation, boolean inService, boolean stable, int measurements) { + addMeasurements(load, generation, inService, stable, measurements); fixture.tester().clock().advance(samplingInterval.negated().multipliedBy(measurements)); - addQueryRateMeasurements(measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only + addQueryRateMeasurements(measurements, t -> t == 0 ? 20.0 : 10.0); // Query traffic only } - public Duration addQueryRateMeasurements(int measurements, Duration samplingInterval, IntFunction<Double> queryRate) { + public Duration addQueryRateMeasurements(int measurements, IntFunction<Double> queryRate) { Instant initialTime = fixture.tester().clock().instant(); for (int i = 0; i < measurements; i++) { fixture.tester().nodeMetricsDb().addClusterMetrics(fixture.applicationId(), diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java index cee80459176..f74ace5bd3b 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java @@ -152,8 +152,9 @@ public class AutoscalingMaintainerTest { // deploy tester.deploy(app1, cluster1, app1Capacity); - tester.addQueryRateMeasurements(app1, cluster1.id(), 12, t -> t == 0 ? 20.0 : 10.0); + int measurements = 5; + Duration samplePeriod = Duration.ofSeconds(150); for (int i = 0; i < 20; i++) { // Record completion to keep scaling window at minimum tester.addMeasurements(0.1f, 0.1f, 0.1f, i, 1, app1); @@ -162,25 +163,20 @@ public class AutoscalingMaintainerTest { tester.clock().advance(Duration.ofDays(1)); if (i % 2 == 0) { // high load - for (int j = 0; j < 200; j++ ) { - tester.addMeasurements(0.99f, 0.99f, 0.99f, i, 1, app1); - tester.clock().advance(Duration.ofMinutes(1)); - } + tester.addMeasurements(0.99f, 0.99f, 0.99f, i, measurements, app1); } else { // low load - for (int j = 0; j < 200; j++ ) { - tester.addMeasurements(0.2f, 0.2f, 0.2f, i, 1, app1); - tester.clock().advance(Duration.ofMinutes(1)); - } + tester.addMeasurements(0.2f, 0.2f, 0.2f, i, measurements, app1); } - tester.addQueryRateMeasurements(app1, cluster1.id(), 2, t -> (t == 0 ? 20.0 : 10.0 )); + tester.clock().advance(samplePeriod.negated().multipliedBy(measurements)); + tester.addQueryRateMeasurements(app1, cluster1.id(), measurements, t -> (t == 0 ? 20.0 : 10.0 )); tester.maintainer().maintain(); } assertEquals(Cluster.maxScalingEvents, tester.cluster(app1, cluster1).scalingEvents().size()); assertEquals("The latest rescaling is the last event stored", tester.clock().instant(), - tester.cluster(app1, cluster1).scalingEvents().get(Cluster.maxScalingEvents - 1).at()); + tester.cluster(app1, cluster1).scalingEvents().get(Cluster.maxScalingEvents - 1).completion().get()); } @Test diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTester.java index e1a1a2af5fb..d921af9543e 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTester.java @@ -93,11 +93,10 @@ public class AutoscalingMaintainerTester { ClusterSpec.Id cluster, int measurements, IntFunction<Double> queryRate) { - Instant time = clock().instant(); for (int i = 0; i < measurements; i++) { nodeRepository().metricsDb().addClusterMetrics(application, - Map.of(cluster, new ClusterMetricSnapshot(time, queryRate.apply(i), 0.0))); - time = time.plus(Duration.ofMinutes(5)); + Map.of(cluster, new ClusterMetricSnapshot(clock().instant(), queryRate.apply(i), 0.0))); + clock().advance(Duration.ofSeconds(150)); } } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java index 6d007368db5..508168261df 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java @@ -97,7 +97,7 @@ public class ScalingSuggestionsMaintainerTest { var suggested = tester.nodeRepository().applications().get(app1).get().cluster(cluster1.id()).get().suggestedResources().get().resources(); tester.deploy(app1, cluster1, Capacity.from(suggested, suggested, false, true)); tester.clock().advance(Duration.ofDays(2)); - addMeasurements(0.2f, 0.7f, 0.6f, + addMeasurements(0.2f, 0.65f, 0.6f, 0, 500, app1, tester.nodeRepository()); maintainer.maintain(); assertEquals("Suggestion is to keep the current allocation", diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/application1.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/application1.json index 40719153b9e..9ae495a7396 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/application1.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/application1.json @@ -73,12 +73,15 @@ "cpu" : 0.0, "idealCpu": 0.1375, "currentCpu": 0.0, + "peakCpu": 0.0, "memory" : 0.0, "idealMemory": 0.65, "currentMemory": 0.0, + "peakMemory": 0.0, "disk" : 0.0, "idealDisk": 0.95, - "currentDisk": 0.0 + "currentDisk": 0.0, + "peakDisk": 0.0 }, "scalingEvents" : [ { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/application2.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/application2.json index 41aa4257c00..5babf5fc843 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/application2.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/application2.json @@ -47,12 +47,15 @@ "cpu" : 0.0, "idealCpu": 0.1394913986537023, "currentCpu": 0.0, + "peakCpu": 0.0, "memory" : 0.0, "idealMemory": 0.325, "currentMemory": 0.0, + "peakMemory": 0.0, "disk" : 0.0, "idealDisk": 0.3, - "currentDisk": 0.0 + "currentDisk": 0.0, + "peakDisk": 0.0 }, "scalingEvents" : [ { diff --git a/screwdriver/release-container-image.sh b/screwdriver/release-container-image.sh index 3ae2a7feb1e..def2f037b63 100755 --- a/screwdriver/release-container-image.sh +++ b/screwdriver/release-container-image.sh @@ -26,27 +26,35 @@ cd $BUILD_DIR git clone --depth 1 https://github.com/vespa-engine/docker-image cd docker-image -docker build --build-arg VESPA_VERSION=$VESPA_VERSION --file Dockerfile \ - --tag docker.io/vespaengine/vespa:$VESPA_VERSION --tag docker.io/vespaengine/vespa:latest \ - --tag ghcr.io/vespa-engine/vespa:$VESPA_VERSION --tag ghcr.io/vespa-engine/vespa:latest . +docker info +docker version +docker buildx version +docker buildx install + +unset DOCKER_HOST +docker context create vespa-context --docker "host=tcp://localhost:2376,ca=/certs/client/ca.pem,cert=/certs/client/cert.pem,key=/certs/client/key.pem" +docker context use vespa-context + +docker buildx create --name vespa-builder --driver docker-container --use +docker buildx inspect --bootstrap # Push to Docker Hub -docker login --username aressem --password "$DOCKER_HUB_DEPLOY_KEY" if curl -fsSL https://index.docker.io/v1/repositories/vespaengine/vespa/tags/$VESPA_VERSION &> /dev/null; then echo "Container image docker.io/vespaengine/vespa:$VESPA_VERSION aldready exists." else - docker push docker.io/vespaengine/vespa:$VESPA_VERSION - docker push docker.io/vespaengine/vespa:latest + docker login --username aressem --password "$DOCKER_HUB_DEPLOY_KEY" + docker buildx build --progress plain --push --platform linux/amd64,linux/arm64 --build-arg VESPA_VERSION=$VESPA_VERSION \ + --tag docker.io/vespaengine/vespa:$VESPA_VERSION --tag docker.io/vespaengine/vespa:latest . fi # Push to GitHub Container Registry -docker login --username aressem --password "$GHCR_DEPLOY_KEY" ghcr.io JWT=$(curl -sSL -u aressem:$GHCR_DEPLOY_KEY "https://ghcr.io/token?service=ghcr.io&scope=repository:vespa-engine/vespa:pull" | jq -re '.token') IMAGE_TAGS=$(curl -sSL -H "Authorization: Bearer $JWT" https://ghcr.io/v2/vespa-engine/vespa/tags/list | jq -re '.tags[]') if grep $VESPA_VERSION <<< "$IMAGE_TAGS" &> /dev/null; then echo "Container image ghcr.io/vespa-engine/vespa:$VESPA_VERSION aldready exists." else - docker push ghcr.io/vespa-engine/vespa:$VESPA_VERSION - docker push ghcr.io/vespa-engine/vespa:latest + docker login --username aressem --password "$GHCR_DEPLOY_KEY" ghcr.io + docker buildx build --progress plain --push --platform linux/amd64,linux/arm64 --build-arg VESPA_VERSION=$VESPA_VERSION \ + --tag ghcr.io/vespa-engine/vespa:$VESPA_VERSION --tag ghcr.io/vespa-engine/vespa:latest . fi diff --git a/searchcore/src/tests/proton/documentdb/documentbucketmover/CMakeLists.txt b/searchcore/src/tests/proton/documentdb/documentbucketmover/CMakeLists.txt index 6ca815cd216..5435e9eb93e 100644 --- a/searchcore/src/tests/proton/documentdb/documentbucketmover/CMakeLists.txt +++ b/searchcore/src/tests/proton/documentdb/documentbucketmover/CMakeLists.txt @@ -17,18 +17,6 @@ vespa_add_executable(searchcore_documentbucketmover_test_app TEST ) vespa_add_test(NAME searchcore_documentbucketmover_test_app COMMAND searchcore_documentbucketmover_test_app) -vespa_add_executable(searchcore_scaniterator_test_app TEST - SOURCES - scaniterator_test.cpp - DEPENDS - searchcore_bucketmover_test - searchcore_server - searchcore_test - searchcore_feedoperation - GTest::GTest -) -vespa_add_test(NAME searchcore_scaniterator_test_app COMMAND searchcore_scaniterator_test_app) - vespa_add_executable(searchcore_documentmover_test_app TEST SOURCES documentmover_test.cpp diff --git a/searchcore/src/tests/proton/documentdb/documentbucketmover/scaniterator_test.cpp b/searchcore/src/tests/proton/documentdb/documentbucketmover/scaniterator_test.cpp deleted file mode 100644 index 4ec38ff7170..00000000000 --- a/searchcore/src/tests/proton/documentdb/documentbucketmover/scaniterator_test.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "bucketmover_common.h" -#include <vespa/searchcore/proton/bucketdb/bucketscaniterator.h> -#include <vespa/vespalib/gtest/gtest.h> - -#include <vespa/log/log.h> -LOG_SETUP("document_bucket_mover_test"); - -using namespace proton; -using namespace proton::move::test; -using document::BucketId; - -using ScanItr = bucketdb::ScanIterator; - -struct ScanTestBase : public ::testing::Test -{ - test::UserDocumentsBuilder _builder; - std::shared_ptr<bucketdb::BucketDBOwner> _bucketDB; - MySubDb _ready; - MySubDb _notReady; - ScanTestBase(); - ~ScanTestBase(); - - ScanItr getItr() { - return getItr(BucketId()); - } - - ScanItr getItr(BucketId bucket) { - return ScanItr(_bucketDB->takeGuard(), bucket); - } -}; - -ScanTestBase::ScanTestBase() - : _builder(), - _bucketDB(std::make_shared<bucketdb::BucketDBOwner>()), - _ready(_builder.getRepo(), _bucketDB, 1, SubDbType::READY), - _notReady(_builder.getRepo(), _bucketDB, 2, SubDbType::NOTREADY) -{} -ScanTestBase::~ScanTestBase() = default; - -struct ScanTest : public ScanTestBase -{ - ScanTest() : ScanTestBase() - { - _builder.createDocs(6, 1, 2); - _builder.createDocs(8, 2, 3); - _ready.insertDocs(_builder.getDocs()); - _builder.clearDocs(); - _builder.createDocs(2, 1, 2); - _builder.createDocs(4, 2, 3); - _notReady.insertDocs(_builder.getDocs()); - _builder.clearDocs(); - } -}; - -struct OnlyNotReadyScanTest : public ScanTestBase -{ - OnlyNotReadyScanTest() : ScanTestBase() - { - _builder.createDocs(2, 1, 2); - _builder.createDocs(4, 2, 3); - _notReady.insertDocs(_builder.getDocs()); - } -}; - -struct OnlyReadyScanTest : public ScanTestBase -{ - OnlyReadyScanTest() : ScanTestBase() - { - _builder.createDocs(6, 1, 2); - _builder.createDocs(8, 2, 3); - _ready.insertDocs(_builder.getDocs()); - } -}; - -struct BucketVector : public BucketId::List -{ - BucketVector() : BucketId::List() {} - BucketVector &add(const BucketId &bucket) { - push_back(bucket); - return *this; - } -}; - -void -advanceToFirstBucketWithDocs(ScanItr &itr, SubDbType subDbType) -{ - while (itr.valid()) { - if (subDbType == SubDbType::READY) { - if (itr.hasReadyBucketDocs()) - return; - } else { - if (itr.hasNotReadyBucketDocs()) - return; - } - ++itr; - } -} - -void -assertEquals(const BucketVector &exp, ScanItr &itr, SubDbType subDbType) -{ - for (size_t i = 0; i < exp.size(); ++i) { - advanceToFirstBucketWithDocs(itr, subDbType); - EXPECT_TRUE(itr.valid()); - EXPECT_EQ(exp[i], itr.getBucket()); - ++itr; - } - advanceToFirstBucketWithDocs(itr, subDbType); - EXPECT_FALSE(itr.valid()); -} - -TEST_F(ScanTest, require_that_we_can_iterate_all_buckets_from_start_to_end) -{ - { - ScanItr itr = getItr(); - assertEquals(BucketVector(). - add(_notReady.bucket(2)). - add(_notReady.bucket(4)), itr, SubDbType::NOTREADY); - } - { - ScanItr itr = getItr(); - assertEquals(BucketVector(). - add(_ready.bucket(6)). - add(_ready.bucket(8)), itr, SubDbType::READY); - } -} - -TEST_F(ScanTest, require_that_we_can_iterate_from_the_middle_of_not_ready_buckets) -{ - BucketId bucket = _notReady.bucket(4); - { - ScanItr itr = getItr(bucket); - assertEquals(BucketVector(). - add(_notReady.bucket(4)), itr, SubDbType::NOTREADY); - } - { - ScanItr itr = getItr(); - assertEquals(BucketVector(). - add(_ready.bucket(6)). - add(_ready.bucket(8)), itr, SubDbType::READY); - } -} - -TEST_F(ScanTest, require_that_we_can_iterate_from_the_middle_of_ready_buckets) -{ - { - ScanItr itr = getItr(); - assertEquals(BucketVector(). - add(_notReady.bucket(2)). - add(_notReady.bucket(4)), itr, SubDbType::NOTREADY); - } - { - BucketId bucket = _ready.bucket(6); - ScanItr itr = getItr(bucket); - assertEquals(BucketVector(). - add(_ready.bucket(6)). - add(_ready.bucket(8)), itr, SubDbType::READY); - } -} - -TEST_F(OnlyNotReadyScanTest, require_that_we_can_iterate_only_not_ready_buckets) -{ - ScanItr itr = getItr(); - assertEquals(BucketVector(). - add(_notReady.bucket(2)). - add(_notReady.bucket(4)), itr, SubDbType::NOTREADY); -} - -TEST_F(OnlyReadyScanTest, require_that_we_can_iterate_only_ready_buckets) -{ - ScanItr itr = getItr(); - assertEquals(BucketVector(). - add(_ready.bucket(6)). - add(_ready.bucket(8)), itr, SubDbType::READY); -} - -TEST_F(ScanTestBase, require_that_we_can_iterate_zero_buckets) -{ - ScanItr itr = getItr(); - EXPECT_FALSE(itr.valid()); -} - -GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp b/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp index b326db47b5c..9d9bb64e6b1 100644 --- a/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp +++ b/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp @@ -143,7 +143,7 @@ struct MyIndexWriter : public test::MockIndexWriter uint32_t _wantedLidLimit; MyTracer &_tracer; MyIndexWriter(MyTracer &tracer) - : test::MockIndexWriter(IIndexManager::SP(new test::MockIndexManager())), + : test::MockIndexWriter(std::make_shared<test::MockIndexManager>()), _removes(), _heartBeatCount(0), _commitCount(0), @@ -224,7 +224,7 @@ struct MyDocumentStore : public test::DummyDocumentStore DocMap _docs; uint64_t _lastSyncToken; uint32_t _compactLidSpaceLidLimit; - MyDocumentStore(const document::DocumentTypeRepo & repo) + MyDocumentStore(const document::DocumentTypeRepo & repo) noexcept : test::DummyDocumentStore("."), _repo(repo), _docs(), @@ -266,42 +266,47 @@ MyDocumentStore::~MyDocumentStore() = default; struct MySummaryManager : public test::DummySummaryManager { MyDocumentStore _store; - MySummaryManager(const document::DocumentTypeRepo & repo) : _store(repo) {} - virtual search::IDocumentStore &getBackingStore() override { return _store; } + MySummaryManager(const document::DocumentTypeRepo & repo) noexcept : _store(repo) {} + ~MySummaryManager() override; + search::IDocumentStore &getBackingStore() override { return _store; } }; +MySummaryManager::~MySummaryManager() = default; + struct MySummaryAdapter : public test::MockSummaryAdapter { ISummaryManager::SP _sumMgr; MyDocumentStore &_store; MyLidVector _removes; - MySummaryAdapter(const document::DocumentTypeRepo & repo) - : _sumMgr(new MySummaryManager(repo)), + MySummaryAdapter(const document::DocumentTypeRepo & repo) noexcept + : _sumMgr(std::make_shared<MySummaryManager>(repo)), _store(static_cast<MyDocumentStore &>(_sumMgr->getBackingStore())), _removes() {} - virtual void put(SerialNum serialNum, DocumentIdT lid, const Document &doc) override { + ~MySummaryAdapter() override; + void put(SerialNum serialNum, DocumentIdT lid, const Document &doc) override { _store.write(serialNum, lid, doc); } - virtual void put(SerialNum serialNum, DocumentIdT lid, const vespalib::nbostream & os) override { + void put(SerialNum serialNum, DocumentIdT lid, const vespalib::nbostream & os) override { _store.write(serialNum, lid, os); } - virtual void remove(SerialNum serialNum, const DocumentIdT lid) override { + void remove(SerialNum serialNum, const DocumentIdT lid) override { LOG(info, "MySummaryAdapter::remove(): serialNum(%" PRIu64 "), docId(%u)", serialNum, lid); _store.remove(serialNum, lid); _removes.push_back(lid); } - virtual const search::IDocumentStore &getDocumentStore() const override { + const search::IDocumentStore &getDocumentStore() const override { return _store; } - virtual std::unique_ptr<Document> get(const DocumentIdT lid, const DocumentTypeRepo &repo) override { + std::unique_ptr<Document> get(const DocumentIdT lid, const DocumentTypeRepo &repo) override { return _store.read(lid, repo); } - virtual void compactLidSpace(uint32_t wantedDocIdLimit) override { + void compactLidSpace(uint32_t wantedDocIdLimit) override { _store.compactLidSpace(wantedDocIdLimit); } }; +MySummaryAdapter::~MySummaryAdapter() = default; struct MyAttributeWriter : public IAttributeWriter { @@ -362,7 +367,7 @@ struct MyAttributeWriter : public IAttributeWriter _updateLid = lid; for (const auto & fieldUpdate : upd.getUpdates()) { search::AttributeVector * attr = getWritableAttribute(fieldUpdate.getField().getName()); - onUpdate.onUpdateField(fieldUpdate.getField().getName(), attr); + onUpdate.onUpdateField(fieldUpdate.getField(), attr); } } void update(SerialNum serialNum, const document::Document &doc, DocumentIdT lid, OnWriteDoneType) override { @@ -434,7 +439,7 @@ struct SchemaContext }; SchemaContext::SchemaContext() : - _schema(new Schema()), + _schema(std::make_shared<Schema>()), _builder() { _schema->addIndexField(Schema::IndexField("i1", DataType::STRING, CollectionType::SINGLE)); @@ -442,7 +447,7 @@ SchemaContext::SchemaContext() : _schema->addAttributeField(Schema::AttributeField("a2", DataType::BOOLEANTREE, CollectionType::SINGLE)); _schema->addAttributeField(Schema::AttributeField("a3", DataType::TENSOR, CollectionType::SINGLE)); _schema->addSummaryField(Schema::SummaryField("s1", DataType::STRING, CollectionType::SINGLE)); - _builder.reset(new DocBuilder(*_schema)); + _builder = std::make_unique<DocBuilder>(*_schema); } SchemaContext::~SchemaContext() = default; @@ -464,7 +469,7 @@ struct DocumentContext DocumentContext::DocumentContext(const vespalib::string &docId, uint64_t timestamp, DocBuilder &builder) : doc(builder.startDocument(docId).startSummaryField("s1").addStr(docId).endField().endDocument().release()), - upd(new DocumentUpdate(*builder.getDocumentTypeRepo(), builder.getDocumentType(), doc->getId())), + upd(std::make_shared<DocumentUpdate>(*builder.getDocumentTypeRepo(), builder.getDocumentType(), doc->getId())), bid(BucketFactory::getNumBucketBits(), doc->getId().getGlobalId().convertToBucketId().getRawId()), ts(timestamp) {} diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp index bb25b3da7be..021fc4717af 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp @@ -764,9 +764,9 @@ AttributeWriter::update(SerialNum serialNum, const DocumentUpdate &upd, Document for (const auto &fupd : upd.getUpdates()) { LOG(debug, "Retrieving guard for attribute vector '%s'.", fupd.getField().getName().data()); - auto itr = _attrMap.find(fupd.getField().getName()); - AttributeVector * attrp = (itr != _attrMap.end()) ? itr->second.attribute : nullptr; - onUpdate.onUpdateField(fupd.getField().getName(), attrp); + auto found = _attrMap.find(fupd.getField().getName()); + AttributeVector * attrp = (found != _attrMap.end()) ? found->second.attribute : nullptr; + onUpdate.onUpdateField(fupd.getField(), attrp); if (__builtin_expect(attrp == nullptr, false)) { LOG(spam, "Failed to find attribute vector %s", fupd.getField().getName().data()); continue; @@ -776,16 +776,15 @@ AttributeWriter::update(SerialNum serialNum, const DocumentUpdate &upd, Document if (__builtin_expect(attrp->getStatus().getLastSyncToken() >= serialNum, false)) { continue; } - if (itr->second.use_two_phase_put_for_assign_updates && - is_single_assign_update(fupd)) { + if (found->second.use_two_phase_put_for_assign_updates && is_single_assign_update(fupd)) { auto prepare_task = std::make_unique<PreparePutTask>(serialNum, lid, *attrp, get_single_assign_update_field_value(fupd)); auto complete_task = std::make_unique<CompletePutTask>(*prepare_task, onWriteDone); LOG(debug, "About to handle assign update as two phase put for docid %u in attribute vector '%s'", lid, attrp->getName().c_str()); _shared_executor.execute(CpuUsage::wrap(std::move(prepare_task), CpuUsage::Category::WRITE)); - _attributeFieldWriter.executeTask(itr->second.executor_id, std::move(complete_task)); + _attributeFieldWriter.executeTask(found->second.executor_id, std::move(complete_task)); } else { - args[itr->second.executor_id.getId()]->_updates.emplace_back(attrp, &fupd); + args[found->second.executor_id.getId()]->_updates.emplace_back(attrp, &fupd); LOG(debug, "About to apply update for docId %u in attribute vector '%s'.", lid, attrp->getName().c_str()); } } diff --git a/searchcore/src/vespa/searchcore/proton/attribute/ifieldupdatecallback.h b/searchcore/src/vespa/searchcore/proton/attribute/ifieldupdatecallback.h index d8872607b44..d3ab970fb39 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/ifieldupdatecallback.h +++ b/searchcore/src/vespa/searchcore/proton/attribute/ifieldupdatecallback.h @@ -5,16 +5,17 @@ #include <vespa/vespalib/stllike/string.h> namespace search { class AttributeVector; } +namespace document { class Field; } namespace proton { struct IFieldUpdateCallback { - virtual ~IFieldUpdateCallback() { } - virtual void onUpdateField(vespalib::stringref fieldName, const search::AttributeVector * attr) = 0; + virtual ~IFieldUpdateCallback() = default; + virtual void onUpdateField(const document::Field & field, const search::AttributeVector * attr) = 0; }; struct DummyFieldUpdateCallback : IFieldUpdateCallback { - void onUpdateField(vespalib::stringref, const search::AttributeVector *) override {} + void onUpdateField(const document::Field & , const search::AttributeVector *) override {} }; } diff --git a/searchcore/src/vespa/searchcore/proton/bucketdb/CMakeLists.txt b/searchcore/src/vespa/searchcore/proton/bucketdb/CMakeLists.txt index 810fe53236d..a542f44f27e 100644 --- a/searchcore/src/vespa/searchcore/proton/bucketdb/CMakeLists.txt +++ b/searchcore/src/vespa/searchcore/proton/bucketdb/CMakeLists.txt @@ -6,7 +6,6 @@ vespa_add_library(searchcore_bucketdb STATIC bucket_db_owner.cpp bucketdb.cpp bucketdbhandler.cpp - bucketscaniterator.cpp bucketsessionbase.cpp bucketstate.cpp checksumaggregators.cpp diff --git a/searchcore/src/vespa/searchcore/proton/bucketdb/bucket_db_explorer.cpp b/searchcore/src/vespa/searchcore/proton/bucketdb/bucket_db_explorer.cpp index b68892be60f..9d28d88ba4a 100644 --- a/searchcore/src/vespa/searchcore/proton/bucketdb/bucket_db_explorer.cpp +++ b/searchcore/src/vespa/searchcore/proton/bucketdb/bucket_db_explorer.cpp @@ -33,10 +33,11 @@ checksumToString(storage::spi::BucketChecksum checksum) void convertBucketsToSlime(const BucketDB &bucketDb, Cursor &array) { - for (auto itr = bucketDb.begin(); itr != bucketDb.end(); ++itr) { + BucketId::List buckets = bucketDb.getBuckets(); + for (BucketId bucketId : buckets) { Cursor &object = array.addObject(); - object.setString("id", bucketIdToString(itr->first)); - const bucketdb::BucketState &state = itr->second; + object.setString("id", bucketIdToString(bucketId)); + bucketdb::BucketState state = bucketDb.get(bucketId); object.setString("checksum", checksumToString(state.getChecksum())); object.setLong("readyCount", state.getReadyCount()); object.setLong("notReadyCount", state.getNotReadyCount()); diff --git a/searchcore/src/vespa/searchcore/proton/bucketdb/bucketdb.cpp b/searchcore/src/vespa/searchcore/proton/bucketdb/bucketdb.cpp index ecdc679e4bc..a99d5cbd573 100644 --- a/searchcore/src/vespa/searchcore/proton/bucketdb/bucketdb.cpp +++ b/searchcore/src/vespa/searchcore/proton/bucketdb/bucketdb.cpp @@ -2,6 +2,7 @@ #include "bucketdb.h" #include "remove_batch_entry.h" +#include <vespa/vespalib/stllike/hash_map.hpp> #include <cassert> #include <algorithm> #include <optional> @@ -27,22 +28,19 @@ BucketDB::~BucketDB() } void -BucketDB::add(const BucketId &bucketId, const BucketState & state) { +BucketDB::add(BucketId bucketId, const BucketState & state) { _map[bucketId] += state; } bucketdb::BucketState * -BucketDB::getBucketStatePtr(const BucketId &bucket) +BucketDB::getBucketStatePtr(BucketId bucket) { auto it(_map.find(bucket)); - if (it != _map.end()) { - return &it->second; - } - return nullptr; + return (it != _map.end()) ? &it->second : nullptr; } void -BucketDB::unloadBucket(const BucketId &bucket, const BucketState &delta) +BucketDB::unloadBucket(BucketId bucket, const BucketState &delta) { BucketState *state = getBucketStatePtr(bucket); assert(state); @@ -51,7 +49,7 @@ BucketDB::unloadBucket(const BucketId &bucket, const BucketState &delta) const bucketdb::BucketState & BucketDB::add(const GlobalId &gid, - const BucketId &bucketId, const Timestamp ×tamp, uint32_t docSize, + BucketId bucketId, Timestamp timestamp, uint32_t docSize, SubDbType subDbType) { BucketState &state = _map[bucketId]; @@ -61,7 +59,7 @@ BucketDB::add(const GlobalId &gid, void BucketDB::remove(const GlobalId &gid, - const BucketId &bucketId, const Timestamp ×tamp, uint32_t docSize, + BucketId bucketId, Timestamp timestamp, uint32_t docSize, SubDbType subDbType) { BucketState &state = _map[bucketId]; @@ -84,8 +82,8 @@ BucketDB::remove_batch(const std::vector<RemoveBatchEntry> &removed, SubDbType s void BucketDB::modify(const GlobalId &gid, - const BucketId &oldBucketId, const Timestamp &oldTimestamp, uint32_t oldDocSize, - const BucketId &newBucketId, const Timestamp &newTimestamp, uint32_t newDocSize, + BucketId oldBucketId, Timestamp oldTimestamp, uint32_t oldDocSize, + BucketId newBucketId, Timestamp newTimestamp, uint32_t newDocSize, SubDbType subDbType) { if (oldBucketId == newBucketId) { @@ -99,17 +97,14 @@ BucketDB::modify(const GlobalId &gid, bucketdb::BucketState -BucketDB::get(const BucketId &bucketId) const +BucketDB::get(BucketId bucketId) const { auto itr = _map.find(bucketId); - if (itr != _map.end()) { - return itr->second; - } - return BucketState(); + return (itr != _map.end()) ? itr->second : BucketState(); } void -BucketDB::cacheBucket(const BucketId &bucketId) +BucketDB::cacheBucket(BucketId bucketId) { _cachedBucketId = bucketId; _cachedBucketState = get(bucketId); @@ -123,13 +118,13 @@ BucketDB::uncacheBucket() } bool -BucketDB::isCachedBucket(const BucketId &bucketId) const +BucketDB::isCachedBucket(BucketId bucketId) const { return _cachedBucketId == bucketId; } bucketdb::BucketState -BucketDB::cachedGet(const BucketId &bucketId) const +BucketDB::cachedGet(BucketId bucketId) const { if (isCachedBucket(bucketId)) { return _cachedBucketState; @@ -138,27 +133,23 @@ BucketDB::cachedGet(const BucketId &bucketId) const } storage::spi::BucketInfo -BucketDB::cachedGetBucketInfo(const BucketId &bucketId) const +BucketDB::cachedGetBucketInfo(BucketId bucketId) const { if (isCachedBucket(bucketId)) { return _cachedBucketState; } - auto itr = _map.find(bucketId); - if (itr != _map.end()) { - return itr->second; - } - return BucketState(); + return get(bucketId); } bool -BucketDB::hasBucket(const BucketId &bucketId) const +BucketDB::hasBucket(BucketId bucketId) const { return (_map.find(bucketId) != _map.end()); } bool -BucketDB::isActiveBucket(const BucketId &bucketId) const +BucketDB::isActiveBucket(BucketId bucketId) const { auto itr = _map.find(bucketId); return (itr != _map.end()) && itr->second.isActive(); @@ -172,6 +163,7 @@ BucketDB::getBuckets() const for (const auto & entry : _map) { buckets.push_back(entry.first); } + std::sort(buckets.begin(), buckets.end()); return buckets; } @@ -199,7 +191,7 @@ BucketDB::checkEmpty() const void -BucketDB::setBucketState(const BucketId &bucketId, bool active) +BucketDB::setBucketState(BucketId bucketId, bool active) { BucketState &state = _map[bucketId]; state.setActive(active); @@ -207,7 +199,7 @@ BucketDB::setBucketState(const BucketId &bucketId, bool active) void -BucketDB::createBucket(const BucketId &bucketId) +BucketDB::createBucket(BucketId bucketId) { BucketState &state = _map[bucketId]; (void) state; @@ -215,7 +207,7 @@ BucketDB::createBucket(const BucketId &bucketId) void -BucketDB::deleteEmptyBucket(const BucketId &bucketId) +BucketDB::deleteEmptyBucket(BucketId bucketId) { auto itr = _map.find(bucketId); if (itr == _map.end()) { @@ -231,11 +223,13 @@ document::BucketId::List BucketDB::getActiveBuckets() const { BucketId::List buckets; + buckets.reserve(_map.size()); for (const auto & entry : _map) { if (entry.second.isActive()) { buckets.push_back(entry.first); } } + std::sort(buckets.begin(), buckets.end()); return buckets; } @@ -247,11 +241,12 @@ BucketDB::populateActiveBuckets(BucketId::List buckets) std::sort(buckets.begin(), buckets.end()); auto si = buckets.begin(); auto se = buckets.end(); - for (const auto & entry : _map) { - for (; si != se && !(entry.first < *si); ++si) { - if (*si < entry.first) { + BucketId::List currentBuckets = getBuckets(); + for (BucketId bucketId : currentBuckets) { + for (; si != se && !(bucketId < *si); ++si) { + if (*si < bucketId) { toAdd.push_back(*si); - } else if (!entry.second.isActive()) { + } else if (!isActiveBucket(bucketId)) { fixupBuckets.push_back(*si); setBucketState(*si, true); } @@ -262,8 +257,8 @@ BucketDB::populateActiveBuckets(BucketId::List buckets) } BucketState activeState; activeState.setActive(true); - for (const BucketId & bucketId : toAdd) { - auto [itr, inserted] = _map.emplace(bucketId, activeState); + for (BucketId bucketId : toAdd) { + auto [itr, inserted] = _map.insert(std::make_pair(bucketId, activeState)); assert(inserted); } return fixupBuckets; diff --git a/searchcore/src/vespa/searchcore/proton/bucketdb/bucketdb.h b/searchcore/src/vespa/searchcore/proton/bucketdb/bucketdb.h index da475f2969a..bd6aa16504b 100644 --- a/searchcore/src/vespa/searchcore/proton/bucketdb/bucketdb.h +++ b/searchcore/src/vespa/searchcore/proton/bucketdb/bucketdb.h @@ -5,7 +5,7 @@ #include "bucketstate.h" #include <vespa/document/bucket/bucketid.h> #include <vespa/persistence/spi/result.h> -#include <map> +#include <vespa/vespalib/stllike/hash_map.h> namespace proton::bucketdb { class RemoveBatchEntry; } @@ -19,8 +19,7 @@ public: typedef storage::spi::Timestamp Timestamp; typedef storage::spi::BucketChecksum BucketChecksum; typedef bucketdb::BucketState BucketState; - typedef std::map<BucketId, BucketState> Map; - typedef Map::const_iterator ConstMapIterator; + typedef vespalib::hash_map<BucketId, BucketState, BucketId::hash> Map; private: Map _map; @@ -34,43 +33,39 @@ public: ~BucketDB(); const BucketState & add(const GlobalId &gid, - const BucketId &bucketId, const Timestamp ×tamp, uint32_t docSize, + BucketId bucketId, Timestamp timestamp, uint32_t docSize, SubDbType subDbType); - void add(const BucketId &bucketId, const BucketState & state); + void add(BucketId bucketId, const BucketState & state); void remove(const GlobalId &gid, - const BucketId &bucketId, const Timestamp ×tamp, uint32_t docSize, + BucketId bucketId, Timestamp timestamp, uint32_t docSize, SubDbType subDbType); void remove_batch(const std::vector<bucketdb::RemoveBatchEntry> &removed, SubDbType sub_db_type); void modify(const GlobalId &gid, - const BucketId &oldBucketId, const Timestamp &oldTimestamp, uint32_t oldDocSize, - const BucketId &newBucketId, const Timestamp &newTimestamp, uint32_t newDocSize, + BucketId oldBucketId, Timestamp oldTimestamp, uint32_t oldDocSize, + BucketId newBucketId, Timestamp newTimestamp, uint32_t newDocSize, SubDbType subDbType); - BucketState get(const BucketId &bucketId) const; - void cacheBucket(const BucketId &bucketId); + BucketState get(BucketId bucketId) const; + void cacheBucket(BucketId bucketId); void uncacheBucket(); - bool isCachedBucket(const BucketId &bucketId) const; - storage::spi::BucketInfo cachedGetBucketInfo(const BucketId &bucketId) const; - BucketState cachedGet(const BucketId &bucketId) const; - bool hasBucket(const BucketId &bucketId) const; + bool isCachedBucket(BucketId bucketId) const; + storage::spi::BucketInfo cachedGetBucketInfo(BucketId bucketId) const; + BucketState cachedGet(BucketId bucketId) const; + bool hasBucket(BucketId bucketId) const; BucketId::List getBuckets() const; bool empty() const; - void setBucketState(const BucketId &bucketId, bool active); - void createBucket(const BucketId &bucketId); - void deleteEmptyBucket(const BucketId &bucketId); + void setBucketState(BucketId bucketId, bool active); + void createBucket(BucketId bucketId); + void deleteEmptyBucket(BucketId bucketId); BucketId::List getActiveBuckets() const; BucketId::List populateActiveBuckets(BucketId::List buckets); - - ConstMapIterator begin() const { return _map.begin(); } - ConstMapIterator end() const { return _map.end(); } - ConstMapIterator lowerBound(const BucketId &bucket) const { return _map.lower_bound(bucket); } size_t size() const { return _map.size(); } - bool isActiveBucket(const BucketId &bucketId) const; - BucketState *getBucketStatePtr(const BucketId &bucket); - void unloadBucket(const BucketId &bucket, const BucketState &delta); + bool isActiveBucket(BucketId bucketId) const; + BucketState *getBucketStatePtr(BucketId bucket); + void unloadBucket(BucketId bucket, const BucketState &delta); }; } diff --git a/searchcore/src/vespa/searchcore/proton/bucketdb/bucketscaniterator.cpp b/searchcore/src/vespa/searchcore/proton/bucketdb/bucketscaniterator.cpp deleted file mode 100644 index c691e786add..00000000000 --- a/searchcore/src/vespa/searchcore/proton/bucketdb/bucketscaniterator.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "bucketscaniterator.h" - -using document::BucketId; - -namespace proton::bucketdb { - -ScanIterator::ScanIterator(const Guard & db, BucketId bucket) - : _db(std::move(db)), - _itr(_db->lowerBound(bucket)), - _end(_db->end()) -{ } - -} // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/bucketdb/bucketscaniterator.h b/searchcore/src/vespa/searchcore/proton/bucketdb/bucketscaniterator.h deleted file mode 100644 index 1b68cfc1e59..00000000000 --- a/searchcore/src/vespa/searchcore/proton/bucketdb/bucketscaniterator.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include "bucket_db_owner.h" -#include "bucketdb.h" - -namespace proton::bucketdb { - - -class ScanIterator { -private: - using BucketId = document::BucketId; - using BucketIterator = BucketDB::ConstMapIterator; - const Guard &_db; - BucketIterator _itr; - BucketIterator _end; - -public: - ScanIterator(const Guard & db, BucketId bucket); - ScanIterator(const ScanIterator &) = delete; - ScanIterator(ScanIterator &&rhs) = delete; - ScanIterator &operator=(const ScanIterator &) = delete; - ScanIterator &operator=(ScanIterator &&rhs) = delete; - - bool valid() const { return _itr != _end; } - bool isActive() const { return _itr->second.isActive(); } - BucketId getBucket() const { return _itr->first; } - bool hasReadyBucketDocs() const { return _itr->second.getReadyCount() != 0; } - bool hasNotReadyBucketDocs() const { return _itr->second.getNotReadyCount() != 0; } - - ScanIterator & operator++() { - ++_itr; - return *this; - } -}; - -} diff --git a/searchcore/src/vespa/searchcore/proton/matching/match_loop_communicator.h b/searchcore/src/vespa/searchcore/proton/matching/match_loop_communicator.h index 217fa2db1f5..3f50bf9faec 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/match_loop_communicator.h +++ b/searchcore/src/vespa/searchcore/proton/matching/match_loop_communicator.h @@ -8,7 +8,7 @@ namespace proton::matching { -class MatchLoopCommunicator : public IMatchLoopCommunicator +class MatchLoopCommunicator final : public IMatchLoopCommunicator { private: using IDiversifier = search::queryeval::IDiversifier; diff --git a/searchcore/src/vespa/searchcore/proton/matching/match_master.cpp b/searchcore/src/vespa/searchcore/proton/matching/match_master.cpp index 985176bcef5..84ff0672fa0 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/match_master.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/match_master.cpp @@ -24,7 +24,7 @@ using vespalib::Issue; namespace { -struct TimedMatchLoopCommunicator : IMatchLoopCommunicator { +struct TimedMatchLoopCommunicator final : IMatchLoopCommunicator { IMatchLoopCommunicator &communicator; vespalib::Timer timer; vespalib::duration elapsed; diff --git a/searchcore/src/vespa/searchcore/proton/matching/match_tools.cpp b/searchcore/src/vespa/searchcore/proton/matching/match_tools.cpp index e0449236af0..eecbf116e9d 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/match_tools.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/match_tools.cpp @@ -14,15 +14,12 @@ #include <vespa/vespalib/data/slime/inserter.h> #include <vespa/vespalib/util/issue.h> -using search::attribute::IAttributeContext; -using search::queryeval::IRequestContext; using search::queryeval::IDiversifier; using search::attribute::diversity::DiversityFilter; using search::attribute::BasicType; using search::attribute::AttributeBlueprintParams; using vespalib::Issue; -using namespace search::fef; using namespace search::fef::indexproperties::matchphase; using namespace search::fef::indexproperties::matching; using namespace search::fef::indexproperties; @@ -33,6 +30,9 @@ namespace proton::matching { namespace { +using search::fef::Properties; +using search::fef::RankSetup; + bool contains_all(const HandleRecorder::HandleMap &old_map, const HandleRecorder::HandleMap &new_map) { @@ -70,7 +70,7 @@ extractDiversityParams(const RankSetup &rankSetup, const Properties &rankPropert } // namespace proton::matching::<unnamed> void -MatchTools::setup(search::fef::RankProgram::UP rank_program, double termwise_limit) +MatchTools::setup(std::unique_ptr<RankProgram> rank_program, double termwise_limit) { if (_search) { _match_data->soft_reset(); @@ -240,12 +240,12 @@ std::unique_ptr<IDiversifier> MatchToolsFactory::createDiversifier(uint32_t heapSize) const { if ( !_diversityParams.enabled() ) { - return std::unique_ptr<IDiversifier>(); + return {}; } auto attr = _requestContext.getAttribute(_diversityParams.attribute); if ( !attr) { Issue::report("Skipping diversity due to no %s attribute.", _diversityParams.attribute.c_str()); - return std::unique_ptr<IDiversifier>(); + return {}; } size_t max_per_group = heapSize/_diversityParams.min_groups; return DiversityFilter::create(*attr, heapSize, max_per_group, _diversityParams.min_groups, @@ -302,10 +302,8 @@ MatchToolsFactory::get_feature_rename_map() const } AttributeBlueprintParams -MatchToolsFactory::extract_global_filter_params(const search::fef::RankSetup& rank_setup, - const search::fef::Properties& rank_properties, - uint32_t active_docids, - uint32_t docid_limit) +MatchToolsFactory::extract_global_filter_params(const RankSetup& rank_setup, const Properties& rank_properties, + uint32_t active_docids, uint32_t docid_limit) { double lower_limit = GlobalFilterLowerLimit::lookup(rank_properties, rank_setup.get_global_filter_lower_limit()); double upper_limit = GlobalFilterUpperLimit::lookup(rank_properties, rank_setup.get_global_filter_upper_limit()); diff --git a/searchcore/src/vespa/searchcore/proton/matching/match_tools.h b/searchcore/src/vespa/searchcore/proton/matching/match_tools.h index 11e943957ef..d7254d4b958 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/match_tools.h +++ b/searchcore/src/vespa/searchcore/proton/matching/match_tools.h @@ -30,19 +30,25 @@ class MatchTools { private: using IRequestContext = search::queryeval::IRequestContext; - QueryLimiter &_queryLimiter; - const vespalib::Doom &_doom; - const Query &_query; - MaybeMatchPhaseLimiter &_match_limiter; - const QueryEnvironment &_queryEnv; - const search::fef::RankSetup &_rankSetup; - const search::fef::Properties &_featureOverrides; - std::unique_ptr<search::fef::MatchData> _match_data; - std::unique_ptr<search::fef::RankProgram> _rank_program; - search::queryeval::SearchIterator::UP _search; - HandleRecorder::HandleMap _used_handles; - bool _search_has_changed; - void setup(std::unique_ptr<search::fef::RankProgram>, double termwise_limit = 1.0); + using SearchIterator = search::queryeval::SearchIterator; + using MatchData = search::fef::MatchData; + using MatchDataLayout = search::fef::MatchDataLayout; + using Properties = search::fef::Properties; + using RankProgram = search::fef::RankProgram; + using RankSetup = search::fef::RankSetup; + QueryLimiter &_queryLimiter; + const vespalib::Doom &_doom; + const Query &_query; + MaybeMatchPhaseLimiter &_match_limiter; + const QueryEnvironment &_queryEnv; + const RankSetup &_rankSetup; + const Properties &_featureOverrides; + std::unique_ptr<MatchData> _match_data; + std::unique_ptr<RankProgram> _rank_program; + std::unique_ptr<SearchIterator> _search; + HandleRecorder::HandleMap _used_handles; + bool _search_has_changed; + void setup(std::unique_ptr<RankProgram>, double termwise_limit = 1.0); public: typedef std::unique_ptr<MatchTools> UP; MatchTools(const MatchTools &) = delete; @@ -52,19 +58,19 @@ public: const Query &query, MaybeMatchPhaseLimiter &match_limiter_in, const QueryEnvironment &queryEnv, - const search::fef::MatchDataLayout &mdl, - const search::fef::RankSetup &rankSetup, - const search::fef::Properties &featureOverrides); + const MatchDataLayout &mdl, + const RankSetup &rankSetup, + const Properties &featureOverrides); ~MatchTools(); const vespalib::Doom &getDoom() const { return _doom; } QueryLimiter & getQueryLimiter() { return _queryLimiter; } MaybeMatchPhaseLimiter &match_limiter() { return _match_limiter; } bool has_second_phase_rank() const; - const search::fef::MatchData &match_data() const { return *_match_data; } - search::fef::RankProgram &rank_program() { return *_rank_program; } - search::queryeval::SearchIterator &search() { return *_search; } - search::queryeval::SearchIterator::UP borrow_search() { return std::move(_search); } - void give_back_search(search::queryeval::SearchIterator::UP search_in) { _search = std::move(search_in); } + const MatchData &match_data() const { return *_match_data; } + RankProgram &rank_program() { return *_rank_program; } + SearchIterator &search() { return *_search; } + std::unique_ptr<SearchIterator> borrow_search() { return std::move(_search); } + void give_back_search(std::unique_ptr<SearchIterator> search_in) { _search = std::move(search_in); } void tag_search_as_changed() { _search_has_changed = true; } void setup_first_phase(); void setup_second_phase(); @@ -92,17 +98,25 @@ class MatchToolsFactory { private: using IAttributeFunctor = search::attribute::IAttributeFunctor; - QueryLimiter & _queryLimiter; - search::attribute::AttributeBlueprintParams _global_filter_params; - Query _query; - MaybeMatchPhaseLimiter::UP _match_limiter; - QueryEnvironment _queryEnv; - RequestContext _requestContext; - search::fef::MatchDataLayout _mdl; - const search::fef::RankSetup & _rankSetup; - const search::fef::Properties & _featureOverrides; - DiversityParams _diversityParams; - bool _valid; + using IAttributeContext = search::attribute::IAttributeContext; + using AttributeBlueprintParams = search::attribute::AttributeBlueprintParams; + using MatchDataLayout = search::fef::MatchDataLayout; + using Properties = search::fef::Properties; + using RankProgram = search::fef::RankProgram; + using RankSetup = search::fef::RankSetup; + using IIndexEnvironment = search::fef::IIndexEnvironment; + using IDiversifier = search::queryeval::IDiversifier; + QueryLimiter & _queryLimiter; + AttributeBlueprintParams _global_filter_params; + Query _query; + MaybeMatchPhaseLimiter::UP _match_limiter; + QueryEnvironment _queryEnv; + RequestContext _requestContext; + MatchDataLayout _mdl; + const RankSetup & _rankSetup; + const Properties & _featureOverrides; + DiversityParams _diversityParams; + bool _valid; std::unique_ptr<AttributeOperationTask> createTask(vespalib::stringref attribute, vespalib::stringref operation) const; @@ -114,23 +128,23 @@ public: MatchToolsFactory(QueryLimiter & queryLimiter, const vespalib::Doom & softDoom, ISearchContext &searchContext, - search::attribute::IAttributeContext &attributeContext, + IAttributeContext &attributeContext, search::engine::Trace & root_trace, vespalib::stringref queryStack, const vespalib::string &location, const ViewResolver &viewResolver, const search::IDocumentMetaStore &metaStore, - const search::fef::IIndexEnvironment &indexEnv, - const search::fef::RankSetup &rankSetup, - const search::fef::Properties &rankProperties, - const search::fef::Properties &featureOverrides, + const IIndexEnvironment &indexEnv, + const RankSetup &rankSetup, + const Properties &rankProperties, + const Properties &featureOverrides, bool is_search); ~MatchToolsFactory(); bool valid() const { return _valid; } const MaybeMatchPhaseLimiter &match_limiter() const { return *_match_limiter; } MatchTools::UP createMatchTools() const; bool should_diversify() const { return _diversityParams.enabled(); } - std::unique_ptr<search::queryeval::IDiversifier> createDiversifier(uint32_t heapSize) const; + std::unique_ptr<IDiversifier> createDiversifier(uint32_t heapSize) const; search::queryeval::Blueprint::HitEstimate estimate() const { return _query.estimate(); } bool has_first_phase_rank() const; bool has_match_features() const; @@ -151,11 +165,9 @@ public: * When searchable-copies > 1, we must scale the parameters to match the effective range of the estimated hit ratio. * This is done by multiplying with the active hit ratio (active docids / docid limit). */ - static search::attribute::AttributeBlueprintParams - extract_global_filter_params(const search::fef::RankSetup& rank_setup, - const search::fef::Properties& rank_properties, - uint32_t active_docids, - uint32_t docid_limit); + static AttributeBlueprintParams + extract_global_filter_params(const RankSetup& rank_setup, const Properties& rank_properties, + uint32_t active_docids, uint32_t docid_limit); }; } diff --git a/searchcore/src/vespa/searchcore/proton/server/bucketmovejob.cpp b/searchcore/src/vespa/searchcore/proton/server/bucketmovejob.cpp index 45cac1d02e9..415000c3f9b 100644 --- a/searchcore/src/vespa/searchcore/proton/server/bucketmovejob.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/bucketmovejob.cpp @@ -9,6 +9,7 @@ #include "document_db_maintenance_config.h" #include <vespa/searchcore/proton/metrics/documentdb_tagged_metrics.h> #include <vespa/searchcore/proton/bucketdb/i_bucket_create_notifier.h> +#include <vespa/searchcore/proton/bucketdb/bucket_db_owner.h> #include <vespa/searchcore/proton/feedoperation/moveoperation.h> #include <vespa/searchcore/proton/documentmetastore/i_document_meta_store.h> #include <vespa/searchcorespi/index/i_thread_service.h> @@ -141,7 +142,7 @@ BucketMoveJob::create(const std::shared_ptr<IBucketStateCalculator> &calc, } BucketMoveJob::NeedResult -BucketMoveJob::needMove(const ScanIterator &itr) const { +BucketMoveJob::needMove(BucketId bucketId, const BucketStateWrapper &itr) const { NeedResult noMove(false, false); const bool hasReadyDocs = itr.hasReadyBucketDocs(); const bool hasNotReadyDocs = itr.hasNotReadyBucketDocs(); @@ -154,13 +155,13 @@ BucketMoveJob::needMove(const ScanIterator &itr) const { if (!_calc || (_calc->nodeRetired() && !isActive)) { return noMove; } - const Trinary shouldBeReady = _calc->shouldBeReady(document::Bucket(_bucketSpace, itr.getBucket())); + const Trinary shouldBeReady = _calc->shouldBeReady(document::Bucket(_bucketSpace, bucketId)); if (shouldBeReady == Trinary::Undefined) { return noMove; } const bool wantReady = (shouldBeReady == Trinary::True) || isActive; LOG(spam, "needMove(): bucket(%s), shouldBeReady(%s), active(%s)", - itr.getBucket().toString().c_str(), toStr(shouldBeReady), toStr(isActive)); + bucketId.toString().c_str(), toStr(shouldBeReady), toStr(isActive)); if (wantReady) { if (!hasNotReadyDocs) { return noMove; // No notready bucket to make ready @@ -301,8 +302,7 @@ BucketMoveJob::considerBucket(const bucketdb::Guard & guard, BucketId bucket) { void BucketMoveJob::reconsiderBucket(const bucketdb::Guard & guard, BucketId bucket) { assert( ! _bucketsInFlight.contains(bucket)); - ScanIterator itr(guard, bucket); - auto [mustMove, wantReady] = needMove(itr); + auto [mustMove, wantReady] = needMove(bucket, guard->get(bucket)); if (mustMove) { _buckets2Move[bucket] = wantReady; } else { @@ -322,10 +322,11 @@ BucketMoveJob::BucketMoveSet BucketMoveJob::computeBuckets2Move(const bucketdb::Guard & guard) { BucketMoveJob::BucketMoveSet toMove; - for (ScanIterator itr(guard, BucketId()); itr.valid(); ++itr) { - auto [mustMove, wantReady] = needMove(itr); + BucketId::List buckets = guard->getBuckets(); + for (BucketId bucketId : buckets) { + auto [mustMove, wantReady] = needMove(bucketId, guard->get(bucketId)); if (mustMove) { - toMove[itr.getBucket()] = wantReady; + toMove[bucketId] = wantReady; } } return toMove; diff --git a/searchcore/src/vespa/searchcore/proton/server/bucketmovejob.h b/searchcore/src/vespa/searchcore/proton/server/bucketmovejob.h index d4438fcd411..9885b581a24 100644 --- a/searchcore/src/vespa/searchcore/proton/server/bucketmovejob.h +++ b/searchcore/src/vespa/searchcore/proton/server/bucketmovejob.h @@ -8,9 +8,9 @@ #include "ibucketstatechangedhandler.h" #include "iclusterstatechangedhandler.h" #include "maintenancedocumentsubdb.h" -#include <vespa/searchcore/proton/bucketdb/bucketscaniterator.h> #include <vespa/searchcore/proton/bucketdb/i_bucket_create_listener.h> #include <vespa/vespalib/util/retain_guard.h> +#include <map> namespace storage::spi { struct BucketExecutor; } @@ -49,7 +49,6 @@ private: using IDestructorCallbackSP = std::shared_ptr<IDestructorCallback>; using IThreadService = searchcorespi::index::IThreadService; using BucketId = document::BucketId; - using ScanIterator = bucketdb::ScanIterator; using BucketMoveSet = std::map<BucketId, bool>; using NeedResult = std::pair<bool, bool>; using ActiveState = storage::spi::BucketInfo::ActiveState; @@ -79,6 +78,17 @@ private: IBucketStateChangedNotifier &_bucketStateChangedNotifier; IDiskMemUsageNotifier &_diskMemUsageNotifier; + class BucketStateWrapper { + private: + const bucketdb::BucketState & _state; + + public: + BucketStateWrapper(const bucketdb::BucketState & state) noexcept : _state(state) {} + + bool isActive() const noexcept { return _state.isActive(); } + bool hasReadyBucketDocs() const noexcept { return _state.getReadyCount() != 0; } + bool hasNotReadyBucketDocs() const noexcept { return _state.getNotReadyCount() != 0; } + }; BucketMoveJob(const std::shared_ptr<IBucketStateCalculator> &calc, vespalib::RetainGuard dbRetainer, IDocumentMoveHandler &moveHandler, @@ -103,7 +113,7 @@ private: void reconsiderBucket(const bucketdb::Guard & guard, BucketId bucket); void updatePending(); void cancelBucket(BucketId bucket); // True if something to cancel - NeedResult needMove(const ScanIterator &itr) const; + NeedResult needMove(BucketId bucketId, const BucketStateWrapper &itr) const; BucketMoveSet computeBuckets2Move(const bucketdb::Guard & guard); BucketMoverSP createMover(BucketId bucket, bool wantReady); BucketMoverSP greedyCreateMover(); diff --git a/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp b/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp index 3fdf82ea61d..783282b71c1 100644 --- a/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp @@ -1025,11 +1025,12 @@ notifyBucketsChanged(const documentmetastore::IBucketHandler &metaStore, IBucketModifiedHandler &handler, const vespalib::string &name) { - bucketdb::Guard buckets = metaStore.getBucketDB().takeGuard(); - for (const auto &kv : *buckets) { - handler.notifyBucketModified(kv.first); + bucketdb::Guard guard = metaStore.getBucketDB().takeGuard(); + document::BucketId::List buckets = guard->getBuckets(); + for (document::BucketId bucketId : buckets) { + handler.notifyBucketModified(bucketId); } - LOG(debug, "notifyBucketsChanged(%s, %zu)", name.c_str(), buckets->size()); + LOG(debug, "notifyBucketsChanged(%s, %zu)", name.c_str(), buckets.size()); } } diff --git a/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.cpp b/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.cpp index 207f1d813d8..7a78b4ba82a 100644 --- a/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.cpp @@ -34,7 +34,7 @@ SearchableFeedView::SearchableFeedView(StoreOnlyFeedView::Context storeOnlyCtx, const FastAccessFeedView::Context &fastUpdateCtx, Context ctx) : Parent(std::move(storeOnlyCtx), params, fastUpdateCtx), _indexWriter(ctx._indexWriter), - _hasIndexedFields(_schema->getNumIndexFields() > 0) + _hasIndexedFields(getSchema()->getNumIndexFields() > 0) { } SearchableFeedView::~SearchableFeedView() = default; diff --git a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp index a537742b79b..a9850b5c2b7 100644 --- a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp @@ -7,14 +7,15 @@ #include "putdonecontext.h" #include "removedonecontext.h" #include "updatedonecontext.h" -#include <vespa/document/datatype/documenttype.h> -#include <vespa/document/fieldvalue/document.h> -#include <vespa/document/repo/documenttyperepo.h> #include <vespa/searchcore/proton/attribute/ifieldupdatecallback.h> #include <vespa/searchcore/proton/common/feedtoken.h> #include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchcore/proton/reference/i_gid_to_lid_change_handler.h> #include <vespa/searchcore/proton/reference/i_pending_gid_to_lid_changes.h> +#include <vespa/searchlib/index/uri_field.h> +#include <vespa/document/repo/documenttyperepo.h> +#include <vespa/document/datatype/documenttype.h> +#include <vespa/document/fieldvalue/document.h> #include <vespa/vespalib/util/cpu_usage.h> #include <vespa/vespalib/util/destructor_callbacks.h> #include <vespa/vespalib/util/exceptions.h> @@ -38,7 +39,7 @@ using vespalib::CpuUsage; using vespalib::IDestructorCallback; using vespalib::IllegalStateException; using vespalib::makeLambdaTask; -using vespalib::make_string; +using vespalib::make_string_short::fmt; namespace proton { @@ -88,8 +89,8 @@ SummaryPutDoneContext::SummaryPutDoneContext(FeedToken token, IPendingLidTracker SummaryPutDoneContext::~SummaryPutDoneContext() = default; -std::vector<document::GlobalId> getGidsToRemove(const IDocumentMetaStore &metaStore, - const LidVectorContext::LidVector &lidsToRemove) +std::vector<document::GlobalId> +getGidsToRemove(const IDocumentMetaStore &metaStore, const LidVectorContext::LidVector &lidsToRemove) { std::vector<document::GlobalId> gids; gids.reserve(lidsToRemove.size()); @@ -102,23 +103,24 @@ std::vector<document::GlobalId> getGidsToRemove(const IDocumentMetaStore &metaSt return gids; } -void putMetaData(documentmetastore::IStore &meta_store, const DocumentId & doc_id, - const DocumentOperation &op, bool is_removed_doc) +void +putMetaData(documentmetastore::IStore &meta_store, const DocumentId & doc_id, + const DocumentOperation &op, bool is_removed_doc) { documentmetastore::IStore::Result putRes( meta_store.put(doc_id.getGlobalId(), op.getBucketId(), op.getTimestamp(), op.getSerializedDocSize(), op.getLid(), op.get_prepare_serial_num())); if (!putRes.ok()) { - throw IllegalStateException( - make_string("Could not put <lid, gid> pair for %sdocument with id '%s' and gid '%s'", - is_removed_doc ? "removed " : "", doc_id.toString().c_str(), - doc_id.getGlobalId().toString().c_str())); + throw IllegalStateException(fmt("Could not put <lid, gid> pair for %sdocument with id '%s' and gid '%s'", + is_removed_doc ? "removed " : "", doc_id.toString().c_str(), + doc_id.getGlobalId().toString().c_str())); } assert(op.getLid() == putRes._lid); } -void removeMetaData(documentmetastore::IStore &meta_store, const GlobalId & gid, const DocumentId &doc_id, - const DocumentOperation &op, bool is_removed_doc) +void +removeMetaData(documentmetastore::IStore &meta_store, const GlobalId & gid, const DocumentId &doc_id, + const DocumentOperation &op, bool is_removed_doc) { assert(meta_store.validLid(op.getPrevLid())); assert(is_removed_doc == op.getPrevMarkedAsRemoved()); @@ -127,9 +129,8 @@ void removeMetaData(documentmetastore::IStore &meta_store, const GlobalId & gid, (void) meta; if (!meta_store.remove(op.getPrevLid(), op.get_prepare_serial_num())) { throw IllegalStateException( - make_string("Could not remove <lid, gid> pair for %sdocument with id '%s' and gid '%s'", - is_removed_doc ? "removed " : "", doc_id.toString().c_str(), - gid.toString().c_str())); + fmt("Could not remove <lid, gid> pair for %sdocument with id '%s' and gid '%s'", + is_removed_doc ? "removed " : "", doc_id.toString().c_str(), gid.toString().c_str())); } } @@ -147,6 +148,37 @@ moveMetaData(documentmetastore::IStore &meta_store, const DocumentId & doc_id, c meta_store.move(op.getPrevLid(), op.getLid(), op.get_prepare_serial_num()); } +class UpdateScope final : public IFieldUpdateCallback +{ +private: + const vespalib::hash_set<int32_t> & _indexedFields; + bool _nonAttributeFields; +public: + bool _hasIndexedFields; + + UpdateScope(const vespalib::hash_set<int32_t> & indexedFields, const DocumentUpdate & upd); + bool hasIndexOrNonAttributeFields() const { + return _hasIndexedFields || _nonAttributeFields; + } + void onUpdateField(const document::Field & field, const search::AttributeVector * attr) override; +}; + +UpdateScope::UpdateScope(const vespalib::hash_set<int32_t> & indexedFields, const DocumentUpdate & upd) + : _indexedFields(indexedFields), + _nonAttributeFields(!upd.getFieldPathUpdates().empty()), + _hasIndexedFields(false) +{} + +void +UpdateScope::onUpdateField(const document::Field & field, const search::AttributeVector * attr) { + if (!_nonAttributeFields && (attr == nullptr || !attr->isUpdateableInMemoryOnly())) { + _nonAttributeFields = true; + } + if (!_hasIndexedFields && (_indexedFields.find(field.getId()) != _indexedFields.end())) { + _hasIndexedFields = true; + } +} + } // namespace StoreOnlyFeedView::StoreOnlyFeedView(Context ctx, const PersistentParams ¶ms) @@ -160,12 +192,26 @@ StoreOnlyFeedView::StoreOnlyFeedView(Context ctx, const PersistentParams ¶ms _pendingLidsForDocStore(), _pendingLidsForCommit(std::move(ctx._pendingLidsForCommit)), _schema(std::move(ctx._schema)), + _indexedFields(), _writeService(ctx._writeService), _params(params), _metaStore(_documentMetaStoreContext->get()), _gidToLidChangeHandler(ctx._gidToLidChangeHandler) { _docType = _repo->getDocumentType(_params._docTypeName.getName()); + if (_schema && _docType) { + for (const auto &indexField : _schema->getIndexFields()) { + size_t dotPos = indexField.getName().find('.'); + if ((dotPos == vespalib::string::npos) || search::index::UriField::mightBePartofUri(indexField.getName())) { + document::FieldPath fieldPath; + _docType->buildFieldPath(fieldPath, indexField.getName().substr(0, dotPos)); + _indexedFields.insert(fieldPath.back().getFieldRef().getId()); + } else { + throw IllegalStateException("Field '%s' is not a valid index name", indexField.getName().c_str()); + } + + } + } } StoreOnlyFeedView::~StoreOnlyFeedView() = default; @@ -207,7 +253,7 @@ void StoreOnlyFeedView::putAttributes(SerialNum, Lid, const Document &, OnPutDoneType) {} void -StoreOnlyFeedView::putIndexedFields(SerialNum, Lid, const Document::SP &, OnOperationDoneType) {} +StoreOnlyFeedView::putIndexedFields(SerialNum, Lid, const std::shared_ptr<Document> &, OnOperationDoneType) {} void StoreOnlyFeedView::preparePut(PutOperation &putOp) @@ -285,7 +331,7 @@ StoreOnlyFeedView::updateAttributes(SerialNum, Lid, const DocumentUpdate & upd, OnOperationDoneType, IFieldUpdateCallback & onUpdate) { for (const auto & fieldUpdate : upd.getUpdates()) { - onUpdate.onUpdateField(fieldUpdate.getField().getName(), nullptr); + onUpdate.onUpdateField(fieldUpdate.getField(), nullptr); } } @@ -387,22 +433,6 @@ StoreOnlyFeedView::heartBeatSummary(SerialNum serialNum, DoneCallback onDone) { })); } -StoreOnlyFeedView::UpdateScope::UpdateScope(const search::index::Schema & schema, const DocumentUpdate & upd) - : _schema(&schema), - _indexedFields(false), - _nonAttributeFields(!upd.getFieldPathUpdates().empty()) -{} - -void -StoreOnlyFeedView::UpdateScope::onUpdateField(vespalib::stringref fieldName, const search::AttributeVector * attr) { - if (!_nonAttributeFields && (attr == nullptr || !attr->isUpdateableInMemoryOnly())) { - _nonAttributeFields = true; - } - if (!_indexedFields && _schema->isIndexField(fieldName)) { - _indexedFields = true; - } -} - void StoreOnlyFeedView::internalUpdate(FeedToken token, const UpdateOperation &updOp) { if ( ! updOp.getUpdate()) { @@ -432,7 +462,7 @@ StoreOnlyFeedView::internalUpdate(FeedToken token, const UpdateOperation &updOp) } auto onWriteDone = createUpdateDoneContext(std::move(token), get_pending_lid_token(updOp), updOp.getUpdate()); - UpdateScope updateScope(*_schema, upd); + UpdateScope updateScope(_indexedFields, upd); updateAttributes(serialNum, lid, upd, onWriteDone, updateScope); if (updateScope.hasIndexOrNonAttributeFields()) { @@ -440,7 +470,7 @@ StoreOnlyFeedView::internalUpdate(FeedToken token, const UpdateOperation &updOp) FutureDoc futureDoc = promisedDoc.get_future().share(); onWriteDone->setDocument(futureDoc); _pendingLidsForDocStore.waitComplete(lid); - if (updateScope._indexedFields) { + if (updateScope._hasIndexedFields) { updateIndexedFields(serialNum, lid, futureDoc, onWriteDone); } PromisedStream promisedStream; diff --git a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h index 2822aa70525..25a98da7ce7 100644 --- a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h +++ b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h @@ -9,7 +9,6 @@ #include "searchcontext.h" #include <vespa/searchcore/proton/common/pendinglidtracker.h> #include <vespa/searchcore/proton/common/doctypename.h> -#include <vespa/searchcore/proton/attribute/ifieldupdatecallback.h> #include <vespa/searchcore/proton/common/feeddebugger.h> #include <vespa/searchcore/proton/documentmetastore/documentmetastore.h> #include <vespa/searchcore/proton/documentmetastore/documentmetastorecontext.h> @@ -18,9 +17,10 @@ #include <vespa/searchcore/proton/persistenceengine/resulthandler.h> #include <vespa/searchcorespi/index/ithreadingservice.h> #include <vespa/searchlib/query/base.h> +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/vespalib/util/threadstackexecutorbase.h> +#include <vespa/vespalib/stllike/hash_set.h> #include <future> -#include <vespa/searchcore/proton/feedoperation/operations.h> namespace vespalib { class IDestructorCallback; } @@ -118,22 +118,6 @@ public: {} }; -protected: - class UpdateScope : public IFieldUpdateCallback - { - private: - const search::index::Schema *_schema; - public: - bool _indexedFields; - bool _nonAttributeFields; - - UpdateScope(const search::index::Schema & schema, const DocumentUpdate & upd); - bool hasIndexOrNonAttributeFields() const { - return _indexedFields || _nonAttributeFields; - } - void onUpdateField(vespalib::stringref fieldName, const search::AttributeVector * attr) override; - }; - private: const ISummaryAdapter::SP _summaryAdapter; const IDocumentMetaStoreContext::SP _documentMetaStoreContext; @@ -142,9 +126,9 @@ private: LidReuseDelayer _lidReuseDelayer; PendingLidTracker _pendingLidsForDocStore; std::shared_ptr<PendingLidTrackerBase> _pendingLidsForCommit; - + const search::index::Schema::SP _schema; + vespalib::hash_set<int32_t> _indexedFields; protected: - const search::index::Schema::SP _schema; searchcorespi::index::IThreadingService &_writeService; PersistentParams _params; IDocumentMetaStore &_metaStore; diff --git a/searchcore/src/vespa/searchcore/proton/test/dummy_document_store.h b/searchcore/src/vespa/searchcore/proton/test/dummy_document_store.h index 9e0e8f66dc0..d8d6e119d9b 100644 --- a/searchcore/src/vespa/searchcore/proton/test/dummy_document_store.h +++ b/searchcore/src/vespa/searchcore/proton/test/dummy_document_store.h @@ -11,7 +11,7 @@ struct DummyDocumentStore : public search::IDocumentStore vespalib::string _baseDir; DummyDocumentStore() = default; - DummyDocumentStore(const vespalib::string &baseDir) + DummyDocumentStore(const vespalib::string &baseDir) noexcept : _baseDir(baseDir) {} ~DummyDocumentStore() = default; diff --git a/searchcore/src/vespa/searchcore/proton/test/dummy_summary_manager.h b/searchcore/src/vespa/searchcore/proton/test/dummy_summary_manager.h index 4d3513c52f5..f826cbbe921 100644 --- a/searchcore/src/vespa/searchcore/proton/test/dummy_summary_manager.h +++ b/searchcore/src/vespa/searchcore/proton/test/dummy_summary_manager.h @@ -9,7 +9,7 @@ namespace test { struct DummySummaryManager : public ISummaryManager { - virtual ISummarySetup::SP + ISummarySetup::SP createSummarySetup(const vespa::config::search::SummaryConfig &, const vespa::config::search::SummarymapConfig &, const vespa::config::search::summary::JuniperrcConfig &, diff --git a/searchlib/src/tests/index/docbuilder/docbuilder_test.cpp b/searchlib/src/tests/index/docbuilder/docbuilder_test.cpp index 75cccb0d573..9f1027d0522 100644 --- a/searchlib/src/tests/index/docbuilder/docbuilder_test.cpp +++ b/searchlib/src/tests/index/docbuilder/docbuilder_test.cpp @@ -13,8 +13,7 @@ LOG_SETUP("docbuilder_test"); using namespace document; using search::index::schema::CollectionType; -namespace search { -namespace index { +namespace search::index { namespace { @@ -26,15 +25,8 @@ namespace linguistics const vespalib::string SPANTREE_NAME("linguistics"); } -class Test : public vespalib::TestApp { -private: - void testBuilder(); -public: - int Main() override; -}; -void -Test::testBuilder() +TEST("test docBuilder") { Schema s; s.addIndexField(Schema::IndexField("ia", schema::DataType::STRING)); @@ -415,7 +407,7 @@ Test::testBuilder() EXPECT_EQUAL("</af>", *itr++); EXPECT_EQUAL("</document>", *itr++); EXPECT_TRUE(itr == lines.end()); -#if 1 +#if 0 std::cout << "onedoc xml start -----" << std::endl << xml << std::endl << "-------" << std::endl; @@ -479,7 +471,7 @@ Test::testBuilder() expSpans.push_back(Span(15, 9)); expSpans.push_back(Span(15, 9)); ASSERT_TRUE(expSpans == spans); -#if 1 +#if 0 std::cout << "onedoc xml start -----" << std::endl << xml << std::endl << "-------" << std::endl; @@ -490,18 +482,21 @@ Test::testBuilder() } } -int -Test::Main() -{ - TEST_INIT("docbuilder_test"); - - testBuilder(); - - TEST_DONE(); +TEST("test if index names are valid uri parts") { + EXPECT_FALSE(UriField::mightBePartofUri("all")); + EXPECT_FALSE(UriField::mightBePartofUri("fragment")); + EXPECT_FALSE(UriField::mightBePartofUri(".all")); + EXPECT_FALSE(UriField::mightBePartofUri("all.b")); + EXPECT_TRUE(UriField::mightBePartofUri("b.all")); + EXPECT_TRUE(UriField::mightBePartofUri("b.scheme")); + EXPECT_TRUE(UriField::mightBePartofUri("b.host")); + EXPECT_TRUE(UriField::mightBePartofUri("b.port")); + EXPECT_TRUE(UriField::mightBePartofUri("b.hostname")); + EXPECT_TRUE(UriField::mightBePartofUri("b.path")); + EXPECT_TRUE(UriField::mightBePartofUri("b.query")); + EXPECT_TRUE(UriField::mightBePartofUri("b.fragment")); } } -} - -TEST_APPHOOK(search::index::Test); +TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp b/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp index 77cc7920ea8..0fef721a6fa 100644 --- a/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp +++ b/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp @@ -263,8 +263,11 @@ TEST_F("test Eager Matching Children", MockFixture(5)) { class IteratorChildrenVerifier : public search::test::IteratorChildrenVerifier { private: - SearchIterator::UP create(const std::vector<SearchIterator*> &children) const override { - std::vector<fef::TermFieldMatchData*> no_child_match; + SearchIterator::UP + create(const std::vector<SearchIterator*> &children) const override { + // This is a pragmatic and dirty workaround to make IteratorVerifier test + // not fail on unpack when accessing child match weights + std::vector<fef::TermFieldMatchData*> no_child_match(children.size(), &_tfmd); MatchData::UP no_match_data; return DotProductSearch::create(children, _tfmd, false, no_child_match, _weights, std::move(no_match_data)); } @@ -272,8 +275,9 @@ private: class WeightIteratorChildrenVerifier : public search::test::DwaIteratorChildrenVerifier { private: - SearchIterator::UP create(std::vector<DocumentWeightIterator> && children) const override { - return SearchIterator::UP(DotProductSearch::create(_tfmd, false, _weights, std::move(children))); + SearchIterator::UP + create(std::vector<DocumentWeightIterator> && children) const override { + return DotProductSearch::create(_tfmd, false, _weights, std::move(children)); } }; diff --git a/searchlib/src/vespa/searchlib/features/attributefeature.cpp b/searchlib/src/vespa/searchlib/features/attributefeature.cpp index 10cca2213e2..8afb5ec1f21 100644 --- a/searchlib/src/vespa/searchlib/features/attributefeature.cpp +++ b/searchlib/src/vespa/searchlib/features/attributefeature.cpp @@ -352,7 +352,7 @@ fef::FeatureExecutor & createAttributeExecutor(uint32_t numOutputs, const IAttributeVector *attribute, const vespalib::string &attrName, const vespalib::string &extraParam, vespalib::Stash &stash) { if (attribute == nullptr) { - Issue::report("attribute feature: The attribute vector '%s' was not found in the attribute manager, returning default values.", + Issue::report("attribute feature: The attribute vector '%s' was not found, returning default values.", attrName.c_str()); std::vector<feature_t> values(numOutputs, 0.0f); return stash.create<ValueExecutor>(values); @@ -440,7 +440,7 @@ createTensorAttributeExecutor(const IAttributeVector *attribute, const vespalib: vespalib::Stash &stash) { if (attribute == nullptr) { - Issue::report("attribute feature: The attribute vector '%s' was not found in the attribute manager." + Issue::report("attribute feature: The attribute vector '%s' was not found." " Returning empty tensor.", attrName.c_str()); return ConstantTensorExecutor::createEmpty(tensorType, stash); } diff --git a/searchlib/src/vespa/searchlib/features/attributematchfeature.cpp b/searchlib/src/vespa/searchlib/features/attributematchfeature.cpp index 51af40f19f2..a86a91fb4a8 100644 --- a/searchlib/src/vespa/searchlib/features/attributematchfeature.cpp +++ b/searchlib/src/vespa/searchlib/features/attributematchfeature.cpp @@ -342,7 +342,7 @@ AttributeMatchBlueprint::createExecutor(const IQueryEnvironment & env, vespalib: { const IAttributeVector * attribute = env.getAttributeContext().getAttribute(_params.attrInfo->name()); if (attribute == nullptr) { - Issue::report("attribute_match feature: The attribute vector '%s' was not found in the attribute manager.", _params.attrInfo->name().c_str()); + Issue::report("attribute_match feature: The attribute vector '%s' was not found.", _params.attrInfo->name().c_str()); std::vector<feature_t> values; values.push_back(0.0); // completeness values.push_back(0.0); // queryCompleteness diff --git a/searchlib/src/vespa/searchlib/features/distance_calculator_bundle.cpp b/searchlib/src/vespa/searchlib/features/distance_calculator_bundle.cpp index 90386dffd51..4b2d67c933d 100644 --- a/searchlib/src/vespa/searchlib/features/distance_calculator_bundle.cpp +++ b/searchlib/src/vespa/searchlib/features/distance_calculator_bundle.cpp @@ -79,13 +79,13 @@ resolve_attribute_for_field(const fef::IQueryEnvironment& env, } -DistanceCalculatorBundle::Element::Element(fef::TermFieldHandle handle_in) +DistanceCalculatorBundle::Element::Element(fef::TermFieldHandle handle_in) noexcept : handle(handle_in), calc() { } -DistanceCalculatorBundle::Element::Element(fef::TermFieldHandle handle_in, std::unique_ptr<search::tensor::DistanceCalculator> calc_in) +DistanceCalculatorBundle::Element::Element(fef::TermFieldHandle handle_in, std::unique_ptr<search::tensor::DistanceCalculator> calc_in) noexcept : handle(handle_in), calc(std::move(calc_in)) { diff --git a/searchlib/src/vespa/searchlib/features/distance_calculator_bundle.h b/searchlib/src/vespa/searchlib/features/distance_calculator_bundle.h index dd3fc521d96..35295c771a6 100644 --- a/searchlib/src/vespa/searchlib/features/distance_calculator_bundle.h +++ b/searchlib/src/vespa/searchlib/features/distance_calculator_bundle.h @@ -27,8 +27,8 @@ public: fef::TermFieldHandle handle; std::unique_ptr<search::tensor::DistanceCalculator> calc; Element(Element&& rhs) noexcept = default; // Needed as std::vector::reserve() is used. - Element(fef::TermFieldHandle handle_in); - Element(fef::TermFieldHandle handle_in, std::unique_ptr<search::tensor::DistanceCalculator> calc_in); + Element(fef::TermFieldHandle handle_in) noexcept; + Element(fef::TermFieldHandle handle_in, std::unique_ptr<search::tensor::DistanceCalculator> calc_in) noexcept; ~Element(); }; private: diff --git a/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp b/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp index ce7df5c9fb7..ef09f9734f1 100644 --- a/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp +++ b/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp @@ -555,7 +555,7 @@ createFromObject(const IAttributeVector * attribute, const fef::Anything & objec // TODO: Add support for creating executor for weighted set string / integer attribute // where the query vector is represented as an object instead of a string. Issue::report("dot_product feature: The attribute vector '%s' is NOT of type array<int/long/float/double>" - ", returning executor with default value.", attribute->getName().c_str()); + ", returning default value.", attribute->getName().c_str()); return stash.create<SingleZeroValueExecutor>(); } @@ -644,7 +644,7 @@ createFromString(const IAttributeVector * attribute, const Property & prop, vesp if (executor == nullptr) { Issue::report("dot_product feature: The attribute vector '%s' is not of type weighted set string/integer nor" - " array<int/long/float/double>, returning executor with default value.", attribute->getName().c_str()); + " array<int/long/float/double>, returning default value.", attribute->getName().c_str()); executor = &stash.create<SingleZeroValueExecutor>(); } return *executor; @@ -854,7 +854,7 @@ DotProductBlueprint::createExecutor(const IQueryEnvironment & env, vespalib::Sta attribute = upgradeIfNecessary(attribute, env); } if (attribute == nullptr) { - Issue::report("dot_product feature: The attribute vector '%s' was not found in the attribute manager, returning executor with default value.", + Issue::report("dot_product feature: The attribute vector '%s' was not found, returning default value.", getAttribute(env).c_str()); return stash.create<SingleZeroValueExecutor>(); } diff --git a/searchlib/src/vespa/searchlib/features/euclidean_distance_feature.cpp b/searchlib/src/vespa/searchlib/features/euclidean_distance_feature.cpp index d41bff62baa..1380d36bc55 100644 --- a/searchlib/src/vespa/searchlib/features/euclidean_distance_feature.cpp +++ b/searchlib/src/vespa/searchlib/features/euclidean_distance_feature.cpp @@ -99,7 +99,7 @@ EuclideanDistanceBlueprint::createExecutor(const IQueryEnvironment &env, vespali { const IAttributeVector * attribute = env.getAttributeContext().getAttribute(_attributeName); if (attribute == nullptr) { - Issue::report("euclidean_distance feature: The attribute vector '%s' was not found in the attribute manager, returning executor with default value.", + Issue::report("euclidean_distance feature: The attribute vector '%s' was not found, returning default value.", _attributeName.c_str()); return stash.create<SingleZeroValueExecutor>(); } @@ -114,7 +114,7 @@ EuclideanDistanceBlueprint::createExecutor(const IQueryEnvironment &env, vespali } } Issue::report("euclidean_distance feature: The attribute vector '%s' is NOT of type array<int/long/float/double>" - ", returning executor with default value.", attribute->getName().c_str()); + ", returning default value.", attribute->getName().c_str()); return stash.create<SingleZeroValueExecutor>(); } diff --git a/searchlib/src/vespa/searchlib/features/internal_max_reduce_prod_join_feature.cpp b/searchlib/src/vespa/searchlib/features/internal_max_reduce_prod_join_feature.cpp index 49d4149953a..875c8574029 100644 --- a/searchlib/src/vespa/searchlib/features/internal_max_reduce_prod_join_feature.cpp +++ b/searchlib/src/vespa/searchlib/features/internal_max_reduce_prod_join_feature.cpp @@ -169,7 +169,7 @@ selectExecutor(const IAttributeVector *attribute, V && vector, vespalib::Stash & } } Issue::report("intrinsic max_reduce_prod_join feature: The attribute vector '%s' is not of type " - "array<int/long>, returning executor with default value.", attribute->getName().c_str()); + "array<int/long>, returning default value.", attribute->getName().c_str()); return stash.create<SingleZeroValueExecutor>(); } @@ -253,8 +253,8 @@ InternalMaxReduceProdJoinBlueprint::createExecutor(const IQueryEnvironment &env, { const IAttributeVector * attribute = lookupAttribute(_attrKey, _attribute, env); if (attribute == nullptr) { - Issue::report("intrinsic max_reduce_prod_join feature: The attribute vector '%s' was not found in the attribute manager, " - "returning executor with default value.", _attribute.c_str()); + Issue::report("intrinsic max_reduce_prod_join feature: The attribute vector '%s' was not found, " + "returning default value.", _attribute.c_str()); return stash.create<SingleZeroValueExecutor>(); } const fef::Anything * queryVectorArg = env.getObjectStore().get(_queryVectorKey); diff --git a/searchlib/src/vespa/searchlib/features/tensor_from_labels_feature.cpp b/searchlib/src/vespa/searchlib/features/tensor_from_labels_feature.cpp index bbae87b2240..b72a75bd19f 100644 --- a/searchlib/src/vespa/searchlib/features/tensor_from_labels_feature.cpp +++ b/searchlib/src/vespa/searchlib/features/tensor_from_labels_feature.cpp @@ -61,7 +61,7 @@ createAttributeExecutor(const search::fef::IQueryEnvironment &env, { const IAttributeVector *attribute = env.getAttributeContext().getAttribute(attrName); if (attribute == NULL) { - Issue::report("tensor_from_labels feature: The attribute vector '%s' was not found in the attribute manager." + Issue::report("tensor_from_labels feature: The attribute vector '%s' was not found." " Returning empty tensor.", attrName.c_str()); return ConstantTensorExecutor::createEmpty(ValueType::make_type(CellType::DOUBLE, {{dimension}}), stash); } diff --git a/searchlib/src/vespa/searchlib/features/tensor_from_weighted_set_feature.cpp b/searchlib/src/vespa/searchlib/features/tensor_from_weighted_set_feature.cpp index 9db9f4616e3..cbe262a0cbd 100644 --- a/searchlib/src/vespa/searchlib/features/tensor_from_weighted_set_feature.cpp +++ b/searchlib/src/vespa/searchlib/features/tensor_from_weighted_set_feature.cpp @@ -75,7 +75,7 @@ createAttributeExecutor(const search::fef::IQueryEnvironment &env, { const IAttributeVector *attribute = env.getAttributeContext().getAttribute(attrName); if (attribute == NULL) { - Issue::report("tensor_from_weighted_set feature: The attribute vector '%s' was not found in the attribute manager." + Issue::report("tensor_from_weighted_set feature: The attribute vector '%s' was not found." " Returning empty tensor.", attrName.c_str()); return ConstantTensorExecutor::createEmpty(ValueType::make_type(CellType::DOUBLE, {{dimension}}), stash); } diff --git a/searchlib/src/vespa/searchlib/index/uri_field.cpp b/searchlib/src/vespa/searchlib/index/uri_field.cpp index 380f67210d3..070afc94837 100644 --- a/searchlib/src/vespa/searchlib/index/uri_field.cpp +++ b/searchlib/src/vespa/searchlib/index/uri_field.cpp @@ -18,9 +18,7 @@ UriField::UriField() } bool -UriField::valid(const Schema &schema, - uint32_t fieldId, - const Schema::CollectionType &collectionType) +UriField::valid(const Schema &schema, uint32_t fieldId, const Schema::CollectionType &collectionType) { if (fieldId == Schema::UNKNOWN_FIELD_ID) { return false; @@ -36,9 +34,7 @@ UriField::valid(const Schema &schema, } bool -UriField::broken(const Schema &schema, - const Schema::CollectionType & - collectionType) const +UriField::broken(const Schema &schema, const Schema::CollectionType & collectionType) const { return !valid(schema, _all, collectionType) && valid(schema, _scheme, collectionType) && @@ -50,9 +46,7 @@ UriField::broken(const Schema &schema, } bool -UriField::valid(const Schema &schema, - const Schema::CollectionType & - collectionType) const +UriField::valid(const Schema &schema, const Schema::CollectionType & collectionType) const { return valid(schema, _all, collectionType) && valid(schema, _scheme, collectionType) && @@ -64,8 +58,7 @@ UriField::valid(const Schema &schema, } void -UriField::setup(const Schema &schema, - const vespalib::string &field) +UriField::setup(const Schema &schema, const vespalib::string &field) { _all = schema.getIndexFieldId(field); _scheme = schema.getIndexFieldId(field + ".scheme"); @@ -77,9 +70,19 @@ UriField::setup(const Schema &schema, _hostname = schema.getIndexFieldId(field + ".hostname"); } +bool +UriField::mightBePartofUri(vespalib::stringref name) { + size_t dotPos = name.find('.'); + if ((dotPos != 0) && (dotPos != vespalib::string::npos)) { + vespalib::stringref suffix = name.substr(dotPos + 1); + return ((suffix == "all") || (suffix == "scheme") || (suffix == "host") || (suffix == "port") || + (suffix == "path") || (suffix == "query") || (suffix == "fragment") || (suffix == "hostname")); + } + return false; +} + void -UriField::markUsed(UsedFieldsMap &usedFields, - uint32_t field) +UriField::markUsed(UsedFieldsMap &usedFields, uint32_t field) { if (field == Schema::UNKNOWN_FIELD_ID) { return; diff --git a/searchlib/src/vespa/searchlib/index/uri_field.h b/searchlib/src/vespa/searchlib/index/uri_field.h index 9b8e4e72b7c..70bf8c01a8c 100644 --- a/searchlib/src/vespa/searchlib/index/uri_field.h +++ b/searchlib/src/vespa/searchlib/index/uri_field.h @@ -35,6 +35,7 @@ public: bool valid(const Schema &schema, const Schema::CollectionType &collectionType) const; void setup(const Schema &schema, const vespalib::string &field); void markUsed(UsedFieldsMap &usedFields) const; + static bool mightBePartofUri(vespalib::stringref name); }; } diff --git a/searchlib/src/vespa/searchlib/queryeval/dot_product_search.cpp b/searchlib/src/vespa/searchlib/queryeval/dot_product_search.cpp index 393140784b0..34cc343b16d 100644 --- a/searchlib/src/vespa/searchlib/queryeval/dot_product_search.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/dot_product_search.cpp @@ -169,9 +169,9 @@ DotProductSearch::create(const std::vector<SearchIterator*> &children, *childMatch[0], weights[0], std::move(md)); } if (childMatch.size() < 128) { - return SearchIterator::UP(new ArrayHeapImpl(tmd, field_is_filter, weights, SearchIteratorPack(children, childMatch, std::move(md)))); + return std::make_unique<ArrayHeapImpl>(tmd, field_is_filter, weights, SearchIteratorPack(children, childMatch, std::move(md))); } - return SearchIterator::UP(new HeapImpl(tmd, field_is_filter, weights, SearchIteratorPack(children, childMatch, std::move(md)))); + return std::make_unique<HeapImpl>(tmd, field_is_filter, weights, SearchIteratorPack(children, childMatch, std::move(md))); } //----------------------------------------------------------------------------- @@ -186,9 +186,9 @@ DotProductSearch::create(TermFieldMatchData &tmd, typedef DotProductSearchImpl<vespalib::LeftHeap, AttributeIteratorPack> HeapImpl; if (iterators.size() < 128) { - return SearchIterator::UP(new ArrayHeapImpl(tmd, field_is_filter, weights, AttributeIteratorPack(std::move(iterators)))); + return std::make_unique<ArrayHeapImpl>(tmd, field_is_filter, weights, AttributeIteratorPack(std::move(iterators))); } - return SearchIterator::UP(new HeapImpl(tmd, field_is_filter, weights, AttributeIteratorPack(std::move(iterators)))); + return std::make_unique<HeapImpl>(tmd, field_is_filter, weights, AttributeIteratorPack(std::move(iterators))); } //----------------------------------------------------------------------------- diff --git a/searchlib/src/vespa/searchlib/test/initrange.cpp b/searchlib/src/vespa/searchlib/test/initrange.cpp index 5154a8abb08..d082bfd4e78 100644 --- a/searchlib/src/vespa/searchlib/test/initrange.cpp +++ b/searchlib/src/vespa/searchlib/test/initrange.cpp @@ -72,7 +72,7 @@ InitRangeVerifier::InitRangeVerifier() : } } -InitRangeVerifier::~InitRangeVerifier() { } +InitRangeVerifier::~InitRangeVerifier() = default; InitRangeVerifier::DocIds InitRangeVerifier::invert(const DocIds & docIds, uint32_t docIdlimit) @@ -173,6 +173,7 @@ InitRangeVerifier::searchRelaxed(SearchIterator & it, Range range) for (uint32_t docid = range.first; docid < range.second; ++docid) { if (it.seek(docid)) { result.emplace_back(docid); + it.unpack(docid); } } return result; @@ -185,6 +186,7 @@ InitRangeVerifier::searchStrict(SearchIterator & it, Range range) it.initRange(range.first, range.second); for (uint32_t docId = it.seekFirst(range.first); docId < range.second; docId = it.seekNext(docId + 1)) { result.push_back(docId); + it.unpack(docId); } return result; } diff --git a/searchsummary/src/tests/juniper/auxTest.cpp b/searchsummary/src/tests/juniper/auxTest.cpp index 15f5ad1749e..c42cf4ccd83 100644 --- a/searchsummary/src/tests/juniper/auxTest.cpp +++ b/searchsummary/src/tests/juniper/auxTest.cpp @@ -136,15 +136,14 @@ AuxTest::TestDoubleWidth() juniper::QueryParser q("\xef\xbd\x93\xef\xbd\x8f\xef\xbd\x8e\xef\xbd\x99"); juniper::QueryHandle qh(q, nullptr, juniper.getModifier()); - juniper::Result* res = juniper::Analyse(&myConfig, &qh, - input, 17, 0, 0, 0); - _test(res != nullptr); + auto res = juniper::Analyse(myConfig, qh, + input, 17, 0, 0, 0); + _test(static_cast<bool>(res)); - juniper::Summary* sum = juniper::GetTeaser(res, nullptr); + juniper::Summary* sum = juniper::GetTeaser(*res, nullptr); (void) sum; // this should work // _test(sum->Length() != 0); - juniper::ReleaseResult(res); } @@ -175,17 +174,15 @@ AuxTest::TestPartialUTF8() juniper::QueryParser q("ipod"); juniper::QueryHandle qh(q, nullptr, juniper.getModifier()); - juniper::Result* res = juniper::Analyse(&myConfig, &qh, - input, inputSize, 0, 0, 0); - _test(res != nullptr); + auto res = juniper::Analyse(myConfig, qh, + input, inputSize, 0, 0, 0); + _test(static_cast<bool>(res)); - juniper::Summary* sum = juniper::GetTeaser(res, nullptr); + juniper::Summary* sum = juniper::GetTeaser(*res, nullptr); _test(sum->Length() != 0); // check for partial/broken utf-8 _test(countBrokenUTF8(sum->Text(), sum->Length()) == 0); - - juniper::ReleaseResult(res); } void AuxTest::TestLargeBlockChinese() @@ -215,11 +212,11 @@ void AuxTest::TestLargeBlockChinese() juniper::QueryParser q("希望"); juniper::QueryHandle qh(q, nullptr, juniper.getModifier()); - juniper::Result* res = juniper::Analyse(&myConfig, &qh, - input, inputSize, 0, 0, 0); - _test(res != nullptr); + auto res = juniper::Analyse(myConfig, qh, + input, inputSize, 0, 0, 0); + _test(static_cast<bool>(res)); - juniper::Summary* sum = juniper::GetTeaser(res, nullptr); + juniper::Summary* sum = juniper::GetTeaser(*res, nullptr); _test(sum->Length() != 0); // check that the entire block of chinese data is not returned in the summary @@ -227,8 +224,6 @@ void AuxTest::TestLargeBlockChinese() // check for partial/broken utf-8 _test(countBrokenUTF8(sum->Text(), sum->Length()) == 0); - - juniper::ReleaseResult(res); } void AuxTest::TestExample() @@ -241,17 +236,14 @@ void AuxTest::TestExample() "&%#%&! cries the sleepy monkey and jumps down from the tree." "the last token here is split across lines consumed"; int content_len = strlen(content); - juniper::Result* res = - juniper::Analyse(juniper::TestConfig, - &qh, - content, content_len, - 0, 0, 0); - _test(res != nullptr); + auto res = juniper::Analyse(*juniper::TestConfig, qh, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); res->Scan(); Matcher& m = *res->_matcher; _test(m.TotalMatchCnt(0) == 2 && m.ExactMatchCnt(0) == 0); - juniper::ReleaseResult(res); } @@ -410,8 +402,8 @@ void AuxTest::TestUTF8context() s.append(char_from_u8(u8" beste forekomst av s\u00f8ket med s\u00f8kemotor til brukeren blir det enda bedre. ")); s.append(char_from_u8(u8"Hvis bare UTF8-kodingen virker som den skal for tegn som tar mer enn \u00e9n byte.")); - juniper::Result* res = juniper::Analyse(juniper::TestConfig, &qh, s.c_str(), s.size(), 0, 0, 0); - _test(res != nullptr); + auto res = juniper::Analyse(*juniper::TestConfig, qh, s.c_str(), s.size(), 0, 0, 0); + _test(static_cast<bool>(res)); size_t charsize; Matcher& m = *res->_matcher; @@ -454,7 +446,6 @@ void AuxTest::TestUTF8context() test_dump(s.c_str(), s.size()); m.dump_statistics(); } - juniper::ReleaseResult(res); } @@ -491,10 +482,10 @@ void AuxTest::TestJapanese() const char* content = testjap[i].text; int content_len = strlen(content); - juniper::Result* res = juniper::Analyse(juniper::TestConfig, &qh, - content, content_len, - 0, 0, 0); - _test(res != nullptr); + auto res = juniper::Analyse(*juniper::TestConfig, qh, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); size_t charsize; Matcher& m = *res->_matcher; @@ -545,7 +536,6 @@ void AuxTest::TestJapanese() default: break; } - juniper::ReleaseResult(res); DeleteSummaryDesc(sumdesc); DeleteSummaryConfig(_sumconf); } @@ -582,15 +572,14 @@ void AuxTest::TestStartHits() " In fact it must be much longer. And then som more text at the end. But this text at " "the end must be much longer than this to trigger the case"; int content_len = strlen(content); - juniper::Result* res = juniper::Analyse(juniper::TestConfig, &qh, - content, content_len, - 0, 0, 0); - _test(res != nullptr); + auto res = juniper::Analyse(*juniper::TestConfig, qh, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); - juniper::Summary* sum = juniper::GetTeaser(res, nullptr); + juniper::Summary* sum = juniper::GetTeaser(*res, nullptr); (void) sum; // TODO: ReEnable _test(sum->Length() != 0); - juniper::ReleaseResult(res); } @@ -607,14 +596,13 @@ void AuxTest::TestEndHit() "surround_len bytes closer than good towardstheend�����������������������������������"; size_t content_len = strlen(content) - 55; - juniper::Result* res = juniper::Analyse(juniper::TestConfig, &qh, - content, content_len, - 0, 0, 0); - _test(res != nullptr); + auto res = juniper::Analyse(*juniper::TestConfig, qh, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); - juniper::Summary* sum = juniper::GetTeaser(res, nullptr); + juniper::Summary* sum = juniper::GetTeaser(*res, nullptr); _test(sum->Length() != 0); - juniper::ReleaseResult(res); } void AuxTest::TestJuniperStack() @@ -880,14 +868,13 @@ AuxTest::TestWhiteSpacePreserved() juniper::QueryParser q("best"); juniper::QueryHandle qh(q, nullptr, juniper.getModifier()); - juniper::Result* res = juniper::Analyse(&myConfig, &qh, input.c_str(), input.size(), 0, 0, 0); - _test(res != nullptr); + auto res = juniper::Analyse(myConfig, qh, input.c_str(), input.size(), 0, 0, 0); + _test(static_cast<bool>(res)); - juniper::Summary* sum = juniper::GetTeaser(res, nullptr); + juniper::Summary* sum = juniper::GetTeaser(*res, nullptr); vespalib::string expected = "<hi>best</hi> of \nmetallica"; vespalib::string actual(sum->Text(), sum->Length()); _test(actual == expected); - juniper::ReleaseResult(res); } void AuxTest::Run(MethodContainer::iterator &itr) { diff --git a/searchsummary/src/tests/juniper/matchobjectTest.cpp b/searchsummary/src/tests/juniper/matchobjectTest.cpp index 07e3cf84767..d8b7724d8a5 100644 --- a/searchsummary/src/tests/juniper/matchobjectTest.cpp +++ b/searchsummary/src/tests/juniper/matchobjectTest.cpp @@ -28,10 +28,10 @@ void MatchObjectTest::testTerm() { size_t content_len = strlen(content); // Fetch a result descriptor: - Result* res = juniper::Analyse(juniper::TestConfig, &q._qhandle, - content, content_len, - 0, 0, 0); - _test(res != 0); + auto res = juniper::Analyse(*juniper::TestConfig, q._qhandle, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); // Do the scanning manually. This calls accept several times res->Scan(); @@ -42,51 +42,39 @@ void MatchObjectTest::testTerm() { _test(ms.size() == 2); - delete res; // printf("%d %d\n", m.TotalHits(),ms.size()); TestQuery q1("t*t"); TestQuery q2("*ea*"); TestQuery q3("*d"); TestQuery q4("*word"); - Result* r1 = juniper::Analyse(juniper::TestConfig, &q1._qhandle, content, content_len, 0, 0, 0); - Result* r2 = juniper::Analyse(juniper::TestConfig, &q2._qhandle, content, content_len, 0, 0, 0); - Result* r3 = juniper::Analyse(juniper::TestConfig, &q3._qhandle, content, content_len, 0, 0, 0); - Result* r4 = juniper::Analyse(juniper::TestConfig, &q4._qhandle, content, content_len, 0, 0, 0); - if (r1 != 0) - { + auto r1 = juniper::Analyse(*juniper::TestConfig, q1._qhandle, content, content_len, 0, 0, 0); + auto r2 = juniper::Analyse(*juniper::TestConfig, q2._qhandle, content, content_len, 0, 0, 0); + auto r3 = juniper::Analyse(*juniper::TestConfig, q3._qhandle, content, content_len, 0, 0, 0); + auto r4 = juniper::Analyse(*juniper::TestConfig, q4._qhandle, content, content_len, 0, 0, 0); + _test(static_cast<bool>(r1)); + if (r1) { r1->Scan(); _test(r1->_matcher->TotalHits() == 1); - delete r1; } - else - _test(r1 != 0); - - if (r2 != 0) - { + _test(static_cast<bool>(r2)); + if (r2) { r2->Scan(); _test(r2->_matcher->TotalHits() == 2); - delete r2; } - else - _test(r2 != 0); - if (r3 != 0) - { + if (r3) { r3->Scan(); _test(r3->_matcher->TotalHits() == 2); - delete r3; + } else { + _test(static_cast<bool>(r3)); } - else - _test(r3 != 0); - if (r4 != 0) - { + if (r4) { r4->Scan(); _test_equal(r4->_matcher->TotalHits(), 2); - delete r4; + } else { + _test(static_cast<bool>(r4)); } - else - _test(r4 != 0); } /** @@ -98,7 +86,7 @@ void MatchObjectTest::testMatch() { juniper::QueryHandle qh(p, NULL, juniper::_Juniper->getModifier()); MatchObject* mo = qh.MatchObj(0); - juniper::Result res(juniper::TestConfig, &qh, "", 0, 0); + juniper::Result res(*juniper::TestConfig, qh, "", 0, 0); unsigned opts = 0; match_iterator mi(mo, &res); ucs4_t ucs4_str[10]; @@ -140,7 +128,7 @@ void MatchObjectTest::testMatch() { "extremelylongwordhit,extremelylongwordhits,extremelylongwordhit," "extremelylongwordhit))"); QueryHandle& qh1(q._qhandle); - juniper::Result res1(juniper::TestConfig, &qh1, + juniper::Result res1(*juniper::TestConfig, qh1, doc.c_str(), doc.size(), 0); juniper::Summary* sum = res1.GetTeaser(NULL); std::string s(sum->Text()); @@ -165,7 +153,7 @@ void MatchObjectTest::testMatchAnnotated() { " stuff"; TestQuery q("AND(big,buy)"); QueryHandle &qh1(q._qhandle); - juniper::Result res1(juniper::TestConfig, &qh1, + juniper::Result res1(*juniper::TestConfig, qh1, doc, strlen(doc), 0); juniper::Summary *sum = res1.GetTeaser(NULL); std::string s(sum->Text()); @@ -205,7 +193,7 @@ void MatchObjectTest::testLangid() std::string doc("see if we can match b or c somewhere in this a3 doc. " "Note that we should not match b1 or c1 or a somewhere.."); - juniper::Result res(juniper::TestConfig, &qh, doc.c_str(), doc.size(),0); + juniper::Result res(*juniper::TestConfig, qh, doc.c_str(), doc.size(),0); juniper::Summary* sum = res.GetTeaser(NULL); std::string s(sum->Text()); @@ -218,7 +206,7 @@ void MatchObjectTest::testLangid() // Do another test with the same query handle (testing reuse of qh with rewriters) std::string doc("Try to run this on another doc just to see if b or c still can be" " matched with the same query handle"); - juniper::Result res(juniper::TestConfig, &qh, + juniper::Result res(*juniper::TestConfig, qh, doc.c_str(), doc.size(), 0); juniper::Summary* sum = res.GetTeaser(NULL); @@ -247,7 +235,7 @@ void MatchObjectTest::testCombined() { std::string doc("see if we can match a3 or c somewhere in this b doc. " "Note that we should not match b1 or c1 or a somewhere.."); - juniper::Result res(juniper::TestConfig, &qh, doc.c_str(), doc.size(), 0); + juniper::Result res(*juniper::TestConfig, qh, doc.c_str(), doc.size(), 0); juniper::Summary* sum = res.GetTeaser(NULL); std::string s(sum->Text()); diff --git a/searchsummary/src/tests/juniper/mcandTest.cpp b/searchsummary/src/tests/juniper/mcandTest.cpp index 5a465275a80..46bd4a5196f 100644 --- a/searchsummary/src/tests/juniper/mcandTest.cpp +++ b/searchsummary/src/tests/juniper/mcandTest.cpp @@ -41,24 +41,23 @@ void MatchCandidateTest::testLog() { TestQuery q(""); std::string content("Here we go hepp and then some words away hoi some silly text here"); - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content.c_str(), content.size(), - 0, 0, 0); - _test(res); // We get a result handle + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content.c_str(), content.size(), + 0, 0, 0); + _test(static_cast<bool>(res)); // We get a result handle _test(!res->_mo); // but it is empty - juniper::Summary* sum = juniper::GetTeaser(res); + juniper::Summary* sum = juniper::GetTeaser(*res); std::string s(sum->Text()); _test_equal(s, std::string("")); - long relevance = juniper::GetRelevancy(res); + long relevance = juniper::GetRelevancy(*res); _test_equal(relevance, PROXIMITYBOOST_NOCONSTRAINT_OFFSET); - sum = juniper::GetLog(res); + sum = juniper::GetLog(*res); s = sum->Text(); _test_equal(s, std::string("")); - juniper::ReleaseResult(res); } @@ -70,56 +69,52 @@ void MatchCandidateTest::testDump() { { TestQuery q("NEAR/1(hepp,hoi)"); - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content.c_str(), content.size(), - 0, 0, 0); - _test(res != NULL); - long relevance = juniper::GetRelevancy(res); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content.c_str(), content.size(), + 0, 0, 0); + _test(static_cast<bool>(res)); + long relevance = juniper::GetRelevancy(*res); // zero value since there are no hits and constraints are enabled.. _test_equal(relevance, 0); - juniper::ReleaseResult(res); } { TestQuery q("OR(NEAR/1(hepp,hoi),bananas)"); - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content.c_str(), content.size(), - 0, 0, 0); - _test(res != NULL); - long relevance = juniper::GetRelevancy(res); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content.c_str(), content.size(), + 0, 0, 0); + _test(static_cast<bool>(res)); + long relevance = juniper::GetRelevancy(*res); // Check that X_CONSTR propagates as intended _test_equal(relevance, 0); - juniper::ReleaseResult(res); } { TestQuery q("PHRASE(hepp,hoi)"); - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content.c_str(), content.size(), - 0, 0, 0); - _test(res != NULL); - long relevance = juniper::GetRelevancy(res); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content.c_str(), content.size(), + 0, 0, 0); + _test(static_cast<bool>(res)); + long relevance = juniper::GetRelevancy(*res); // constant value since there are no hits but this is // also not a constrained search.. _test_equal(relevance, PROXIMITYBOOST_NOCONSTRAINT_OFFSET); - juniper::ReleaseResult(res); } { TestQuery q("AND(hepp,hoi)"); - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content.c_str(), content.size(), - 0, 0, 0); - _test(res != NULL); - long relevance = juniper::GetRelevancy(res); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content.c_str(), content.size(), + 0, 0, 0); + _test(static_cast<bool>(res)); + long relevance = juniper::GetRelevancy(*res); // Relevance may change, but nice to discover such changes.. // The important is that we get a nonzero value here as a hit _test_equal(relevance, 4470); - juniper::ReleaseResult(res); } } @@ -135,11 +130,11 @@ void MatchCandidateTest::testorder() { size_t content_len = strlen(content); // Fetch a result descriptor: - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content, content_len, - 0, 0, 0); - _test(res != 0); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); // Do the scanning manually. Scan calls accept several times res->Scan(); @@ -150,7 +145,6 @@ void MatchCandidateTest::testorder() { match_candidate_set& ms = m.OrderedMatchSet(); _test(ms.size() == 1); - juniper::ReleaseResult(res); } @@ -165,11 +159,11 @@ void MatchCandidateTest::testMatches_limit() { size_t content_len = strlen(content); // Fetch a result descriptor: - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content, content_len, - 0, 0, 0); - _test(res != 0); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); // Do the scanning manually. This calls accept several times res->Scan(); @@ -182,11 +176,10 @@ void MatchCandidateTest::testMatches_limit() { _test(ms.size() == 2); // The first (complete) match and the second starting at "test" // Check if we get the correct teaser as well.. - juniper::Summary* sum = juniper::GetTeaser(res); + juniper::Summary* sum = juniper::GetTeaser(*res); _test(strcmp(sum->Text(), "This is a simple text where a <b>phrase</b> <b>match</b> can be found not" " quite adjacent to a <b>test</b> <b>word</b>") == 0); - juniper::ReleaseResult(res); } @@ -200,11 +193,11 @@ void MatchCandidateTest::testAccept() { size_t content_len = strlen(content); // Fetch a result descriptor: - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content, content_len, - 0, 0, 0); - _test(res != 0); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); // Do the scanning manually. This calls accept several times res->Scan(); @@ -218,7 +211,6 @@ void MatchCandidateTest::testAccept() { _test(ms.size() > 0); if (!ms.size()) { - juniper::ReleaseResult(res); return; // No point in continuing.. } @@ -234,10 +226,9 @@ void MatchCandidateTest::testAccept() { _test(mc._klist.size() == 2); // Two occurrence elements in list // Just for the sake of it, verify that we get a proper teaser out of this also.. - juniper::Summary* sum = juniper::GetTeaser(res); + juniper::Summary* sum = juniper::GetTeaser(*res); _test(strcmp(sum->Text(), "This is a <b>simple</b> <b>test</b> where we should get a perfect match") == 0); - juniper::ReleaseResult(res); } @@ -260,11 +251,11 @@ void MatchCandidateTest::testMake_keylist() { size_t content_len = strlen(content); // Fetch a result descriptor: - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content, content_len, - 0, 0, 0); - _test(res != 0); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); // Do the scanning manually. This calls accept several times res->Scan(); @@ -275,8 +266,6 @@ void MatchCandidateTest::testMake_keylist() { match_candidate_set& ms = m.OrderedMatchSet(); _test_equal(static_cast<size_t>(ms.size()), 6u); - - juniper::ReleaseResult(res); } @@ -291,11 +280,11 @@ void MatchCandidateTest::testAdd_to_keylist() { size_t content_len = strlen(content); // Fetch a result descriptor: - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content, content_len, - 0, 0, 0); - _test(res != 0); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); // Do the scanning manually. This calls accept several times res->Scan(); @@ -308,13 +297,12 @@ void MatchCandidateTest::testAdd_to_keylist() { _test_equal(static_cast<size_t>(ms.size()), 1u); // Single result // Bug triggered when result is fetched.. - juniper::Summary* sum = juniper::GetTeaser(res); + juniper::Summary* sum = juniper::GetTeaser(*res); std::string s(sum->Text()); _test_equal(s, "connect truende. <b>phr1</b> <b>phr2</b> www www www <b>phr3</b>" " <b>phr4</b> acuicola 8844"); - juniper::ReleaseResult(res); } @@ -331,11 +319,11 @@ void MatchCandidateTest::testLength() { TestQuery q("NEAR/4(pattern,NEAR/1(simple,with),NEAR/2(simple,adjacent))"); // Fetch a result descriptor: - Result* res = juniper::Analyse(juniper::TestConfig, &q._qhandle, - content, content_len, - 0, 0, 0); + auto res = juniper::Analyse(*juniper::TestConfig, q._qhandle, + content, content_len, + 0, 0, 0); - juniper::Summary* sum = juniper::GetTeaser(res); + juniper::Summary* sum = juniper::GetTeaser(*res); Matcher& m = *res->_matcher; match_candidate_set& ms = m.OrderedMatchSet(); _test_equal(static_cast<size_t>(ms.size()), 1u); @@ -345,7 +333,6 @@ void MatchCandidateTest::testLength() { "this <b>simple</b> text <b>with</b> <b>adjacent</b> words of " "a certain <b>pattern</b> must be matched according to specific" " rules to be detailed in this test."); - juniper::ReleaseResult(res); } { @@ -353,17 +340,16 @@ void MatchCandidateTest::testLength() { TestQuery q("ONEAR/4(pattern,NEAR/1(simple,with),NEAR/2(simple,adjacent))"); // Fetch a result descriptor: - Result* res = juniper::Analyse(juniper::TestConfig, - &q._qhandle - ,content, content_len, - 0, 0, 0); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle + ,content, content_len, + 0, 0, 0); res->Scan(); Matcher& m = *res->_matcher; match_candidate_set& ms = m.OrderedMatchSet(); _test_equal(static_cast<size_t>(ms.size()), 0u); - juniper::ReleaseResult(res); } { @@ -372,16 +358,14 @@ void MatchCandidateTest::testLength() { TestQuery q("NEAR/4(pattern,NEAR/1(simple,with),NEAR/1(simple,adjacent))"); // Fetch a result descriptor: - Result* res = juniper::Analyse(juniper::TestConfig, &q._qhandle, - content, content_len, - 0, 0, 0); + auto res = juniper::Analyse(*juniper::TestConfig, q._qhandle, + content, content_len, + 0, 0, 0); res->Scan(); Matcher& m = *res->_matcher; match_candidate_set& ms = m.OrderedMatchSet(); _test_equal(static_cast<size_t>(ms.size()), 0u); - - juniper::ReleaseResult(res); } } @@ -416,11 +400,11 @@ void MatchCandidateTest::requireThatMaxNumberOfMatchCandidatesCanBeControlled() const char *content = "re re re re foo re re re re bar re re re re foo re re re re bar"; size_t content_len = strlen(content); - Result *res = juniper::Analyse(juniper::TestConfig, - &q._qhandle, - content, content_len, - 0, 0, 0); - _test(res != 0); + auto res = juniper::Analyse(*juniper::TestConfig, + q._qhandle, + content, content_len, + 0, 0, 0); + _test(static_cast<bool>(res)); // Deflect tokens to my processor Matcher &m = *res->_matcher; @@ -435,8 +419,6 @@ void MatchCandidateTest::requireThatMaxNumberOfMatchCandidatesCanBeControlled() _test_equal(m.TotalHits(), 20); match_candidate_set& mcs = m.OrderedMatchSet(); _test_equal(static_cast<size_t>(mcs.size()), 2u); - - juniper::ReleaseResult(res); } diff --git a/searchsummary/src/vespa/juniper/Matcher.cpp b/searchsummary/src/vespa/juniper/Matcher.cpp index e286068038b..d580faae927 100644 --- a/searchsummary/src/vespa/juniper/Matcher.cpp +++ b/searchsummary/src/vespa/juniper/Matcher.cpp @@ -38,7 +38,7 @@ Matcher::Matcher(Result* result) : _log_text("") { _occ.reserve(KEY_OCC_RESERVED); - DocsumParams& dsp = _result->_config->_docsumparams; + const DocsumParams& dsp = _result->_config->_docsumparams; _winsize = _result->WinSize(); _winsizeFallback = static_cast<size_t>(_result->WinSizeFallbackMultiplier() * _winsize); _max_match_candidates = _result->MaxMatchCandidates(); diff --git a/searchsummary/src/vespa/juniper/juniperparams.cpp b/searchsummary/src/vespa/juniper/juniperparams.cpp index 4f25b2446ad..2ee0f3c31f6 100644 --- a/searchsummary/src/vespa/juniper/juniperparams.cpp +++ b/searchsummary/src/vespa/juniper/juniperparams.cpp @@ -108,18 +108,12 @@ MatcherParams& MatcherParams::SetWordFolder(Fast_WordFolder* wordfolder) return *this; } -Fast_WordFolder* MatcherParams::WordFolder() { return _wordfolder; } - - MatcherParams& MatcherParams::SetProximityFactor(double factor) { _proximity_factor = factor; return *this; } -double MatcherParams::ProximityFactor() { return _proximity_factor; } - - bool operator==(MatcherParams& mp1, MatcherParams& mp2) { return memcmp(&mp1, &mp2, sizeof(MatcherParams)) == 0; diff --git a/searchsummary/src/vespa/juniper/juniperparams.h b/searchsummary/src/vespa/juniper/juniperparams.h index f4f17779f2d..415c254b3f0 100644 --- a/searchsummary/src/vespa/juniper/juniperparams.h +++ b/searchsummary/src/vespa/juniper/juniperparams.h @@ -48,8 +48,10 @@ class MatcherParams { public: MatcherParams(); - MatcherParams(MatcherParams &) = delete; - MatcherParams &operator=(MatcherParams &) = delete; + MatcherParams(const MatcherParams&) = delete; + MatcherParams(MatcherParams&&) = delete; + MatcherParams &operator=(const MatcherParams&) = delete; + MatcherParams &operator=(MatcherParams&&) = delete; MatcherParams& SetMatchWindowSize(size_t winsize); size_t MatchWindowSize() const; @@ -66,10 +68,10 @@ public: size_t StemMaxExtend() const; MatcherParams& SetWordFolder(Fast_WordFolder* wordfolder); - Fast_WordFolder* WordFolder(); + const Fast_WordFolder* WordFolder() const noexcept { return _wordfolder; } MatcherParams& SetProximityFactor(double factor); - double ProximityFactor(); + double ProximityFactor() const noexcept { return _proximity_factor; }; private: size_t _match_winsize; diff --git a/searchsummary/src/vespa/juniper/result.cpp b/searchsummary/src/vespa/juniper/result.cpp index 15ad9aa2a98..18d91fcae8e 100644 --- a/searchsummary/src/vespa/juniper/result.cpp +++ b/searchsummary/src/vespa/juniper/result.cpp @@ -27,14 +27,14 @@ public: }; -Result::Result(Config* config, QueryHandle* qhandle, +Result::Result(const Config& config, QueryHandle& qhandle, const char* docsum, size_t docsum_len, uint32_t langid) : - _qhandle(qhandle), - _mo(qhandle->MatchObj(langid)), + _qhandle(&qhandle), + _mo(qhandle.MatchObj(langid)), _docsum(docsum), _docsum_len(docsum_len), _langid(langid), - _config(config), + _config(&config), _matcher(), _tokenizer(), _summaries(), @@ -50,8 +50,8 @@ Result::Result(Config* config, QueryHandle* qhandle, { if (!_mo) return; // The empty result.. - MatcherParams& mp = _config->_matcherparams; - Fast_WordFolder* wordfolder = mp.WordFolder(); + const MatcherParams& mp = _config->_matcherparams; + const Fast_WordFolder* wordfolder = mp.WordFolder(); if (_qhandle->_stem_min < 0) _stem_min = mp.StemMinLength(); @@ -87,8 +87,8 @@ Result::Result(Config* config, QueryHandle* qhandle, _registry = std::make_unique<SpecialTokenRegistry>(_matcher->getQuery()); - if (qhandle->_log_mask) - _matcher->set_log(qhandle->_log_mask); + if (qhandle._log_mask) + _matcher->set_log(qhandle._log_mask); _tokenizer->SetSuccessor(_matcher.get()); if (!_registry->getSpecialTokens().empty()) { @@ -157,7 +157,7 @@ Summary* Result::GetTeaser(const Config* alt_config) const char *src_end = _docsum + _docsum_len; ucs4_t *dst = buf; ucs4_t *dst_end = dst + TOKEN_DSTLEN; - Fast_WordFolder *folder = _config->_matcherparams.WordFolder(); + const Fast_WordFolder *folder = _config->_matcherparams.WordFolder(); text.reserve(_dynsum_len*2); if (src_end - src <= _dynsum_len) { diff --git a/searchsummary/src/vespa/juniper/result.h b/searchsummary/src/vespa/juniper/result.h index f0dcf3d4335..015291cb4ef 100644 --- a/searchsummary/src/vespa/juniper/result.h +++ b/searchsummary/src/vespa/juniper/result.h @@ -14,7 +14,7 @@ namespace juniper class Result { public: - Result(Config* config, QueryHandle* qhandle, + Result(const Config& config, QueryHandle& qhandle, const char* docsum, size_t docsum_len, uint32_t langid); ~Result(); @@ -42,7 +42,7 @@ public: const char* _docsum; size_t _docsum_len; uint32_t _langid; - Config* _config; + const Config* _config; std::unique_ptr<Matcher> _matcher; std::unique_ptr<SpecialTokenRegistry> _registry; std::unique_ptr<JuniperTokenizer> _tokenizer; diff --git a/searchsummary/src/vespa/juniper/rpinterface.cpp b/searchsummary/src/vespa/juniper/rpinterface.cpp index f9e91073a9b..32ea7759170 100644 --- a/searchsummary/src/vespa/juniper/rpinterface.cpp +++ b/searchsummary/src/vespa/juniper/rpinterface.cpp @@ -79,9 +79,9 @@ std::unique_ptr<Config> Juniper::CreateConfig(const char* config_name) return std::unique_ptr<Config>(new Config(config_name, *this)); } -QueryHandle* Juniper::CreateQueryHandle(const IQuery& fquery, const char* juniperoptions) +std::unique_ptr<QueryHandle> Juniper::CreateQueryHandle(const IQuery& fquery, const char* juniperoptions) { - return new QueryHandle(fquery, juniperoptions, *_modifier); + return std::make_unique<QueryHandle>(fquery, juniperoptions, *_modifier); } void Juniper::AddRewriter(const char* index_name, IRewriter* rewriter, bool for_query, bool for_document) @@ -95,44 +95,29 @@ void Juniper::FlushRewriters() } -void ReleaseQueryHandle(QueryHandle*& handle) -{ - delete handle; - handle = NULL; -} - - -Result* Analyse(const Config* config, QueryHandle* qhandle, +std::unique_ptr<Result> Analyse(const Config& config, QueryHandle& qhandle, const char* docsum, size_t docsum_len, uint32_t docid, uint32_t /* inputfield_id */, uint32_t langid) { LOG(debug, "juniper::Analyse(): docId(%u), docsumLen(%zu), docsum(%s), langId(%u)", docid, docsum_len, docsum, langid); - Result* res = new Result(const_cast<Config*>(config), qhandle, docsum, docsum_len, langid); - return res; -} - -long GetRelevancy(Result* result_handle) -{ - return result_handle->GetRelevancy(); + return std::make_unique<Result>(config, qhandle, docsum, docsum_len, langid); } -Summary* GetTeaser(Result* result_handle, const Config* alt_config) +long GetRelevancy(Result& result_handle) { - return result_handle->GetTeaser(alt_config); + return result_handle.GetRelevancy(); } -Summary* GetLog(Result* result_handle) +Summary* GetTeaser(Result& result_handle, const Config* alt_config) { - return result_handle->GetLog(); + return result_handle.GetTeaser(alt_config); } -void ReleaseResult(Result*& result_handle) +Summary* GetLog(Result& result_handle) { - LOG(debug, "juniper::ReleaseResult"); - delete result_handle; - result_handle = NULL; + return result_handle.GetLog(); } } // end namespace juniper diff --git a/searchsummary/src/vespa/juniper/rpinterface.h b/searchsummary/src/vespa/juniper/rpinterface.h index 6cda324ae5c..d4ef5c5ebed 100644 --- a/searchsummary/src/vespa/juniper/rpinterface.h +++ b/searchsummary/src/vespa/juniper/rpinterface.h @@ -120,9 +120,9 @@ public: * behaviour such as user customization of teaser parameters, selectively * enabling of Juniper debugging/tracing features and to support Juniper extensions * to the query language. - * @return An allocated handle to be subsequently released by ReleaseQueryHandle() + * @return A unique pointer to a QueryHandle. */ - QueryHandle* CreateQueryHandle(const IQuery& query, const char* juniperoptions); + std::unique_ptr<QueryHandle> CreateQueryHandle(const IQuery& query, const char* juniperoptions); /** Add an rewriter for all terms that are prefixed with the given index. * When Juniper encounter a term in the query tagged with this index, @@ -150,11 +150,6 @@ private: */ bool AnalyseCompatible(Config* conf1, Config* conf2); -/** Release a QueryHandle as previously allocated by CreateQueryHandle. - * @param handle The QueryHandle object to release - */ -void ReleaseQueryHandle(QueryHandle*& handle); - /** Perform initial content analysis on a query/content pair. * Note that the content may either be a simple UTF-8 encoded string or a * more advanced representation including document structure elements, as provided @@ -170,10 +165,9 @@ void ReleaseQueryHandle(QueryHandle*& handle); within the document that contains the provided document summary. * @param langid A unique 32 bit id representing the language which this document summary is to be analysed in context of. - * @return A pointer to an allocated handle to be used in subsequent specific result - * requests (must later be released with ReleaseResult()) + * @return A unique pointer to a Result */ -Result* Analyse(const Config* config, QueryHandle* query, +std::unique_ptr<Result> Analyse(const Config& config, QueryHandle& query, const char* docsum, size_t docsum_len, uint32_t docid, uint32_t inputfield_id, uint32_t langid); @@ -182,17 +176,16 @@ Result* Analyse(const Config* config, QueryHandle* query, * @param result_handle The result to retrieve from * @return The relevancy (proximitymetric) of the processed content. */ -long GetRelevancy(Result* result_handle); +long GetRelevancy(Result& result_handle); /** Generate a teaser based on the provided analysis result * @param result_handle a handle obtained by a previous call to Analyse * @param alt_config An optional alternate config to use for this teaser generation * The purpose of alt_config is to allow generation of multiple teasers * based on the same content and analysis. - * @return The generated Teaser object. This object is valid until ReleaseResult - * is called for result_handle + * @return The generated Teaser object. This object is valid until result_handle is deleted. */ -Summary* GetTeaser(Result* result_handle, const Config* alt_config = NULL); +Summary* GetTeaser(Result& result_handle, const Config* alt_config = NULL); /** Retrieve log information based on the previous calls to this result handle. * Note that for the log to be complete, the juniper log override entry in @@ -200,15 +193,9 @@ Summary* GetTeaser(Result* result_handle, const Config* alt_config = NULL); * @param result_handle a handle obtained by a previous call to Analyse. * @return value: a summary description containing the Juniper log as a text field * if any log information is available, or else an empty summary. - * This object is valid until ReleaseResult is called for result_handle - */ -Summary* GetLog(Result* result_handle); - -/** Release all resources associated with the handle given including the - * summaries created by this result handle. - * @param result_handle The handle to release + * This object is valid until result_handle is deleted. */ -void ReleaseResult(Result*& result_handle); +Summary* GetLog(Result& result_handle); } // end namespace juniper diff --git a/searchsummary/src/vespa/juniper/tokenizer.cpp b/searchsummary/src/vespa/juniper/tokenizer.cpp index db6e1ecfccd..9253f81cf25 100644 --- a/searchsummary/src/vespa/juniper/tokenizer.cpp +++ b/searchsummary/src/vespa/juniper/tokenizer.cpp @@ -7,7 +7,7 @@ #include <vespa/log/log.h> LOG_SETUP(".juniper.tokenizer"); -JuniperTokenizer::JuniperTokenizer(Fast_WordFolder* wordfolder, +JuniperTokenizer::JuniperTokenizer(const Fast_WordFolder* wordfolder, const char* text, size_t len, ITokenProcessor* successor, const juniper::SpecialTokenRegistry * registry) : _wordfolder(wordfolder), _text(text), _len(len), _successor(successor), _registry(registry), diff --git a/searchsummary/src/vespa/juniper/tokenizer.h b/searchsummary/src/vespa/juniper/tokenizer.h index 34ed1dba5bb..bf0c9452665 100644 --- a/searchsummary/src/vespa/juniper/tokenizer.h +++ b/searchsummary/src/vespa/juniper/tokenizer.h @@ -11,7 +11,7 @@ class Fast_WordFolder; class JuniperTokenizer { public: - JuniperTokenizer(Fast_WordFolder* wordfolder, + JuniperTokenizer(const Fast_WordFolder* wordfolder, const char* text, size_t len, ITokenProcessor* = NULL, const juniper::SpecialTokenRegistry * registry = NULL); inline void SetSuccessor(ITokenProcessor* successor) { _successor = successor; } @@ -22,7 +22,7 @@ public: // Scan the input and dispatch to the successor void scan(); private: - Fast_WordFolder* _wordfolder; + const Fast_WordFolder* _wordfolder; const char* _text; // The current input text size_t _len; // Length of the text input ITokenProcessor* _successor; diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumstate.cpp b/searchsummary/src/vespa/searchsummary/docsummary/docsumstate.cpp index 16575a2e9dc..9c810386703 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/docsumstate.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/docsumstate.cpp @@ -4,6 +4,7 @@ #include "docsum_field_writer_state.h" #include <vespa/juniper/rpinterface.h> #include <vespa/document/datatype/positiondatatype.h> +#include <vespa/juniper/queryhandle.h> #include <vespa/searchcommon/attribute/iattributecontext.h> #include <vespa/searchlib/common/geo_location.h> #include <vespa/searchlib/common/geo_location_parser.h> @@ -36,24 +37,10 @@ GetDocsumsState::GetDocsumsState(GetDocsumsStateCallback &callback) _rankFeatures(nullptr), _matching_elements() { - _dynteaser._docid = static_cast<uint32_t>(-1); - _dynteaser._input = static_cast<uint32_t>(-1); - _dynteaser._lang = static_cast<uint32_t>(-1); - _dynteaser._config = nullptr; - _dynteaser._query = nullptr; - _dynteaser._result = nullptr; } -GetDocsumsState::~GetDocsumsState() -{ - if (_dynteaser._result != nullptr) { - juniper::ReleaseResult(_dynteaser._result); - } - if (_dynteaser._query != nullptr) { - juniper::ReleaseQueryHandle(_dynteaser._query); - } -} +GetDocsumsState::~GetDocsumsState() = default; const MatchingElements & GetDocsumsState::get_matching_elements(const MatchingElementsFields &matching_elems_fields) diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumstate.h b/searchsummary/src/vespa/searchsummary/docsummary/docsumstate.h index 438a8a6d847..adcd47c098c 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/docsumstate.h +++ b/searchsummary/src/vespa/searchsummary/docsummary/docsumstate.h @@ -57,12 +57,7 @@ public: GetDocsumsStateCallback &_callback; struct DynTeaserState { - uint32_t _docid; // document id ('cache key') - uint32_t _input; // input field ('cache key') - uint32_t _lang; // lang field ('cache key') - juniper::Config *_config; // juniper config ('cache key') - juniper::QueryHandle *_query; // juniper query representation - juniper::Result *_result; // juniper analyze result + std::unique_ptr<juniper::QueryHandle> _query; // juniper query representation } _dynteaser; diff --git a/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp index 024046b679b..58dde39c336 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp @@ -9,6 +9,8 @@ #include <vespa/searchlib/queryeval/split_float.h> #include <vespa/vespalib/objects/hexdump.h> #include <vespa/juniper/config.h> +#include <vespa/juniper/queryhandle.h> +#include <vespa/juniper/result.h> #include <sstream> #include <vespa/log/log.h> @@ -368,51 +370,35 @@ DynamicTeaserDFW::getJuniperInput(GeneralResult *gres) { vespalib::string DynamicTeaserDFW::makeDynamicTeaser(uint32_t docid, vespalib::stringref input, GetDocsumsState *state) { - if (state->_dynteaser._query == nullptr) { + if (!state->_dynteaser._query) { JuniperQueryAdapter iq(state->_kwExtractor, state->_args.getStackDump(), &state->_args.highlightTerms()); state->_dynteaser._query = _juniper->CreateQueryHandle(iq, nullptr); } - if (docid != state->_dynteaser._docid || - _inputFieldEnumValue != state->_dynteaser._input || - _langFieldEnumValue != state->_dynteaser._lang || - !juniper::AnalyseCompatible(_juniperConfig.get(), state->_dynteaser._config)) { - LOG(debug, "makeDynamicTeaser: docid (%d,%d), fieldenum (%d,%d), lang (%d,%d) analyse %s", - docid, state->_dynteaser._docid, - _inputFieldEnumValue, state->_dynteaser._input, - _langFieldEnumValue, state->_dynteaser._lang, - (juniper::AnalyseCompatible(_juniperConfig.get(), state->_dynteaser._config) ? "no" : "yes")); - - if (state->_dynteaser._result != nullptr) - juniper::ReleaseResult(state->_dynteaser._result); - - state->_dynteaser._docid = docid; - state->_dynteaser._input = _inputFieldEnumValue; - state->_dynteaser._lang = _langFieldEnumValue; - state->_dynteaser._config = _juniperConfig.get(); - state->_dynteaser._result = nullptr; - - if (state->_dynteaser._query != nullptr) { - - if (LOG_WOULD_LOG(spam)) { - std::ostringstream hexDump; - hexDump << vespalib::HexDump(input.data(), input.length()); - LOG(spam, "makeDynamicTeaser: docid=%d, input='%s', hexdump:\n%s", - docid, std::string(input.data(), input.length()).c_str(), hexDump.str().c_str()); - } + LOG(debug, "makeDynamicTeaser: docid (%d), fieldenum (%d), lang (%d)", + docid, _inputFieldEnumValue, _langFieldEnumValue); + + std::unique_ptr<juniper::Result> result; - auto langid = static_cast<uint32_t>(-1); + if (state->_dynteaser._query != nullptr) { - state->_dynteaser._result = - juniper::Analyse(_juniperConfig.get(), state->_dynteaser._query, - input.data(), input.length(), docid, _inputFieldEnumValue, langid); + if (LOG_WOULD_LOG(spam)) { + std::ostringstream hexDump; + hexDump << vespalib::HexDump(input.data(), input.length()); + LOG(spam, "makeDynamicTeaser: docid=%d, input='%s', hexdump:\n%s", + docid, std::string(input.data(), input.length()).c_str(), hexDump.str().c_str()); } + + auto langid = static_cast<uint32_t>(-1); + + result = juniper::Analyse(*_juniperConfig, *state->_dynteaser._query, + input.data(), input.length(), docid, _inputFieldEnumValue, langid); } - juniper::Summary *teaser = (state->_dynteaser._result != nullptr) - ? juniper::GetTeaser(state->_dynteaser._result, _juniperConfig.get()) + juniper::Summary *teaser = result + ? juniper::GetTeaser(*result, _juniperConfig.get()) : nullptr; if (LOG_WOULD_LOG(debug)) { diff --git a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp index ddd2457ec49..c2bbf4d09da 100644 --- a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp +++ b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp @@ -936,7 +936,6 @@ SearchVisitor::handleDocument(StorageDocument & document) group(document.docDoc(), rp.getRankScore(), false); if (amongTheBest) { - document.saveCachedFields(); needToKeepDocument = true; } diff --git a/streamingvisitors/src/vespa/vsm/common/storagedocument.cpp b/streamingvisitors/src/vespa/vsm/common/storagedocument.cpp index a0d666268f5..b73b6be2862 100644 --- a/streamingvisitors/src/vespa/vsm/common/storagedocument.cpp +++ b/streamingvisitors/src/vespa/vsm/common/storagedocument.cpp @@ -17,28 +17,31 @@ StorageDocument::StorageDocument(document::Document::UP doc, const SharedFieldPa _fieldMap(fim), _cachedFields(getFieldCount()), _backedFields() -{ } +{ + _backedFields.reserve(getFieldCount()); +} -StorageDocument::~StorageDocument() { } +StorageDocument::~StorageDocument() = default; namespace { FieldPath _emptyFieldPath; - StorageDocument::SubDocument _empySubDocument(NULL, _emptyFieldPath.getFullRange()); + StorageDocument::SubDocument _empySubDocument(nullptr, _emptyFieldPath.getFullRange()); } const StorageDocument::SubDocument & StorageDocument::getComplexField(FieldIdT fId) const { - if (_cachedFields[fId].getFieldValue() == NULL) { + if (_cachedFields[fId].getFieldValue() == nullptr) { const FieldPath & fp = (*_fieldMap)[fId]; if ( ! fp.empty() ) { const document::StructuredFieldValue * sfv = _doc.get(); NestedIterator nested = fp.getFullRange(); const document::FieldPathEntry& fvInfo = nested.cur(); - bool ok = sfv->getValue(fvInfo.getFieldRef(), fvInfo.getFieldValueToSet()); - if (ok) { - SubDocument tmp(&fvInfo.getFieldValueToSet(), nested.next()); + document::FieldValue::UP fv = sfv->getValue(fvInfo.getFieldRef()); + if (fv) { + SubDocument tmp(fv.get(), nested.next()); _cachedFields[fId].swap(tmp); + _backedFields.push_back(std::move(fv)); } } else { LOG(debug, "Failed getting field fId %d.", fId); @@ -48,18 +51,6 @@ StorageDocument::getComplexField(FieldIdT fId) const return _cachedFields[fId]; } -void StorageDocument::saveCachedFields() const -{ - size_t m(_cachedFields.size()); - _backedFields.reserve(m); - for (size_t i(0); i < m; i++) { - if (_cachedFields[i].getFieldValue() != 0) { - _backedFields.emplace_back(document::FieldValue::UP(_cachedFields[i].getFieldValue()->clone())); - _cachedFields[i].setFieldValue(_backedFields.back().get()); - } - } -} - const document::FieldValue * StorageDocument::getField(FieldIdT fId) const { diff --git a/streamingvisitors/src/vespa/vsm/common/storagedocument.h b/streamingvisitors/src/vespa/vsm/common/storagedocument.h index a7f21cb052f..0ac94157462 100644 --- a/streamingvisitors/src/vespa/vsm/common/storagedocument.h +++ b/streamingvisitors/src/vespa/vsm/common/storagedocument.h @@ -47,7 +47,6 @@ public: const SubDocument &getComplexField(FieldIdT fId) const; const document::FieldValue *getField(FieldIdT fId) const override; bool setField(FieldIdT fId, document::FieldValue::UP fv) override ; - void saveCachedFields() const; private: document::Document::UP _doc; SharedFieldPathMap _fieldMap; diff --git a/vespa-hadoop/src/main/java/com/yahoo/vespa/hadoop/pig/VespaStorage.java b/vespa-hadoop/src/main/java/com/yahoo/vespa/hadoop/pig/VespaStorage.java index 96a95351bb5..a564dfac25d 100644 --- a/vespa-hadoop/src/main/java/com/yahoo/vespa/hadoop/pig/VespaStorage.java +++ b/vespa-hadoop/src/main/java/com/yahoo/vespa/hadoop/pig/VespaStorage.java @@ -1,6 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hadoop.pig; +import com.fasterxml.jackson.databind.ObjectMapper; import com.yahoo.vespa.hadoop.mapreduce.VespaOutputFormat; import com.yahoo.vespa.hadoop.mapreduce.util.TupleTools; import com.yahoo.vespa.hadoop.mapreduce.util.VespaConfiguration; @@ -165,27 +166,13 @@ public class VespaStorage extends StoreFunc { return VespaDocumentOperation.create(operation, docId, fields, properties, schema); } - - public static String base64Serialize(Object o) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { - oos.writeObject(o); - } - return Base64.getEncoder().encodeToString(baos.toByteArray()); + public static String base64Serialize(ResourceSchema resourceSchema) throws IOException { + byte[] bytes = new ObjectMapper().writeValueAsBytes(resourceSchema); + return Base64.getEncoder().encodeToString(bytes); } - - @SuppressWarnings("unchecked") - public static <T extends Serializable> T base64Deserialize(String s) throws IOException { - Object ret; + public static ResourceSchema base64Deserialize(String s) throws IOException { byte[] data = Base64.getDecoder().decode(s); - ByteArrayInputStream bais = new ByteArrayInputStream(data); - try (ObjectInputStream ois = new ObjectInputStream(bais)) { - ret = ois.readObject(); - } catch (ClassNotFoundException e) { - throw new IOException(e); - } - return (T) ret; + return new ObjectMapper().readValue(data, ResourceSchema.class); } - } |