From 0bfa6fad11ed2c76b3bff078eb7891580ede3161 Mon Sep 17 00:00:00 2001 From: wujinhua <1322301717@qq.com> Date: Fri, 25 Oct 2024 14:12:35 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90GLCC=E3=80=91Higress=20Console=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=80=9A=E8=BF=87=E8=A1=A8=E5=8D=95=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=20Wasm=20=E6=8F=92=E4=BB=B6=20(#322)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package-lock.json | 13 +- frontend/package.json | 1 + frontend/src/locales/en-US/translation.json | 6 +- frontend/src/locales/zh-CN/translation.json | 6 +- .../PluginDrawer/ArrayForm/index.module.css | 4 + .../PluginDrawer/ArrayForm/index.tsx | 289 ++++++++++++ .../PluginDrawer/GlobalPluginDetail.tsx | 414 +++++++++++++++++- .../plugin/components/PluginDrawer/index.tsx | 6 +- frontend/yarn.lock | 276 +++++++++++- 9 files changed, 991 insertions(+), 24 deletions(-) create mode 100644 frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.module.css create mode 100644 frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c955a94a..0c18ef05 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -35,6 +35,7 @@ "@ice/plugin-request": "^1.0.0", "@ice/plugin-store": "^1.0.0", "@iceworks/spec": "^1.0.0", + "@types/js-yaml": "^4.0.9", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@typescript-eslint/eslint-plugin": "^5.60.1", @@ -7517,6 +7518,12 @@ "resolved": "https://registry.npmmirror.com/@types/js-cookie/-/js-cookie-2.2.7.tgz", "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==" }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmmirror.com/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -10479,9 +10486,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001509", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz", - "integrity": "sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA==", + "version": "1.0.30001651", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", "funding": [ { "type": "opencollective", diff --git a/frontend/package.json b/frontend/package.json index 64258301..98a0bb9d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -30,6 +30,7 @@ "@ice/plugin-request": "^1.0.0", "@ice/plugin-store": "^1.0.0", "@iceworks/spec": "^1.0.0", + "@types/js-yaml": "^4.0.9", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@typescript-eslint/eslint-plugin": "^5.60.1", diff --git a/frontend/src/locales/en-US/translation.json b/frontend/src/locales/en-US/translation.json index e7b90696..1072242a 100644 --- a/frontend/src/locales/en-US/translation.json +++ b/frontend/src/locales/en-US/translation.json @@ -501,6 +501,10 @@ "seconds": "Sec(s)", "tbd": "Still in development. To be released soon...", "yes": "Yes", - "no": "No" + "no": "No", + "switchToYAML": "YAML View", + "switchToForm": "Form View", + "isRequired": "is required", + "invalidSchema": "Since schema information cannot be properly parsed, this plugin only supports YAML editing." } } diff --git a/frontend/src/locales/zh-CN/translation.json b/frontend/src/locales/zh-CN/translation.json index e0cd68aa..458c2870 100644 --- a/frontend/src/locales/zh-CN/translation.json +++ b/frontend/src/locales/zh-CN/translation.json @@ -545,6 +545,10 @@ "seconds": "秒", "tbd": "页面开发中,即将推出...", "yes": "是", - "no": "否" + "no": "否", + "switchToYAML": "YAML视图", + "switchToForm": "表单视图", + "isRequired": "是必填的", + "invalidSchema": "由于 schema 信息无法正常解析,本插件只支持 YAML 编辑方式。" } } diff --git a/frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.module.css b/frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.module.css new file mode 100644 index 00000000..4b47e3d3 --- /dev/null +++ b/frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.module.css @@ -0,0 +1,4 @@ +.ant-empty-normal { + margin: 0; +} + diff --git a/frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.tsx b/frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.tsx new file mode 100644 index 00000000..accacff1 --- /dev/null +++ b/frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.tsx @@ -0,0 +1,289 @@ +import { DeleteOutlined, PlusOutlined } from '@ant-design/icons'; +import { Button, Form, Input, Select, Table } from 'antd'; +import type { FormInstance } from 'antd/es/form'; +import { uniqueId } from 'lodash'; +import React, { useContext, useEffect, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import styles from './index.module.css'; +import i18next from 'i18next'; + +const EditableContext = React.createContext | null>(null); + +interface Item { + key: string; +} + +interface EditableRowProps { + index: number; +} + +const EditableRow: React.FC = ({ index, ...props }) => { + const [form] = Form.useForm(); + return ( +
+ + + +
+ ); +}; + +interface EditableCellProps { + title: React.ReactNode; + editable: boolean; + children: React.ReactNode; + dataIndex: keyof Item; + record: Item; + nodeType: string; + required: boolean; + handleSave: (record: Item, valid: boolean) => void; +} + +const EditableCell: React.FC = ({ + title, + editable, + children, + dataIndex, + nodeType, + record, + required, + handleSave, + ...restProps +}) => { + const { t } = useTranslation(); + const [editing, setEditing] = useState(true); + const inputRef = useRef(null); + const form = useContext(EditableContext)!; + + const matchOptions = ['PRE', 'EQUAL', 'REGULAR'].map((v) => { + return { label: t(`route.matchTypes.${v}`), value: v }; + }); + + useEffect(() => { + form.setFieldsValue({ ...record }); + }, [editing]); + + const save = async () => { + form.validateFields().then(values => { + handleSave({ ...record, ...values }, true); + }).catch(e => { + handleSave({ ...record, ...form.getFieldsValue() }, false); + }) + }; + + let childNode = children; + let node; + + const handleInputChange = (name, value) => { + form.setFieldValue(name, value); + }; + + switch (nodeType) { + case 'string': + node = ( + handleInputChange(dataIndex, e.target.value)} + /> + ); + break; + case 'integer': + node = ( + handleInputChange(dataIndex, parseInt(e.target.value, 10))} + /> + ); + break; + case 'number': + node = ( + handleInputChange(dataIndex, parseFloat(e.target.value))} + /> + ) + break; + case 'boolean': + node = ( + + ); + break; + default: + node = ( + handleInputChange(dataIndex, e.target.value)} + /> + ); + } + + if (editable) { + childNode = ( + + {node} + + ); + } + + return {childNode}; +}; + +type EditableTableProps = Parameters[0]; + +interface DataType { + uid: number; + new: boolean; + invalid: boolean; +} + +type ColumnTypes = Exclude; + +const ArrayForm: React.FC = ({ array, value, onChange }) => { + const { t } = useTranslation(); + + const initDataSource = value || []; + for (const item of initDataSource) { + if (!item.uid) { + item.uid = uniqueId(); + } + } + + const [dataSource, setDataSource] = useState(value || []); + + function getLocalizedText(obj: any, index: string, defaultText: string) { + const i18nObj = obj[`x-${index}-i18n`]; + return i18nObj && i18nObj[i18next.language] || obj[index] || defaultText || ''; + } + + const defaultColumns: any[] = []; + if (array.type === 'object') { + Object.entries(array.properties).forEach(([key, prop]) => { + let translatedTitle = getLocalizedText(prop, 'title', key); + const isRequired = (array.required || []).includes(key); + defaultColumns.push({ + title: translatedTitle, + dataIndex: key, + editable: true, + required: isRequired, + nodeType: prop.type, + }); + }); + } else { + let translatedTitle = getLocalizedText(array, 'title', ''); + defaultColumns.push({ + title: translatedTitle, + dataIndex: 'Item', + editable: true, + required: true, + nodeType: array.type, + }); + } + + defaultColumns.push({ + dataIndex: 'operation', + width: 60, + render: (_, record: { uid: number }) => + (dataSource.length >= 1 ? ( +
handleDelete(record.uid)}> + +
+ ) : null), + }); + + const handleAdd = () => { + const newData: DataType = { + uid: uniqueId(), + new: true, + invalid: true, + }; + setDataSource([...dataSource, newData]); + onChange([...dataSource, newData]); + }; + + const handleDelete = (uid: number) => { + const newData = dataSource.filter((item) => item.uid !== uid); + setDataSource(newData); + onChange(newData); + }; + + const handleSave = (row: DataType, valid: boolean) => { + const newData = [...dataSource]; + const index = newData.findIndex((item) => row.uid === item.uid); + const item = newData[index]; + newData.splice(index, 1, { + ...item, + ...row, + new: false, + invalid: !valid, + }); + setDataSource(newData); + onChange(newData); + }; + + const components = { + body: { + row: EditableRow, + cell: EditableCell, + }, + }; + + const columns = defaultColumns.map((col) => { + if (!col.editable) { + return col; + } + return { + ...col, + onCell: (record: DataType) => ({ + record, + editable: col.editable, + dataIndex: col.dataIndex, + title: col.title, + required: col.required, + nodeType: col.nodeType, + handleSave, + }), + }; + }); + + return ( +
+ record.uid} + /> + + + ); +}; + +export default ArrayForm; diff --git a/frontend/src/pages/plugin/components/PluginDrawer/GlobalPluginDetail.tsx b/frontend/src/pages/plugin/components/PluginDrawer/GlobalPluginDetail.tsx index 49deb171..87bcd369 100644 --- a/frontend/src/pages/plugin/components/PluginDrawer/GlobalPluginDetail.tsx +++ b/frontend/src/pages/plugin/components/PluginDrawer/GlobalPluginDetail.tsx @@ -1,13 +1,17 @@ import CodeEditor from '@/components/CodeEditor'; -import { Alert, Divider, Form, Spin, Switch, message, Space, Typography } from 'antd'; +import { Alert, Form, Spin, Switch, message, Space, Typography, Input, Select, Divider, Tabs, Card } from 'antd'; import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react'; import * as servicesApi from '@/services'; import { useRequest } from 'ahooks'; -import { t } from 'i18next'; +import i18next, { t } from 'i18next'; import { useSearchParams } from 'ice'; +import ArrayForm from './ArrayForm'; +import yaml from 'js-yaml'; + const { Text } = Typography; +const { TabPane } = Tabs; export interface IPluginData { configurations: object; @@ -24,6 +28,7 @@ export interface IPropsData { name?: string; category: string; } + export interface IProps { data: IPropsData; onSuccess: () => void; @@ -34,9 +39,9 @@ const GlobalPluginDetail = forwardRef((props: IProps, ref) => { const { name: pluginName = '', category = '' } = data || {}; const [searchParams] = useSearchParams(); - const queryType: string = searchParams.get('type') || ''; const queryName: string = searchParams.get('name') || ''; + const [currentTabKey, setCurrentTabKey] = useState('form'); const isChangeExampleRaw = useMemo(() => { return ['route', 'domain'].includes(queryType) && category === 'auth'; @@ -64,6 +69,7 @@ const GlobalPluginDetail = forwardRef((props: IProps, ref) => { update: servicesApi.updateDomainPluginInstance.bind(servicesApi), }; } + return { get: servicesApi.getGlobalPluginInstance.bind(servicesApi), update: servicesApi.updateGlobalPluginInstance.bind(servicesApi), @@ -74,6 +80,7 @@ const GlobalPluginDetail = forwardRef((props: IProps, ref) => { const [pluginData, setPluginData] = useState(); const [configData, setConfigData] = useState(); + const [schema, setSchema] = useState(''); const [rawConfigurations, setRawConfigurations] = useState(''); const [defaultValue, setDefaultValue] = useState(''); @@ -81,22 +88,36 @@ const GlobalPluginDetail = forwardRef((props: IProps, ref) => { const { loading: getDataLoading, run: getData } = useRequest(pluginInstancesApi.get, { manual: true, onSuccess: (res: IPluginData) => { + setCurrentTabKey('form'); setPluginData(res); setRawConfigurations(res.rawConfigurations); setDefaultValue(res.rawConfigurations); getConfig(pluginName); + form.resetFields(); + if (res.rawConfigurations) { + form.setFieldsValue(yamlToFormValues(res.rawConfigurations)); + } }, }); + const { loading: getConfigLoading, run: getConfig } = useRequest(servicesApi.getWasmPluginsConfig, { manual: true, onSuccess: (res) => { setConfigData(res); + setSchema(res.schema); + if (!res.schema.jsonSchema.properties) { + setCurrentTabKey('yaml'); + } if (!defaultValue) { let exampleRaw = res?.schema?.extensions['x-example-raw']; if (isChangeExampleRaw) { - // 需要冒号后面加空格 + // Need a space after the colon exampleRaw = 'allow: []'; } + form.resetFields(); + if (exampleRaw) { + form.setFieldsValue(yamlToFormValues(exampleRaw)); + } setRawConfigurations(exampleRaw); setDefaultValue(exampleRaw); } @@ -114,6 +135,310 @@ const GlobalPluginDetail = forwardRef((props: IProps, ref) => { }, }); + const handleInputChange = (name, value) => { + form.setFieldValue(name, value); + }; + + const validateArrayTypes = (value) => { + const validTypes = ['string', 'integer', 'number', 'boolean']; + if (value.type !== 'object') { + return validTypes.includes(value.type); + } + if (value.properties) { + return Object.values(value.properties).every(property => { + return validTypes.includes(property.type); + }); + } + return false; + }; + + function getLocalizedText(obj: any, index: string, defaultText: string) { + const i18nObj = obj[`x-${index}-i18n`]; + return i18nObj && i18nObj[i18next.language] || obj[index] || defaultText || ''; + } + + function generateFields(scm, prefix = '') { + const properties = scm.properties; + const requiredFields = scm.required || []; + if (!properties) { + return
{t('misc.invalidSchema')}
; + } + return Object.entries(properties).map(([key, property]) => { + const fullKey = prefix ? `${prefix}.${key}` : key; + let translatedTitle = getLocalizedText(property, 'title', key); + let tip = null; + if ('description' in property) { + tip = getLocalizedText(property, 'description', property.description); + } + const isRequired = requiredFields.includes(key); + if (property.type === 'object' && property.properties) { + // If it's a nested object, recursively generate the sub-form + return ( + + {generateFields(property, fullKey)} + + ); + } + + const { type, title } = property; + let fieldComponent; + let validationRules = []; + if (isRequired && currentTabKey !== 'yaml') { + validationRules.push({ required: true, message: `${translatedTitle} ${t('misc.isRequired')}` }); + } + switch (type) { + case 'string': + fieldComponent = ( + handleInputChange(fullKey, e.target.value)} + /> + ); + break; + case 'integer': + fieldComponent = ( + handleInputChange(fullKey, parseInt(e.target.value, 10))} + /> + ); + break; + case 'number': + fieldComponent = ( + handleInputChange(fullKey, parseFloat(e.target.value))} + /> + ); + break; + case 'boolean': + fieldComponent = ( + + ); + break; + case 'array': + if (!validateArrayTypes(property.items)) { + throw new Error(`Unsupported array's type`); + } + validationRules.push({ + validator(_, value) { + if (Array.isArray(value) && value.some(i => !i.new && i.invalid)) { + return Promise.reject(); + } + return Promise.resolve(); + }, + }); + return ( + + + + ); + case 'object': + return; + default: + throw new Error(`Unsupported type: ${type}`); + } + + return ( + + {fieldComponent} + + ); + }); + } + + function formValuesToSchema(formValues) { + const result = {}; + const newFormValues = JSON.parse(JSON.stringify(formValues)); + formValues = processFormValues(newFormValues); + function buildObjectFromPath(path, value) { + const parts = path.split('.'); + let current = result; + for (let i = 0; i < parts.length - 1; i++) { + const part = parts[i]; + if (!current[part]) { + current[part] = {}; + } + current = current[part]; + } + current[parts[parts.length - 1]] = value; + } + + Object.entries(formValues).forEach(([key, value]) => { + if (value !== undefined) { + buildObjectFromPath(key, value); + } + }); + + return result; + } + + function schemaToYaml(obj, indent = ''): string { + let result = ''; + Object.entries(obj).forEach(([key, value]) => { + if (key === 'enabled') return; + if (value === null) { + result += `${indent}${key}: null\n`; + } else if (Array.isArray(value)) { + result += `${indent}${key}:\n`; + value.forEach((item, index) => { + if (typeof item === 'object' && !Array.isArray(item)) { + // Check if the object has only one key named "Item" + const keys = Object.keys(item); + if (keys.length === 1 && keys[0] === 'Item') { + result += `${indent} - ${quoteIfString(item.Item)}\n`; + } else { + // Handle the first key-value pair of the object directly following the '-' + let firstEntry = true; + result += `${indent} - `; + Object.entries(item).forEach(([innerKey, innerValue], i) => { + if (firstEntry) { + result += `${innerKey}: ${quoteIfString(innerValue)}`; + firstEntry = false; + } else { + result += `\n${indent} ${innerKey}: ${quoteIfString(innerValue)}`; + } + }); + result += '\n'; + } + } else { + result += `${indent} - ${quoteIfString(item)}\n`; + } + }); + } else if (typeof value === 'object') { + result += `${indent}${key}:\n${schemaToYaml(value, indent + ' ')}`; + } else { + result += `${indent}${key}: ${quoteIfString(value)}\n`; + } + }); + return result; + } + + function quoteIfString(value) { + if (typeof value === 'string') { + const escapedValue = JSON.stringify(value); + return escapedValue; + } + return value; + } + + function yamlToFormValues(yamlString) { + try { + const parsedObj = yaml.load(yamlString); + let uidCounter = 1; + const flattenObject = (obj, parentKey = '') => { + let flatResult = {}; + let currentUid = uidCounter; + Object.keys(obj).forEach(key => { + const newKey = parentKey ? `${parentKey}.${key}` : key; + if (Array.isArray(obj[key])) { + obj[key].forEach((item, index) => { + const uid = currentUid++; + if (typeof item === 'object' && item !== null) { + const newItem = { uid }; + Object.keys(item).forEach(subKey => { + newItem[subKey] = item[subKey]; + }); + flatResult[newKey] = flatResult[newKey] || []; + flatResult[newKey].push(newItem); + } else { + const newItem = { uid, Item: item }; + flatResult[newKey] = flatResult[newKey] || []; + flatResult[newKey].push(newItem); + } + }); + currentUid += obj[key].length; + } else if (typeof obj[key] === 'object' && obj[key] !== null) { + Object.assign(flatResult, flattenObject(obj[key], newKey)); + } else if (typeof obj[key] === 'boolean') { + flatResult[newKey] = obj[key]; + } else { + flatResult[newKey] = obj[key]; + } + }); + + return flatResult; + } + return flattenObject(parsedObj, ''); + } catch (error) { + console.error('Error parsing YAML:', error); + return null; + } + } + + function processFormValues(obj) { + if (Array.isArray(obj)) { + return obj.filter(item => { + if (item && typeof item === 'object' && !Array.isArray(item)) { + // Remove unnecessary fields for the YAML result + delete item.uid; + delete item.new; + delete item.invalid; + const keys = Object.keys(item); + const nonEmptyKeys = keys.filter(key => item[key] != null && item[key] !== ""); + if (nonEmptyKeys.length === 0) { + return false; + } + } + return true; + }).map(processFormValues); + } else if (typeof obj === 'object' && obj !== null) { + const newObj = {}; + Object.keys(obj).forEach(key => { + newObj[key] = processFormValues(obj[key]); + }); + return newObj; + } + return obj; + } + + function mergeValues(a, b) { + const result = { ...b }; + const newA = JSON.parse(JSON.stringify(a)); + a = processFormValues(newA); + Object.keys(a).forEach(key => { + // If the key in a exists in b and both are objects, then recursively merge them + if ( + a[key] != null && key in result && + typeof a[key] === 'object' && !Array.isArray(a[key]) && + typeof result[key] === 'object' && !Array.isArray(result[key]) + ) { + result[key] = mergeValues(a[key], result[key]); + } else if (!a[key] && a[key] !== false) { + delete result[key]; + } else { + result[key] = a[key]; + } + if (Array.isArray(a[key]) && a[key].length === 0) { + delete result[key]; + } + }); + return result; + } + const onSubmit = async () => { await form.validateFields(); const values = form.getFieldsValue(); @@ -141,6 +466,7 @@ const GlobalPluginDetail = forwardRef((props: IProps, ref) => { }; useEffect(() => { + resetForm(); if (isRoutePlugin || isDomainPlugin) { getData({ name: queryName, @@ -151,6 +477,38 @@ const GlobalPluginDetail = forwardRef((props: IProps, ref) => { getData(pluginName); }, [pluginName, queryName]); + const resetForm = () => { + // Reset the form and other states when the plugin selection changes + form.resetFields(); + setPluginData(undefined); + setConfigData(undefined); + setSchema(''); + setRawConfigurations(''); + setDefaultValue(''); + setCurrentTabKey('form'); + }; + + useEffect(() => { + if (currentTabKey === 'yaml') { + setDefaultValue(rawConfigurations); + } else if (currentTabKey === 'form') { + let en = form.getFieldsValue().enabled; + let formBefore = form.getFieldsValue(); + form.resetFields(); + if (rawConfigurations) { + if (yamlToFormValues(rawConfigurations) != null) { + form.setFieldsValue(yamlToFormValues(rawConfigurations)); + } else { + form.setFieldsValue(formBefore); + } + } + form.setFieldsValue({ + enabled: en, + }); + setDefaultValue(rawConfigurations); + } + }, [currentTabKey]); + useImperativeHandle(ref, () => ({ submit: onSubmit, })); @@ -162,23 +520,57 @@ const GlobalPluginDetail = forwardRef((props: IProps, ref) => { }; }, [isRoutePlugin, isDomainPlugin, queryName]); + const fieldChange = () => { + if (!getConfigLoading && !getDataLoading && currentTabKey === 'form') { + const values = form.getFieldsValue(); + const rawValues = yamlToFormValues(rawConfigurations); + const mergedValues = mergeValues(values, rawValues); + const scm = formValuesToSchema(mergedValues); + const yamlString = schemaToYaml(scm); + setRawConfigurations(yamlString); + } + }; + + const tryCatchRender = (scm) => { + try { + return generateFields(scm); + } catch (error) { + console.error(error); + return
{t('misc.invalidSchema')}
; + } + }; + return (
{alertStatus.isShow && ( )} -
+ - - {t('plugins.configForm.dataEditor')} - {!getConfigLoading && !getDataLoading && ( - setRawConfigurations(val)} /> - )} + setCurrentTabKey(key)}> + + {!getConfigLoading && !getDataLoading && schema && ( + tryCatchRender(schema.jsonSchema) + )} + + + {!getConfigLoading && !getDataLoading && ( + { + setRawConfigurations(val); + }} + /> + )} + + {!getConfigLoading && !getDataLoading && !isRoutePlugin && !isDomainPlugin && ( - + {t('plugins.configForm.globalConfigWarning')} )} diff --git a/frontend/src/pages/plugin/components/PluginDrawer/index.tsx b/frontend/src/pages/plugin/components/PluginDrawer/index.tsx index eaae5360..1c953fa2 100644 --- a/frontend/src/pages/plugin/components/PluginDrawer/index.tsx +++ b/frontend/src/pages/plugin/components/PluginDrawer/index.tsx @@ -1,11 +1,8 @@ import { Button, Drawer, Space } from 'antd'; - import { useImperativeHandle, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; - import GlobalPluginDetail from './GlobalPluginDetail'; import RoutePluginDetail from './RoutePluginDetail'; - import { getI18nValue } from '../../utils'; import Cors from '../Cors'; import HeaderModify from '../HeaderModify'; @@ -26,7 +23,6 @@ export default function PluginDrawer(props) { const globalPluginDetailRef = useRef<{ submit: () => {} }>(null); const [activePluginData, setActivePluginData] = useState({ title: '', key: '' }); - const [open, setOpen] = useState(false); const [loading, setLoading] = useState(false); @@ -91,4 +87,4 @@ export default function PluginDrawer(props) { )} ); -} +} \ No newline at end of file diff --git a/frontend/yarn.lock b/frontend/yarn.lock index f9a2df63..e9a57c17 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2384,6 +2384,16 @@ resolved "https://registry.npmmirror.com/@builder/swc-darwin-arm64/-/swc-darwin-arm64-0.1.3.tgz" integrity sha512-Sm69HjiM3bTFjWQqxpA6x9cnvK8c/RJfA9uyN5ypxAjEq8F9O1sV8qrzjmELUqdnSDcjG1DE3VFWNeyjgrA2Qg== +"@builder/swc-darwin-x64@^0.1.0": + version "0.1.3" + resolved "https://registry.npmmirror.com/@builder/swc-darwin-x64/-/swc-darwin-x64-0.1.3.tgz" + integrity sha512-SC4Mj1/nMurpDfT6TgydhfyOEraC77e6wYXpp6X+TbujYYXAXuDgTj682llNOfl79cU2ouBMk0flnGt37td7aA== + +"@builder/swc-linux-x64-gnu@^0.1.0": + version "0.1.3" + resolved "https://registry.npmmirror.com/@builder/swc-linux-x64-gnu/-/swc-linux-x64-gnu-0.1.3.tgz" + integrity sha512-YV2T5RFb19Lo2KzAuwIKRXyTxtLNxb/UfNuZ3xdNDLX5p8jaCw1U3X8q1sCY7phXcHz2w9drdXlK/om+0zPfjw== + "@builder/swc-loader@^1.0.0": version "1.0.1" resolved "https://registry.npmmirror.com/@builder/swc-loader/-/swc-loader-1.0.1.tgz" @@ -2392,6 +2402,11 @@ "@builder/swc" "^0.1.0" loader-utils "^2.0.0" +"@builder/swc-win32-x64-msvc@^0.1.0": + version "0.1.3" + resolved "https://registry.npmmirror.com/@builder/swc-win32-x64-msvc/-/swc-win32-x64-msvc-0.1.3.tgz" + integrity sha512-BAc63zk6gAm9kvG+lpnevDoeVD7l9QLpM9MYZjTN/UnHhh/zl2lVCVj+ivSI3LpJZNVMG6OLQtAYAtmWNT83cQ== + "@builder/swc@^0.1.0": version "0.1.3" resolved "https://registry.npmmirror.com/@builder/swc/-/swc-0.1.3.tgz" @@ -2616,11 +2631,121 @@ resolved "https://registry.npmmirror.com/@emotion/unitless/-/unitless-0.7.5.tgz" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== +"@esbuild/android-arm@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz" + integrity sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw== + +"@esbuild/android-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz" + integrity sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg== + +"@esbuild/android-x64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.16.17.tgz" + integrity sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ== + "@esbuild/darwin-arm64@0.16.17": version "0.16.17" resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz" integrity sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w== +"@esbuild/darwin-x64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz" + integrity sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg== + +"@esbuild/freebsd-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz" + integrity sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw== + +"@esbuild/freebsd-x64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz" + integrity sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug== + +"@esbuild/linux-arm@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz" + integrity sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ== + +"@esbuild/linux-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz" + integrity sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g== + +"@esbuild/linux-ia32@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz" + integrity sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg== + +"@esbuild/linux-loong64@0.14.54": + version "0.14.54" + resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz" + integrity sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw== + +"@esbuild/linux-loong64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz" + integrity sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ== + +"@esbuild/linux-mips64el@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz" + integrity sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw== + +"@esbuild/linux-ppc64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz" + integrity sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g== + +"@esbuild/linux-riscv64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz" + integrity sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw== + +"@esbuild/linux-s390x@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz" + integrity sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w== + +"@esbuild/linux-x64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz" + integrity sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw== + +"@esbuild/netbsd-x64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz" + integrity sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA== + +"@esbuild/openbsd-x64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz" + integrity sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg== + +"@esbuild/sunos-x64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz" + integrity sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw== + +"@esbuild/win32-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz" + integrity sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw== + +"@esbuild/win32-ia32@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz" + integrity sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig== + +"@esbuild/win32-x64@0.16.17": + version "0.16.17" + resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz" + integrity sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q== + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" @@ -3552,6 +3677,51 @@ resolved "https://registry.npmmirror.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.19.tgz" integrity sha512-6xLtmXzS4nNWGQkajbiAjGXspUJfxS2IWoGQ16J9nfOFdttKyoIG5o5+mxUfKeg5bXw9cI+r675kN/irx3z7MQ== +"@swc/core-darwin-x64@1.3.19": + version "1.3.19" + resolved "https://registry.npmmirror.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.19.tgz" + integrity sha512-qCDQcngYBeWrsNS1kcBslRD0dahKcYKaUUWRC9yHpRcs3SRvnSpJyWQR4y9RCdO9YNmixJ9+5+zPD9qcgL7jBw== + +"@swc/core-linux-arm-gnueabihf@1.3.19": + version "1.3.19" + resolved "https://registry.npmmirror.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.19.tgz" + integrity sha512-ufbKW6Lhii1+kVCXnsHgqYIpRvXhPjdhMudfP4KKVgJtT6TsdEIr+KRAQIBHLjRUsTKA2DLsGEpu9jfjwFiNEg== + +"@swc/core-linux-arm64-gnu@1.3.19": + version "1.3.19" + resolved "https://registry.npmmirror.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.19.tgz" + integrity sha512-HHhqLRZv9Ss8orJrlEP4XRcLuqLDwFtGgbtHU8kyWBmQEtK42uT18Pf5RJBo5sPJHY8m5EO8C8y3hIbGmKtLyg== + +"@swc/core-linux-arm64-musl@1.3.19": + version "1.3.19" + resolved "https://registry.npmmirror.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.19.tgz" + integrity sha512-vipnF3C6T1368uHQqz8RpdszWxxGh0X8VBK3TdTOSWvI/duNZtZXEOZlB2Nh9w+u09umVw0MsJhvg86Aon39mA== + +"@swc/core-linux-x64-gnu@1.3.19": + version "1.3.19" + resolved "https://registry.npmmirror.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.19.tgz" + integrity sha512-dUbq8mnIqBhU7OppfY3ncOvl26691WFGxd97QtnnlfMZrKnaofKFMIxE9sTHOLSbBo16AylnEMiwa45w2UWDEg== + +"@swc/core-linux-x64-musl@1.3.19": + version "1.3.19" + resolved "https://registry.npmmirror.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.19.tgz" + integrity sha512-RiVZrlkNGcj9jZyjF7YFOW3fj9fWPC25AYkknLpWxAmLQcp1piAWj+aSixmMWUC4QJau78VZzcm+kRgIOECALw== + +"@swc/core-win32-arm64-msvc@1.3.19": + version "1.3.19" + resolved "https://registry.npmmirror.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.19.tgz" + integrity sha512-r2U6GC+go2iiLx5JBZIJswYFiMv0yOsm+pgE1srVvAc8dP02320t9yh0Uj4Sr2hDipTWJ33Y5PMZwEsZSfBVbQ== + +"@swc/core-win32-ia32-msvc@1.3.19": + version "1.3.19" + resolved "https://registry.npmmirror.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.19.tgz" + integrity sha512-SPpESDa4vr0PRvUiqXSi8oZSTmkDOGrZ/pSiLD7ISgjsQ5RQMbPkuEK0ztWljim87q2fO0bGVVhyaVYxdOVS1A== + +"@swc/core-win32-x64-msvc@1.3.19": + version "1.3.19" + resolved "https://registry.npmmirror.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.19.tgz" + integrity sha512-0X5HqFC1wQlheOQDZeF6KNOSURZKkGISNK3aTSmTq9g7dDJ/kTcVjsdKbu2rK4ibCnlC9IS0cLK9FpROnsVPwA== + "@swc/core@1.3.19": version "1.3.19" resolved "https://registry.npmmirror.com/@swc/core/-/core-1.3.19.tgz" @@ -3844,6 +4014,11 @@ resolved "https://registry.npmmirror.com/@types/js-cookie/-/js-cookie-2.2.7.tgz" integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== +"@types/js-yaml@^4.0.9": + version "4.0.9" + resolved "https://registry.npmmirror.com/@types/js-yaml/-/js-yaml-4.0.9.tgz" + integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg== + "@types/json-schema@*", "@types/json-schema@^7.0.0", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz" @@ -5559,9 +5734,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001431, caniuse-lite@^1.0.30001434, caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464: - version "1.0.30001509" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz" - integrity sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA== + version "1.0.30001651" + resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz" + integrity sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg== case-sensitive-paths-webpack-plugin@^2.4.0: version "2.4.0" @@ -7219,11 +7394,106 @@ es6-promise@^4.1.1: resolved "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== +esbuild-android-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz" + integrity sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ== + +esbuild-android-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz" + integrity sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg== + +esbuild-darwin-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz" + integrity sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug== + esbuild-darwin-arm64@0.14.54: version "0.14.54" resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz" integrity sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw== +esbuild-freebsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz" + integrity sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg== + +esbuild-freebsd-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz" + integrity sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q== + +esbuild-linux-32@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz" + integrity sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw== + +esbuild-linux-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz" + integrity sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg== + +esbuild-linux-arm@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz" + integrity sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw== + +esbuild-linux-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz" + integrity sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig== + +esbuild-linux-mips64le@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz" + integrity sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw== + +esbuild-linux-ppc64le@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz" + integrity sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ== + +esbuild-linux-riscv64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz" + integrity sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg== + +esbuild-linux-s390x@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz" + integrity sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA== + +esbuild-netbsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz" + integrity sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w== + +esbuild-openbsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz" + integrity sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw== + +esbuild-sunos-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz" + integrity sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw== + +esbuild-windows-32@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz" + integrity sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w== + +esbuild-windows-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz" + integrity sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ== + +esbuild-windows-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz" + integrity sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg== + esbuild@^0.14.22: version "0.14.54" resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz"