From 9219dbe5c1d02c13029f1553a657bb30233da595 Mon Sep 17 00:00:00 2001 From: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:22:52 +0530 Subject: [PATCH 1/3] chore(ui): improve webpack build (#18038) * chore(ui): improve webpack build * update deps * update browser-list * remove js files from project * update import --- openmetadata-ui/pom.xml | 13 -- .../main/resources/ui/.vscode/settings.json | 6 +- .../src/main/resources/ui/package.json | 17 +- .../useCustomLocation.test.ts | 1 + .../useCustomLocation/useCustomLocation.ts | 1 + .../src/main/resources/ui/src/index.tsx | 2 +- .../ui/src/styles/{index.js => index.ts} | 0 .../ui/src/utils/AuthProvider.util.ts | 1 + .../resources/ui/src/utils/HistoryUtils.ts | 1 + .../resources/ui/src/utils/RouterUtils.ts | 1 + .../main/resources/ui/webpack.config.dev.js | 117 ++-------- .../main/resources/ui/webpack.config.prod.js | 131 ++---------- .../src/main/resources/ui/yarn.lock | 199 +----------------- 13 files changed, 65 insertions(+), 425 deletions(-) rename openmetadata-ui/src/main/resources/ui/src/styles/{index.js => index.ts} (100%) diff --git a/openmetadata-ui/pom.xml b/openmetadata-ui/pom.xml index b9bb4492bac6..b93d17069eae 100644 --- a/openmetadata-ui/pom.xml +++ b/openmetadata-ui/pom.xml @@ -177,19 +177,6 @@ src/main/resources/ui/dist true - - src/main/resources/ui - ${project.build.outputDirectory}/openmetadata-ui/ - - dist/** - node_modules/** - webpack/** - *tsconfig.tsbuildinfo - - - ** - - diff --git a/openmetadata-ui/src/main/resources/ui/.vscode/settings.json b/openmetadata-ui/src/main/resources/ui/.vscode/settings.json index 1cf299a9bc00..8ce149e64485 100644 --- a/openmetadata-ui/src/main/resources/ui/.vscode/settings.json +++ b/openmetadata-ui/src/main/resources/ui/.vscode/settings.json @@ -4,9 +4,9 @@ "editor.formatOnSave": true, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true, // eslint --fix on save - "source.fixAll.stylelint": true, // stylelint --fix on save - "source.organizeImports": true // Organize imports on save + "source.fixAll.eslint": "explicit", + "source.fixAll.stylelint": "explicit", + "source.organizeImports": "explicit" }, // Indentations purely based on linters and file formatters, not based on existing occurrences diff --git a/openmetadata-ui/src/main/resources/ui/package.json b/openmetadata-ui/src/main/resources/ui/package.json index c49a50b3fb94..8c8ef24b6bbc 100644 --- a/openmetadata-ui/src/main/resources/ui/package.json +++ b/openmetadata-ui/src/main/resources/ui/package.json @@ -12,8 +12,8 @@ "directory": "openmetadata-ui/src/main/resources/ui" }, "scripts": { - "start": "NODE_ENV=development BABEL_ENV=development webpack serve --config ./webpack.config.dev.js --env development", - "build": "NODE_ENV=production BABEL_ENV=production webpack --config ./webpack.config.prod.js --env production", + "start": "webpack serve --config ./webpack.config.dev.js --env development", + "build": "webpack --config ./webpack.config.prod.js --env production", "postinstall": "yarn run build-check", "preinstall": "cd ../../../../.. && yarn install --frozen-lockfile", "pre-commit": "lint-staged --concurrent false", @@ -71,7 +71,6 @@ "@tiptap/starter-kit": "^2.3.0", "@tiptap/suggestion": "^2.3.0", "@toast-ui/react-editor": "^3.1.8", - "@types/turndown": "^5.0.4", "@windmillcode/quill-emoji": "^2.0.1000", "analytics": "^0.8.1", "antd": "4.24.0", @@ -95,7 +94,6 @@ "jwt-decode": "^3.1.2", "katex": "^0.16.10", "less": "^4.1.3", - "less-loader": "^11.0.0", "lodash": "^4.17.21", "luxon": "^3.2.1", "oidc-client": "^1.11.5", @@ -182,6 +180,7 @@ "@types/recharts": "^1.8.23", "@types/showdown": "^2.0.0", "@types/testing-library__jest-dom": "^5.9.5", + "@types/turndown": "^5.0.4", "@types/use-analytics": "^0.0.0", "@typescript-eslint/eslint-plugin": "4.31.0", "@typescript-eslint/parser": "4.31.0", @@ -192,7 +191,6 @@ "copy-webpack-plugin": "^7.0.0", "css-loader": "^6.7.2", "dotenv": "^16.0.0", - "dotenv-webpack": "^8.1.0", "eslint": "7.32.0", "eslint-config-prettier": "8.3.0", "eslint-plugin-i18next": "^6.0.0-2", @@ -203,7 +201,6 @@ "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "7.36.1", "eslint-plugin-react-hooks": "4.2.0", - "eslint-webpack-plugin": "^3.2.0", "file-loader": "^6.2.0", "fork-ts-checker-webpack-plugin": "6.5.0", "fs-extra": "^10.1.0", @@ -212,16 +209,14 @@ "i18next-json-sync": "^3.1.2", "jest": "^26.6.3", "jest-sonar-reporter": "^2.0.0", + "less-loader": "^11.0.0", "license-check-and-add": "^4.0.5", "lint-staged": "^10.3.0", - "mini-css-extract-plugin": "^2.7.0", "organize-imports-cli": "^0.10.0", "pinst": "^3.0.0", "postcss-loader": "^6.1.0", "prettier": "^2.1.2", "react-test-renderer": "^16.14.0", - "sass": "^1.39.0", - "sass-loader": "^12.1.0", "style-loader": "^3.3.1", "sync-i18n": "^0.0.20", "ts-jest": "^26.4.4", @@ -230,10 +225,8 @@ "typescript": "^4.2.4", "url-loader": "^4.1.1", "webpack": "5.94.0", - "webpack-bundle-analyzer": "4.5.0", "webpack-cli": "^5.1.4", - "webpack-dev-server": "4.15.2", - "webpackbar": "5.0.2" + "webpack-dev-server": "4.15.2" }, "resolutions": { "history": "4.5.1", diff --git a/openmetadata-ui/src/main/resources/ui/src/hooks/useCustomLocation/useCustomLocation.test.ts b/openmetadata-ui/src/main/resources/ui/src/hooks/useCustomLocation/useCustomLocation.test.ts index 2173b26ad75f..a5be78ef3c27 100644 --- a/openmetadata-ui/src/main/resources/ui/src/hooks/useCustomLocation/useCustomLocation.test.ts +++ b/openmetadata-ui/src/main/resources/ui/src/hooks/useCustomLocation/useCustomLocation.test.ts @@ -11,6 +11,7 @@ * limitations under the License. */ import { renderHook } from '@testing-library/react-hooks'; +import process from 'process'; import { useLocation } from 'react-router-dom'; import useCustomLocation from './useCustomLocation'; diff --git a/openmetadata-ui/src/main/resources/ui/src/hooks/useCustomLocation/useCustomLocation.ts b/openmetadata-ui/src/main/resources/ui/src/hooks/useCustomLocation/useCustomLocation.ts index 69a3ba42da76..db9e294434ae 100644 --- a/openmetadata-ui/src/main/resources/ui/src/hooks/useCustomLocation/useCustomLocation.ts +++ b/openmetadata-ui/src/main/resources/ui/src/hooks/useCustomLocation/useCustomLocation.ts @@ -10,6 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import process from 'process'; import { useLocation } from 'react-router-dom'; const useCustomLocation = (): ReturnType => { diff --git a/openmetadata-ui/src/main/resources/ui/src/index.tsx b/openmetadata-ui/src/main/resources/ui/src/index.tsx index 93a5441351c1..b8add396c9c7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/index.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/index.tsx @@ -14,7 +14,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; -import './styles/index.js'; +import './styles/index'; ReactDOM.render( diff --git a/openmetadata-ui/src/main/resources/ui/src/styles/index.js b/openmetadata-ui/src/main/resources/ui/src/styles/index.ts similarity index 100% rename from openmetadata-ui/src/main/resources/ui/src/styles/index.js rename to openmetadata-ui/src/main/resources/ui/src/styles/index.ts diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider.util.ts b/openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider.util.ts index 25d8656f0f29..ce84d039e23a 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider.util.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider.util.ts @@ -20,6 +20,7 @@ import { CookieStorage } from 'cookie-storage'; import jwtDecode, { JwtPayload } from 'jwt-decode'; import { first, get, isEmpty, isNil } from 'lodash'; import { WebStorageStateStore } from 'oidc-client'; +import process from 'process'; import { AuthenticationConfigurationWithScope, OidcUser, diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/HistoryUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/HistoryUtils.ts index 0f9916f11d20..eead40242d37 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/HistoryUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/HistoryUtils.ts @@ -12,6 +12,7 @@ */ import { createBrowserHistory } from 'history'; +import process from 'process'; const subPath = process.env.APP_SUB_PATH ?? ''; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/RouterUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/RouterUtils.ts index 952f1dddeffe..90e5a2846d97 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/RouterUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/RouterUtils.ts @@ -13,6 +13,7 @@ import { isUndefined } from 'lodash'; import { ServiceTypes } from 'Models'; +import process from 'process'; import { getServiceDetailsPath, IN_PAGE_SEARCH_ROUTES, diff --git a/openmetadata-ui/src/main/resources/ui/webpack.config.dev.js b/openmetadata-ui/src/main/resources/ui/webpack.config.dev.js index 094b5ffb1392..af2a37d943be 100644 --- a/openmetadata-ui/src/main/resources/ui/webpack.config.dev.js +++ b/openmetadata-ui/src/main/resources/ui/webpack.config.dev.js @@ -12,14 +12,10 @@ */ const path = require('path'); -const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); -const WebpackBar = require('webpackbar'); -const webpack = require('webpack'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const Dotenv = require('dotenv-webpack'); +const process = require('process'); const outputPath = path.join(__dirname, 'build'); const subPath = process.env.APP_SUB_PATH ?? ''; @@ -36,24 +32,15 @@ module.exports = { path: outputPath, filename: '[name].js', chunkFilename: '[name].js', - publicPath: `${subPath}/`, + // Clean the output directory before emit. + clean: true, // Ensures bundle is served from absolute path as opposed to relative + publicPath: `${subPath}/`, }, // Loaders module: { rules: [ - // .js and .jsx files to be handled by babel-loader - { - test: /\.(js|jsx)$/, - include: path.resolve(__dirname, 'src'), - use: { - loader: 'babel-loader', - options: { - presets: ['@babel/preset-env', '@babel/preset-react'], - }, - }, - }, // .mjs files to be handled { test: /\.m?js/, @@ -73,51 +60,20 @@ module.exports = { }, include: path.resolve(__dirname, 'src'), // Just the source code }, - // .css and .scss files to be handled by sass-loader - // include scss rule and sass-loader if injecting scss/sass file + // .css files to be handled by style-loader & css-loader { - test: /\.(css|s[ac]ss)$/, - use: [ - 'style-loader', - 'css-loader', - { - loader: 'sass-loader', - options: { - // Prefer `dart-sass` - implementation: require.resolve('sass'), - }, - }, - 'postcss-loader', - ], - include: [ - path.resolve(__dirname, 'src'), - path.resolve(__dirname, 'node_modules/@fontsource/poppins'), - path.resolve(__dirname, 'node_modules/@fontsource/source-code-pro'), - path.resolve(__dirname, 'node_modules/reactflow'), - path.resolve(__dirname, 'node_modules/codemirror'), - path.resolve(__dirname, 'node_modules/react-toastify'), - path.resolve(__dirname, 'node_modules/@windmillcode/quill-emoji'), - path.resolve(__dirname, 'node_modules/react-awesome-query-builder'), - path.resolve(__dirname, 'node_modules/katex'), - path.resolve(__dirname, 'node_modules/react-resizable'), - path.resolve(__dirname, 'node_modules/react-antd-column-resize'), - ], - // May need to handle files outside the source code - // (from node_modules) + test: /\.(css)$/, + use: ['style-loader', 'css-loader'], }, - // .less files to be handled by sass-loader + // .less files to be handled by less-loader { test: /\.less$/, use: [ - { - loader: 'style-loader', - }, - { - loader: 'css-loader', // translates CSS into CommonJS - }, + 'style-loader', + 'css-loader', 'postcss-loader', { - loader: 'less-loader', // compiles Less to CSS + loader: 'less-loader', options: { lessOptions: { javascriptEnabled: true, @@ -129,38 +85,21 @@ module.exports = { // .svg files to be handled by @svgr/webpack { test: /\.svg$/, - use: ['@svgr/webpack'], + use: ['@svgr/webpack', 'url-loader'], include: path.resolve(__dirname, 'src'), // Just the source code }, - // different urls to be handled by url-loader + // images files to be handled by file-loader { - test: /\.(png|jpg|jpeg|gif|svg|ico)$/i, + test: /\.png$/, use: [ { - loader: 'url-loader', + loader: 'file-loader', options: { - limit: 8192, - name: `[name].[ext]`, + name: '[name].[ext]', + outputPath: 'images/', }, }, ], - include: [ - path.resolve(__dirname, 'src'), - path.resolve(__dirname, 'node_modules/@windmillcode/quill-emoji'), - ], // Just the source code - }, - // Font files to be handled by asset-modules, see https://webpack.js.org/guides/asset-modules/ - { - test: /\.(ttf|eot|woff|woff2)$/i, - type: 'asset/resource', - generator: { - filename: 'fonts/[name][ext]', - }, - include: [ - path.resolve(__dirname, 'src'), - path.resolve(__dirname, 'node_modules/@fontsource/poppins'), - path.resolve(__dirname, 'node_modules/@fontsource/source-code-pro'), - ], // Just the source code }, ], }, @@ -168,10 +107,9 @@ module.exports = { // Module resolution resolve: { // File types to be handled - extensions: ['.ts', '.tsx', '.js', '.jsx', '.css', '.svg'], + extensions: ['.ts', '.tsx', '.js', '.css', '.less', '.svg'], fallback: { https: require.resolve('https-browserify'), - path: require.resolve('path-browserify'), fs: false, 'process/browser': require.resolve('process/browser'), }, @@ -183,10 +121,6 @@ module.exports = { }, plugins: [ - // Clean webpack output directory - new CleanWebpackPlugin({ - verbose: true, - }), // In development mode, fork TypeScript checking to run in another thread and not block main // transpilation new ForkTsCheckerWebpackPlugin({ @@ -199,6 +133,7 @@ module.exports = { favicon: path.join(__dirname, 'public/favicon.png'), template: path.join(__dirname, 'public/index.html'), scriptLoading: 'defer', + hash: true, }), // Copy favicon, logo and manifest for index.html new CopyWebpackPlugin({ @@ -233,20 +168,6 @@ module.exports = { }, ], }), - // Build progress bar - new WebpackBar({ - name: '@openmetadata [dev]', - color: '#54BAC9', - }), - new MiniCssExtractPlugin({ - filename: '[name].bundle.css', - chunkFilename: '[id].css', - }), - new webpack.ProvidePlugin({ - process: 'process/browser', - Buffer: ['buffer', 'Buffer'], - }), - new Dotenv(), ], // webpack-dev-server diff --git a/openmetadata-ui/src/main/resources/ui/webpack.config.prod.js b/openmetadata-ui/src/main/resources/ui/webpack.config.prod.js index 6c692f4ab16e..ce49ec841873 100644 --- a/openmetadata-ui/src/main/resources/ui/webpack.config.prod.js +++ b/openmetadata-ui/src/main/resources/ui/webpack.config.prod.js @@ -12,47 +12,34 @@ */ const path = require('path'); -const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); -const WebpackBar = require('webpackbar'); -const webpack = require('webpack'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const BundleAnalyzerPlugin = - require('webpack-bundle-analyzer').BundleAnalyzerPlugin; -const Dotenv = require('dotenv-webpack'); +const process = require('process'); const outputPath = path.join(__dirname, 'dist/assets'); +const subPath = process.env.APP_SUB_PATH ?? ''; module.exports = { // Production mode mode: 'production', // Input configuration - entry: ['@babel/polyfill', path.join(__dirname, 'src/index.tsx')], + entry: path.join(__dirname, 'src/index.tsx'), // Output configuration output: { path: outputPath, filename: 'openmetadata.[fullhash].js', chunkFilename: '[name].[fullhash].js', - publicPath: `${process.env.APP_SUB_PATH ?? ''}/`, // Ensures bundle is served from absolute path as opposed to relative + // Clean the output directory before emit. + clean: true, + // Ensures bundle is served from absolute path as opposed to relative + publicPath: `${subPath ?? ''}/`, }, // Loaders module: { rules: [ - // .js and .jsx files to be handled by babel-loader - { - test: /\.(js|jsx)$/, - include: path.resolve(__dirname, 'src'), // Just the source code - use: { - loader: 'babel-loader', - options: { - presets: ['@babel/preset-env', '@babel/preset-react'], - }, - }, - }, // .mjs files to be handled { test: /\.m?js/, @@ -72,51 +59,20 @@ module.exports = { }, include: path.resolve(__dirname, 'src'), // Just the source code }, - // .css and .scss files to be handled by sass-loader - // include scss rule and sass-loader if injecting scss/sass file + // .css files to be handled by style-loader & css-loader { - test: /\.(css|s[ac]ss)$/, - use: [ - 'style-loader', - 'css-loader', - { - loader: 'sass-loader', - options: { - // Prefer `dart-sass` - implementation: require.resolve('sass'), - }, - }, - 'postcss-loader', - ], - include: [ - path.resolve(__dirname, 'src'), - path.resolve(__dirname, 'node_modules/@fontsource/poppins'), - path.resolve(__dirname, 'node_modules/@fontsource/source-code-pro'), - path.resolve(__dirname, 'node_modules/reactflow'), - path.resolve(__dirname, 'node_modules/codemirror'), - path.resolve(__dirname, 'node_modules/react-toastify'), - path.resolve(__dirname, 'node_modules/@windmillcode/quill-emoji'), - path.resolve(__dirname, 'node_modules/react-awesome-query-builder'), - path.resolve(__dirname, 'node_modules/katex'), - path.resolve(__dirname, 'node_modules/react-resizable'), - path.resolve(__dirname, 'node_modules/react-antd-column-resize'), - ], - // May need to handle files outside the source code - // (from node_modules) + test: /\.(css)$/, + use: ['style-loader', 'css-loader'], }, - // .less files to be handled by sass-loader + // .less files to be handled by less-loader { test: /\.less$/, use: [ - { - loader: 'style-loader', - }, - { - loader: 'css-loader', // translates CSS into CommonJS - }, + 'style-loader', + 'css-loader', 'postcss-loader', { - loader: 'less-loader', // compiles Less to CSS + loader: 'less-loader', options: { lessOptions: { javascriptEnabled: true, @@ -128,38 +84,21 @@ module.exports = { // .svg files to be handled by @svgr/webpack { test: /\.svg$/, - use: ['@svgr/webpack'], + use: ['@svgr/webpack', 'url-loader'], include: path.resolve(__dirname, 'src'), // Just the source code }, - // different urls to be handled by url-loader + // images files to be handled by file-loader { - test: /\.(png|jpg|jpeg|gif|svg|ico)$/i, + test: /\.png$/, use: [ { - loader: 'url-loader', + loader: 'file-loader', options: { - limit: 8192, - name: `[name].[ext]`, + name: '[name].[ext]', + outputPath: 'images/', }, }, ], - include: [ - path.resolve(__dirname, 'src'), - path.resolve(__dirname, 'node_modules/@windmillcode/quill-emoji'), - ], // Just the source code - }, - // Font files to be handled by asset-modules, see https://webpack.js.org/guides/asset-modules/ - { - test: /\.(ttf|eot|woff|woff2)$/i, - type: 'asset/resource', - generator: { - filename: 'fonts/[name][ext]', - }, - include: [ - path.resolve(__dirname, 'src'), - path.resolve(__dirname, 'node_modules/@fontsource/poppins'), - path.resolve(__dirname, 'node_modules/@fontsource/source-code-pro'), - ], // Just the source code }, ], }, @@ -167,10 +106,9 @@ module.exports = { // Module resolution resolve: { // File types to be handled - extensions: ['.ts', '.tsx', '.js', '.jsx', '.css', '.scss', '.svg'], + extensions: ['.ts', '.tsx', '.js', '.css', '.less', '.svg'], fallback: { https: require.resolve('https-browserify'), - path: require.resolve('path-browserify'), fs: false, 'process/browser': require.resolve('process/browser'), }, @@ -182,10 +120,6 @@ module.exports = { }, plugins: [ - // Clean webpack output directory - new CleanWebpackPlugin({ - verbose: true, - }), // Generate index.html from template new HtmlWebpackPlugin({ favicon: path.join(__dirname, 'public/favicon.png'), @@ -227,28 +161,5 @@ module.exports = { }, ], }), - // Build progress bar - new WebpackBar({ - name: '@openmetadata [prod]', - color: '#15C39B', - }), - new MiniCssExtractPlugin({ - filename: '[name].bundle.css', - chunkFilename: '[id].css', - }), - new webpack.ProvidePlugin({ - process: 'process/browser', - Buffer: ['buffer', 'Buffer'], - }), - // Bundle analyzer - new BundleAnalyzerPlugin({ - analyzerMode: 'static', - reportFilename: path.join( - __dirname, - 'webpack/bundle-analyzer-report.html' - ), - openAnalyzer: false, - }), - new Dotenv(), ], }; diff --git a/openmetadata-ui/src/main/resources/ui/yarn.lock b/openmetadata-ui/src/main/resources/ui/yarn.lock index fea57e69b11f..279f46fca62b 100644 --- a/openmetadata-ui/src/main/resources/ui/yarn.lock +++ b/openmetadata-ui/src/main/resources/ui/yarn.lock @@ -2939,11 +2939,6 @@ dependencies: playwright "1.44.1" -"@polka/url@^1.0.0-next.15": - version "1.0.0-next.15" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.15.tgz#6a9d143f7f4f49db2d782f9e1c8839a29b43ae23" - integrity sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA== - "@popperjs/core@^2.9.0": version "2.11.8" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" @@ -4261,14 +4256,6 @@ dependencies: "@types/trusted-types" "*" -"@types/eslint@^7.29.0 || ^8.4.1": - version "8.4.10" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.10.tgz#19731b9685c19ed1552da7052b6f668ed7eb64bb" - integrity sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - "@types/estree@*", "@types/estree@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" @@ -4378,16 +4365,16 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== - "@types/json-schema@^7.0.4": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== +"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -5090,17 +5077,12 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn-walk@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.1.1.tgz#3ddab7f84e4a7e2313f6c414c5b7dac85f4e3ebc" - integrity sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w== - acorn@^7.1.1, acorn@^7.4.0, acorn@^7.4.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4, acorn@^8.2.4, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8.2: +acorn@^8.2.4, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8.2: version "8.12.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== @@ -5959,9 +5941,9 @@ camelize@^1.0.0: integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001541: - version "1.0.30001541" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001541.tgz#b1aef0fadd87fb72db4dcb55d220eae17b81cdb1" - integrity sha512-bLOsqxDgTqUBkzxbNlSBt8annkDpQB9NdzdTbO2ooJ+eC/IQcvDspDc058g84ejCelF7vHUx57KIOjEecOHXaw== + version "1.0.30001664" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz" + integrity sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g== capture-exit@^2.0.0: version "2.0.0" @@ -6000,21 +5982,6 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -"chokidar@>=3.0.0 <4.0.0": - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - chokidar@^3.4.2: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" @@ -6326,11 +6293,6 @@ connect-history-api-fallback@^2.0.0: resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== -consola@^2.15.3: - version "2.15.3" - resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" - integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== - content-disposition@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -7143,40 +7105,16 @@ dot-case@^3.0.4: no-case "^3.0.4" tslib "^2.0.3" -dotenv-defaults@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz#6b3ec2e4319aafb70940abda72d3856770ee77ac" - integrity sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg== - dependencies: - dotenv "^8.2.0" - -dotenv-webpack@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz#4d66abc4a30395b46a030ebcd125320232b54873" - integrity sha512-owK1JcsPkIobeqjVrk6h7jPED/W6ZpdFsMPR+5ursB7/SdgDyO+VzAU+szK8C8u3qUhtENyYnj8eyXMR5kkGag== - dependencies: - dotenv-defaults "^2.0.2" - dotenv@^16.0.0: version "16.0.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== -dotenv@^8.2.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" - integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== - drange@^1.0.2: version "1.1.1" resolved "https://registry.yarnpkg.com/drange/-/drange-1.1.1.tgz#b2aecec2aab82fcef11dbbd7b9e32b83f8f6c0b8" integrity sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA== -duplexer@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - editorconfig@^0.15.3: version "0.15.3" resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" @@ -7683,17 +7621,6 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint-webpack-plugin@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz#1978cdb9edc461e4b0195a20da950cf57988347c" - integrity sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w== - dependencies: - "@types/eslint" "^7.29.0 || ^8.4.1" - jest-worker "^28.0.2" - micromatch "^4.0.5" - normalize-path "^3.0.0" - schema-utils "^4.0.0" - eslint@7.32.0: version "7.32.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" @@ -8517,13 +8444,6 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -gzip-size@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" - integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== - dependencies: - duplexer "^0.1.2" - handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -9852,15 +9772,6 @@ jest-worker@^26.6.2: merge-stream "^2.0.0" supports-color "^7.0.0" -jest-worker@^28.0.2: - 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@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" @@ -10481,7 +10392,7 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= -micromatch@4.0.8, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: +micromatch@4.0.8, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -10511,11 +10422,6 @@ mime@1.6.0, mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.3.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" - integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -10539,13 +10445,6 @@ mini-create-react-context@^0.4.1: "@babel/runtime" "^7.12.1" tiny-warning "^1.0.3" -mini-css-extract-plugin@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz#d7d9ba0c5b596d155e36e2b174082fc7f010dd64" - integrity sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw== - dependencies: - schema-utils "^4.0.0" - minim@~0.23.8: version "0.23.8" resolved "https://registry.yarnpkg.com/minim/-/minim-0.23.8.tgz#a529837afe1654f119dfb68ce7487dd8d4866b9c" @@ -10987,11 +10886,6 @@ openapi-server-url-templating@^1.0.0: dependencies: apg-lite "^1.0.3" -opener@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" - integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== - optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -11453,11 +11347,6 @@ pretty-format@^26.0.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" -pretty-time@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" - integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== - prismjs@^1.29.0: version "1.29.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" @@ -13080,21 +12969,6 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sass-loader@^12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.1.0.tgz#b73324622231009da6fba61ab76013256380d201" - integrity sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg== - dependencies: - klona "^2.0.4" - neo-async "^2.6.2" - -sass@^1.39.0: - version "1.39.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.39.0.tgz#6c64695d1c437767c8f1a4e471288e831f81d035" - integrity sha512-F4o+RhJkNOIG0b6QudYU8c78ZADKZjKDk5cyrf8XTKWfrgbtyVVXImFstJrc+1pkQDCggyidIOytq6gS4gCCZg== - dependencies: - chokidar ">=3.0.0 <4.0.0" - sax@>=0.6.0, sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -13396,15 +13270,6 @@ simple-get@^4.0.0: once "^1.3.1" simple-concat "^1.0.0" -sirv@^1.0.7: - version "1.0.12" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.12.tgz#d816c882b35489b3c63290e2f455ae3eccd5f652" - integrity sha512-+jQoCxndz7L2tqQL4ZyzfDhky0W/4ZJip3XoOuxyQWnAwMxindLl3Xv1qT4x1YX/re0leShvTm8Uk0kQspGhBg== - dependencies: - "@polka/url" "^1.0.0-next.15" - mime "^2.3.1" - totalist "^1.0.0" - sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -13586,11 +13451,6 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -std-env@^3.0.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.3.1.tgz#93a81835815e618c8aa75e7c8a4dc04f7c314e29" - integrity sha512-3H20QlwQsSm2OvAxWIYhs+j01MzzqwMwGiiO1NQaJYZgJZFPuAbf95/DiKRBSTYIJ2FeGUc+B/6mPGcWP9dO3Q== - string-argv@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" @@ -13865,13 +13725,6 @@ supports-color@^7.0.0, supports-color@^7.1.0: 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" @@ -14118,11 +13971,6 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -totalist@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" - integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== - tough-cookie@4.1.3, tough-cookie@^4.0.0: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" @@ -14756,21 +14604,6 @@ webidl-conversions@^6.1.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== -webpack-bundle-analyzer@4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" - integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== - dependencies: - acorn "^8.0.4" - acorn-walk "^8.0.0" - chalk "^4.1.0" - commander "^7.2.0" - gzip-size "^6.0.0" - lodash "^4.17.20" - opener "^1.5.2" - sirv "^1.0.7" - ws "^7.3.1" - webpack-cli@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" @@ -14879,16 +14712,6 @@ webpack@5.94.0: watchpack "^2.4.1" webpack-sources "^3.2.3" -webpackbar@5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-5.0.2.tgz#d3dd466211c73852741dfc842b7556dcbc2b0570" - integrity sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ== - dependencies: - chalk "^4.1.0" - consola "^2.15.3" - pretty-time "^1.1.0" - std-env "^3.0.1" - websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" @@ -15072,7 +14895,7 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -ws@8.17.1, ws@^7.3.1, ws@^7.4.6, ws@^8.13.0, ws@~8.2.3: +ws@8.17.1, ws@^7.4.6, ws@^8.13.0, ws@~8.2.3: version "8.17.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== From 47cde167b40b4efced66b1bb845f992baae970c9 Mon Sep 17 00:00:00 2001 From: Karan Hotchandani <33024356+karanh37@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:00:47 +0530 Subject: [PATCH 2/3] GEN-712: show column lineage function in edge drawer (#18032) * show column lineage function * add e2e tests --- .../ui/playwright/e2e/Pages/Lineage.spec.ts | 84 ++++++++++++++++++- .../EdgeInfoDrawer.component.tsx | 10 ++- .../ui/src/utils/EntityLineageUtils.test.tsx | 73 +++++++++++++++- .../ui/src/utils/EntityLineageUtils.tsx | 12 +++ 4 files changed, 176 insertions(+), 3 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Lineage.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Lineage.spec.ts index 11f75bfb5f73..058784b928c9 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Lineage.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Lineage.spec.ts @@ -10,7 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import test from '@playwright/test'; +import test, { expect } from '@playwright/test'; import { get } from 'lodash'; import { ApiEndpointClass } from '../../support/entity/ApiEndpointClass'; import { ContainerClass } from '../../support/entity/ContainerClass'; @@ -280,3 +280,85 @@ test('Verify column lineage between table and api endpoint', async ({ await afterAction(); }); + +test('Verify function data in edge drawer', async ({ browser }) => { + const { page } = await createNewPage(browser); + const { apiContext, afterAction } = await getApiContext(page); + const table1 = new TableClass(); + const table2 = new TableClass(); + + try { + await table1.create(apiContext); + await table2.create(apiContext); + const sourceTableFqn = get(table1, 'entityResponseData.fullyQualifiedName'); + const sourceColName = `${sourceTableFqn}.${get( + table1, + 'entityResponseData.columns[0].name' + )}`; + + const targetTableFqn = get(table2, 'entityResponseData.fullyQualifiedName'); + const targetColName = `${targetTableFqn}.${get( + table2, + 'entityResponseData.columns[0].name' + )}`; + + await addPipelineBetweenNodes(page, table1, table2); + await activateColumnLayer(page); + await addColumnLineage(page, sourceColName, targetColName); + + const lineageReq = page.waitForResponse('/api/v1/lineage/getLineage?*'); + await page.reload(); + const lineageRes = await lineageReq; + const jsonRes = await lineageRes.json(); + const edge = jsonRes.edges[0]; + const columnData = edge.columns[0]; + + const newEdge = { + edge: { + fromEntity: { + id: edge.fromEntity.id, + type: edge.fromEntity.type, + }, + toEntity: { + id: edge.toEntity.id, + type: edge.toEntity.type, + }, + lineageDetails: { + columnsLineage: [ + { + fromColumns: [columnData.fromColumns[0]], + function: 'count', + toColumn: columnData.toColumn, + }, + ], + description: 'test', + }, + }, + }; + await apiContext.put(`/api/v1/lineage`, { + data: newEdge, + }); + const lineageReq1 = page.waitForResponse('/api/v1/lineage/getLineage?*'); + await page.reload(); + await lineageReq1; + + await activateColumnLayer(page); + await page + .locator( + `[data-testid="column-edge-${btoa(sourceColName)}-${btoa( + targetColName + )}"]` + ) + .dispatchEvent('click'); + + await page.locator('.edge-info-drawer').isVisible(); + + await expect(await page.locator('[data-testid="Function"]')).toContainText( + 'count' + ); + } finally { + await table1.delete(apiContext); + await table2.delete(apiContext); + await afterAction(); + } +}); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx index 24b82ddf22c7..83799b3bcf46 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx @@ -27,6 +27,7 @@ import { EntityType } from '../../../enums/entity.enum'; import { Source } from '../../../generated/type/entityLineage'; import { getNameFromFQN } from '../../../utils/CommonUtils'; import { + getColumnFunctionValue, getColumnSourceTargetHandles, getLineageDetailsObject, } from '../../../utils/EntityLineageUtils'; @@ -66,6 +67,7 @@ const EdgeInfoDrawer = ({ const { source, target, data } = edge; const { sourceHandle, targetHandle } = getColumnSourceTargetHandles(edge); const { pipeline, pipelineEntityType } = data?.edge ?? {}; + const isColumnLineage = sourceHandle && targetHandle; let sourceData: Node | undefined, targetData: Node | undefined; nodes.forEach((node) => { @@ -121,7 +123,13 @@ const EdgeInfoDrawer = ({ }, functionInfo: { key: t('label.function'), - value: data.columnFunctionValue, + value: isColumnLineage + ? getColumnFunctionValue( + data?.edge?.columns ?? [], + sourceHandle ?? '', + targetHandle ?? '' + ) + : undefined, }, }); setIsLoading(false); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.test.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.test.tsx index 42cc95e4e8d6..e5f584daa603 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.test.tsx @@ -16,7 +16,7 @@ import { EdgeTypeEnum } from '../components/Entity/EntityLineage/EntityLineage.i import { EdgeDetails } from '../components/Lineage/Lineage.interface'; import { SourceType } from '../components/SearchedData/SearchedData.interface'; import { EntityType } from '../enums/entity.enum'; -import { AddLineage } from '../generated/api/lineage/addLineage'; +import { AddLineage, ColumnLineage } from '../generated/api/lineage/addLineage'; import { MOCK_CHILD_MAP, MOCK_LINEAGE_DATA_NEW, @@ -29,6 +29,7 @@ import { createNewEdge, getAllTracedEdges, getChildMap, + getColumnFunctionValue, getColumnLineageData, getColumnSourceTargetHandles, getConnectedNodesEdges, @@ -608,4 +609,74 @@ describe('Test EntityLineageUtils utility', () => { expect(result.childrenHeading).toEqual('label.column-plural'); }); }); + + describe('getColumnFunctionValue', () => { + it('should return the correct function value when a matching column is found', () => { + const columns = [ + { + toColumn: 'targetColumn', + fromColumns: ['sourceColumn'], + function: 'SUM', + }, + { + toColumn: 'anotherTargetColumn', + fromColumns: ['anotherSourceColumn'], + function: 'AVG', + }, + ]; + const sourceFqn = 'sourceColumn'; + const targetFqn = 'targetColumn'; + + const result = getColumnFunctionValue(columns, sourceFqn, targetFqn); + + expect(result).toBe('SUM'); + }); + + it('should return undefined when no matching column is found', () => { + const columns = [ + { + toColumn: 'targetColumn', + fromColumns: ['sourceColumn'], + function: 'SUM', + }, + { + toColumn: 'anotherTargetColumn', + fromColumns: ['anotherSourceColumn'], + function: 'AVG', + }, + ]; + const sourceFqn = 'nonExistentSourceColumn'; + const targetFqn = 'nonExistentTargetColumn'; + + const result = getColumnFunctionValue(columns, sourceFqn, targetFqn); + + expect(result).toBeUndefined(); + }); + + it('should return undefined when columns array is empty', () => { + const columns: ColumnLineage[] = []; + const sourceFqn = 'sourceColumn'; + const targetFqn = 'targetColumn'; + + const result = getColumnFunctionValue(columns, sourceFqn, targetFqn); + + expect(result).toBeUndefined(); + }); + + it('should return undefined when fromColumns is undefined', () => { + const columns = [ + { + toColumn: 'targetColumn', + fromColumns: undefined, + function: 'SUM', + }, + ]; + const sourceFqn = 'sourceColumn'; + const targetFqn = 'targetColumn'; + + const result = getColumnFunctionValue(columns, sourceFqn, targetFqn); + + expect(result).toBeUndefined(); + }); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.tsx index 90c4e3c2d396..32db6376d2ca 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageUtils.tsx @@ -1390,3 +1390,15 @@ export const getPaginatedChildMap = ( return { nodes, edges }; }; + +export const getColumnFunctionValue = ( + columns: ColumnLineage[], + sourceFqn: string, + targetFqn: string +) => { + const column = columns.find( + (col) => col.toColumn === targetFqn && col.fromColumns?.includes(sourceFqn) + ); + + return column?.function; +}; From 907e0d38b84b7deca6e10d307aed7ba69898e99e Mon Sep 17 00:00:00 2001 From: RounakDhillon <162090200+RounakDhillon@users.noreply.github.com> Date: Mon, 30 Sep 2024 16:45:38 +0530 Subject: [PATCH 3/3] Docs: updatinggettingstarted (#18045) Co-authored-by: Rounak Dhillon --- .../getting-started/day-1/database-service-setup.md | 1 - .../how-to-guides/getting-started/day-1/index.md | 1 - .../v1.5.x/how-to-guides/getting-started/index.md | 4 ++-- .../content/v1.5.x/how-to-guides/index.md | 13 +++++++++++++ .../getting-started/day-1/database-service-setup.md | 1 - .../how-to-guides/getting-started/day-1/index.md | 1 - .../how-to-guides/getting-started/index.md | 4 ++-- .../content/v1.6.x-SNAPSHOT/how-to-guides/index.md | 13 +++++++++++++ 8 files changed, 30 insertions(+), 8 deletions(-) diff --git a/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/day-1/database-service-setup.md b/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/day-1/database-service-setup.md index 8ddf6e0b17ff..a67d0dc90c28 100644 --- a/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/day-1/database-service-setup.md +++ b/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/day-1/database-service-setup.md @@ -1,7 +1,6 @@ --- title: Database service setup slug: /how-to-guides/getting-started/day-1/database-service-setup -collate: true --- ## Setting Up a Database Service for Metadata Extraction diff --git a/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/day-1/index.md b/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/day-1/index.md index 0b0877b24ebf..87bd8c564e38 100644 --- a/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/day-1/index.md +++ b/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/day-1/index.md @@ -1,7 +1,6 @@ --- title: Day 1 slug: /how-to-guides/getting-started/day-1 -collate: true --- # Getting Started: Day 1 diff --git a/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/index.md b/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/index.md index ad0a3aea8868..d1044aa836fd 100644 --- a/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/index.md +++ b/openmetadata-docs/content/v1.5.x/how-to-guides/getting-started/index.md @@ -7,7 +7,7 @@ slug: /how-to-guides/getting-started Welcome to OpenMetadata's unified platform for data discovery, observability, and governance. Our platform centralizes all data context to help you build high-quality data and AI assets. This guide provides the necessary information to set up your OpenMetadata environment in 30 minutes. -## How Does Collate Work? +## How Does OpenMetadata Work? OpenMetadata is designed to support both technical and non-technical data practitioners across various use cases, including data discovery, lineage, observability, quality, collaboration, governance, and insights. @@ -18,7 +18,7 @@ The platform’s native collaboration features support shared workflows, enablin ## Key Features of OpenMetadata -Before we get started, here’s a quick summary of some of Collate’s main features: +Before we get started, here’s a quick summary of some of OpenMetadata’s main features: ### Discovery - Integrated catalog, data quality, and glossary diff --git a/openmetadata-docs/content/v1.5.x/how-to-guides/index.md b/openmetadata-docs/content/v1.5.x/how-to-guides/index.md index fcc33a8cc675..84af90a4eb6a 100644 --- a/openmetadata-docs/content/v1.5.x/how-to-guides/index.md +++ b/openmetadata-docs/content/v1.5.x/how-to-guides/index.md @@ -5,6 +5,19 @@ slug: /how-to-guides # How-to Guides +## Getting Started + +Set up and explore OpenMetadata's core features, from basic configuration to advanced functionalities, for a seamless onboarding experience. + +{% tilesContainer %} +{% tile + title="Getting Started" + description="Unlock metadata insights for informed business decisions." + link="/how-to-guides/getting-started" + icon="discovery" +/%} +{% /tilesContainer %} + The How-to Guides will give you a walk through on accomplishing the basic to the most advanced things in OpenMetadata. These step-by-step guides will help get an overview of the features and also help explore the various functionalities. ## Features in OpenMetadata diff --git a/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/day-1/database-service-setup.md b/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/day-1/database-service-setup.md index 826148ca706a..c8310a1dfff4 100644 --- a/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/day-1/database-service-setup.md +++ b/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/day-1/database-service-setup.md @@ -1,7 +1,6 @@ --- title: Database service setup slug: /how-to-guides/getting-started/day-1/database-service-setup -collate: true --- ## Setting Up a Database Service for Metadata Extraction diff --git a/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/day-1/index.md b/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/day-1/index.md index 319b8b528a87..3788f95015c8 100644 --- a/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/day-1/index.md +++ b/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/day-1/index.md @@ -1,7 +1,6 @@ --- title: Day 1 slug: /how-to-guides/getting-started/day-1 -collate: true --- # Getting Started: Day 1 diff --git a/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/index.md b/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/index.md index ad0a3aea8868..d1044aa836fd 100644 --- a/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/index.md +++ b/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/getting-started/index.md @@ -7,7 +7,7 @@ slug: /how-to-guides/getting-started Welcome to OpenMetadata's unified platform for data discovery, observability, and governance. Our platform centralizes all data context to help you build high-quality data and AI assets. This guide provides the necessary information to set up your OpenMetadata environment in 30 minutes. -## How Does Collate Work? +## How Does OpenMetadata Work? OpenMetadata is designed to support both technical and non-technical data practitioners across various use cases, including data discovery, lineage, observability, quality, collaboration, governance, and insights. @@ -18,7 +18,7 @@ The platform’s native collaboration features support shared workflows, enablin ## Key Features of OpenMetadata -Before we get started, here’s a quick summary of some of Collate’s main features: +Before we get started, here’s a quick summary of some of OpenMetadata’s main features: ### Discovery - Integrated catalog, data quality, and glossary diff --git a/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/index.md b/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/index.md index fcc33a8cc675..84af90a4eb6a 100644 --- a/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/index.md +++ b/openmetadata-docs/content/v1.6.x-SNAPSHOT/how-to-guides/index.md @@ -5,6 +5,19 @@ slug: /how-to-guides # How-to Guides +## Getting Started + +Set up and explore OpenMetadata's core features, from basic configuration to advanced functionalities, for a seamless onboarding experience. + +{% tilesContainer %} +{% tile + title="Getting Started" + description="Unlock metadata insights for informed business decisions." + link="/how-to-guides/getting-started" + icon="discovery" +/%} +{% /tilesContainer %} + The How-to Guides will give you a walk through on accomplishing the basic to the most advanced things in OpenMetadata. These step-by-step guides will help get an overview of the features and also help explore the various functionalities. ## Features in OpenMetadata