diff --git a/.gitignore b/.gitignore index 04a7b2685..b3e42a14f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ # dependencies /packages/*/node_modules -/scripts/*/node_modules +/scripts/**/node_modules /node_modules /.pnpm-store /.pnp @@ -41,4 +41,4 @@ yarn-error.log* /packages/icons/.dumi/tmp* docs-dist docs-dist.tar.gz -es \ No newline at end of file +es diff --git a/package.json b/package.json index 8a8cbe422..a9bc43e07 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "build": "pnpm --filter base build", "build:ee": "pnpm --filter base build:ee", "build:demo": "pnpm --filter base build:demo", - "prettier:w": "prettier -w packages/*/src/ packages/*/lib/", - "prettier:c": "prettier -c packages/*/src/ packages/*/lib/", - "eslint": "eslint packages/*/src/ packages/*/lib/", + "prettier:w": "prettier -w packages/*/src/ packages/*/lib/ scripts/cli/*/src", + "prettier:c": "prettier -c packages/*/src/ packages/*/lib/ scripts/cli/*/src", + "eslint": "eslint packages/*/src/ packages/*/lib/ scripts/cli/*/src", "stylelint": "stylelint packages/*/{src,lib}/**/{*.less,style.ts,element.ts}", "ts-check": "tsc --noEmit", "checker": "pnpm ts-check && pnpm eslint && pnpm stylelint && pnpm prettier:c", @@ -26,11 +26,13 @@ "icon:docs:g": "pnpm --filter @actiontech/icons docs:g", "icon:docs": "pnpm --filter @actiontech/icons start", "icon:docs:build": "pnpm --filter @actiontech/icons docs:build", - "icon:build": "pnpm --filter @actiontech/icons build" + "icon:build": "pnpm --filter @actiontech/icons build", + "dms:g": "pnpm --filter @actiontech/cli-create-dms-page build && create-dms-page" }, "keywords": [], "author": "", "devDependencies": { + "@actiontech/cli-create-dms-page": "workspace:^", "@cfaester/enzyme-adapter-react-18": "^0.7.0", "@testing-library/dom": "9.3.4", "@testing-library/jest-dom": "6.4.2", diff --git a/packages/base/src/locale/zh-CN/dmsMenu.ts b/packages/base/src/locale/zh-CN/dmsMenu.ts index 6462ac620..2b58571bd 100644 --- a/packages/base/src/locale/zh-CN/dmsMenu.ts +++ b/packages/base/src/locale/zh-CN/dmsMenu.ts @@ -1,3 +1,4 @@ +// @warn/cli/create-dms-page // eslint-disable-next-line import/no-anonymous-default-export export default { projectOverview: '项目概览', diff --git a/packages/base/src/locale/zh-CN/index.ts b/packages/base/src/locale/zh-CN/index.ts index 1f60afb8f..f715c66cd 100644 --- a/packages/base/src/locale/zh-CN/index.ts +++ b/packages/base/src/locale/zh-CN/index.ts @@ -1,3 +1,4 @@ +// @warn/cli/create-dms-page import dmsLogin from './dmsLogin'; import dmsHome from './dmsHome'; import dmsLayout from './dmsLayout'; diff --git a/packages/base/src/page/Nav/SideMenu/MenuList/menus/base.tsx b/packages/base/src/page/Nav/SideMenu/MenuList/menus/base.tsx index 111301fb7..28292ae5a 100644 --- a/packages/base/src/page/Nav/SideMenu/MenuList/menus/base.tsx +++ b/packages/base/src/page/Nav/SideMenu/MenuList/menus/base.tsx @@ -1,3 +1,5 @@ +// @warn/cli/create-dms-page + import { MemberFilled, ExportFilled, diff --git a/packages/base/src/page/Nav/SideMenu/MenuList/menus/index.type.ts b/packages/base/src/page/Nav/SideMenu/MenuList/menus/index.type.ts index 4cb9f01a0..0a7f8c901 100644 --- a/packages/base/src/page/Nav/SideMenu/MenuList/menus/index.type.ts +++ b/packages/base/src/page/Nav/SideMenu/MenuList/menus/index.type.ts @@ -1,3 +1,5 @@ +// @warn/cli/create-dms-page + import { PermissionsConstantType } from '@actiontech/shared/lib/global'; import { ItemType } from 'antd/es/menu/hooks/useItems'; @@ -21,11 +23,13 @@ export type MenuStructTreeType = Array< export type GenerateMenuItemType = (projectID: string) => CustomMenuItemType; -export type MenuStructTreeKey = +type BaseMenuStructTreeKey = | 'instance' | 'member' | 'cloud-beaver' - | 'data-export' + | 'data-export'; + +type SqleMenuStructTreeKey = | 'project-overview' | 'sql-audit' | 'plugin-audit' @@ -42,3 +46,5 @@ export type MenuStructTreeKey = | 'pipeline-configuration' | 'version-management' | 'data-source-comparison'; + +export type MenuStructTreeKey = BaseMenuStructTreeKey | SqleMenuStructTreeKey; diff --git a/packages/base/src/page/Nav/SideMenu/MenuList/menus/menu.data.tsx b/packages/base/src/page/Nav/SideMenu/MenuList/menus/menu.data.tsx index 092e2e599..8e4e9d3ad 100644 --- a/packages/base/src/page/Nav/SideMenu/MenuList/menus/menu.data.tsx +++ b/packages/base/src/page/Nav/SideMenu/MenuList/menus/menu.data.tsx @@ -1,3 +1,4 @@ +// @warn/cli/create-dms-page import { t } from '../../../../../locale'; import { MenuStructTreeType } from './index.type'; import { genMenuItemsWithMenuStructTree } from './common'; diff --git a/packages/base/src/page/Nav/SideMenu/MenuList/menus/sqle.tsx b/packages/base/src/page/Nav/SideMenu/MenuList/menus/sqle.tsx index d0540a6f0..342f2ecce 100644 --- a/packages/base/src/page/Nav/SideMenu/MenuList/menus/sqle.tsx +++ b/packages/base/src/page/Nav/SideMenu/MenuList/menus/sqle.tsx @@ -1,3 +1,5 @@ +// @warn/cli/create-dms-page + import { SIDE_MENU_DATA_PLACEHOLDER_KEY } from './common'; import { t } from '../../../../../locale'; import { GenerateMenuItemType } from './index.type'; diff --git a/packages/base/src/router/router.base.tsx b/packages/base/src/router/router.base.tsx index 9fd23717a..6bd637588 100644 --- a/packages/base/src/router/router.base.tsx +++ b/packages/base/src/router/router.base.tsx @@ -1,60 +1,69 @@ +// @warn/cli/create-dms-page import { PERMISSIONS } from '@actiontech/shared/lib/global'; import { ROUTE_PATHS } from '@actiontech/shared/lib/data/routePaths'; import { RouterConfigItem } from '@actiontech/shared/lib/types/common.type'; -import { lazy } from 'react'; - +import React from 'react'; // #if [ee] -const Project = lazy(() => import('../page/Project')); -const ImportProject = lazy(() => import('../page/Project/ImportProject')); -const ProjectBatchImportDataSource = lazy( +const Project = React.lazy(() => import('../page/Project')); +const ImportProject = React.lazy(() => import('../page/Project/ImportProject')); +const ProjectBatchImportDataSource = React.lazy( () => import('../page/Project/BatchImportDataSource') ); -const ExportTaskList = lazy(() => import('../page/DataExportManagement/List')); -const CreateExportTask = lazy( +const ExportTaskList = React.lazy( + () => import('../page/DataExportManagement/List') +); +const CreateExportTask = React.lazy( () => import('../page/DataExportManagement/Create') ); -const ExportTaskDetail = lazy( +const ExportTaskDetail = React.lazy( () => import('../page/DataExportManagement/Detail') ); -const AddSyncTask = lazy(() => import('../page/SyncDataSource/AddPage')); -const UpdateSyncTask = lazy(() => import('../page/SyncDataSource/UpdatePage')); -const BatchImportDataSource = lazy( +const AddSyncTask = React.lazy(() => import('../page/SyncDataSource/AddPage')); +const UpdateSyncTask = React.lazy( + () => import('../page/SyncDataSource/UpdatePage') +); +const BatchImportDataSource = React.lazy( () => import('../page/DataSource/components/BatchImportDataSource') ); -const GlobalBatchImportDataSource = lazy( +const GlobalBatchImportDataSource = React.lazy( () => import('../page/GlobalDataSource/BatchImportDataSource') ); -const GlobalAddDataSource = lazy( +const GlobalAddDataSource = React.lazy( () => import('../page/DataSource/components/AddDataSource') ); // #endif -const Home = lazy(() => import('../page/Home')); -const UserCenter = lazy(() => import('../page/UserCenter')); -const DataSource = lazy(() => import('../page/DataSource')); -const AddDataSource = lazy( +const Home = React.lazy(() => import('../page/Home')); +const UserCenter = React.lazy(() => import('../page/UserCenter')); +const DataSource = React.lazy(() => import('../page/DataSource')); +const AddDataSource = React.lazy( () => import('../page/DataSource/components/AddDataSource') ); -const UpdateDataSource = lazy( +const UpdateDataSource = React.lazy( () => import('../page/DataSource/components/UpdateDataSource') ); -const DataSourceList = lazy(() => import('../page/DataSource/components/List')); +const DataSourceList = React.lazy( + () => import('../page/DataSource/components/List') +); -const Member = lazy(() => import('../page/Member')); -const ProjectDetail = lazy(() => import('../page/Project/Detail')); -const System = lazy(() => import('../page/System')); +const Member = React.lazy(() => import('../page/Member')); +const System = React.lazy(() => import('../page/System')); -const CloudBeaver = lazy(() => import('../page/CloudBeaver')); -const Account = lazy(() => import('../page/Account')); -const ExportTaskManagement = lazy(() => import('../page/DataExportManagement')); -const DataSourceManagement = lazy(() => import('../page/DataSourceManagement')); +const CloudBeaver = React.lazy(() => import('../page/CloudBeaver')); +const Account = React.lazy(() => import('../page/Account')); +const ExportTaskManagement = React.lazy( + () => import('../page/DataExportManagement') +); +const DataSourceManagement = React.lazy( + () => import('../page/DataSourceManagement') +); -const Transit = lazy(() => import('../page/Transit')); +const Transit = React.lazy(() => import('../page/Transit')); -export const BaseRouterConfig: RouterConfigItem[] = [ +export const BaseGlobalRouterConfig: RouterConfigItem[] = [ { path: ROUTE_PATHS.BASE.HOME, key: 'home', @@ -144,77 +153,73 @@ export const BaseRouterConfig: RouterConfigItem[] = [ element: } ] - }, + } // #endif +]; +export const BaseProjectRouterConfig: RouterConfigItem[] = [ + { + path: ROUTE_PATHS.BASE.MEMBER.index.path, + key: 'member', + element: + }, { - key: 'projectDetail', - path: ROUTE_PATHS.BASE.PROJECT_DETAIL, - element: , + path: ROUTE_PATHS.BASE.DATA_SOURCE.index.path, + key: 'dataSource', + element: , children: [ { - path: ROUTE_PATHS.BASE.MEMBER.index.path, - key: 'member', - element: + index: true, + element: , + key: 'dataSourceList' + }, + { + path: ROUTE_PATHS.BASE.DATA_SOURCE.create.path, + element: , + key: 'dataSourceCreate' }, { - path: ROUTE_PATHS.BASE.DATA_SOURCE.index.path, - key: 'dataSource', - element: , - children: [ - { - index: true, - element: , - key: 'dataSourceList' - }, - { - path: ROUTE_PATHS.BASE.DATA_SOURCE.create.path, - element: , - key: 'dataSourceCreate' - }, - { - path: ROUTE_PATHS.BASE.DATA_SOURCE.update.path, - element: , - key: 'dataSourceUpdate' - }, - // #if [ee] - { - path: ROUTE_PATHS.BASE.DATA_SOURCE.batch_import.path, - element: , - key: 'batchImportDataSource' - } - // #endif - ] + path: ROUTE_PATHS.BASE.DATA_SOURCE.update.path, + element: , + key: 'dataSourceUpdate' }, + // #if [ee] + { + path: ROUTE_PATHS.BASE.DATA_SOURCE.batch_import.path, + element: , + key: 'batchImportDataSource' + } + // #endif + ] + }, + { + path: ROUTE_PATHS.BASE.DATA_EXPORT.index.path, + key: 'dataExportManagement', + element: , + // #if [ee] + children: [ { - path: ROUTE_PATHS.BASE.DATA_EXPORT.index.path, + index: true, key: 'dataExportManagement', - element: , - // #if [ee] - children: [ - { - index: true, - key: 'dataExportManagement', - element: - }, - { - path: ROUTE_PATHS.BASE.DATA_EXPORT.create.path, - element: , - key: 'CreateExportTask' - }, - { - path: ROUTE_PATHS.BASE.DATA_EXPORT.detail.path, - element: , - key: 'ExportTaskDetail' - } - ] - // #endif + element: + }, + { + path: ROUTE_PATHS.BASE.DATA_EXPORT.create.path, + element: , + key: 'CreateExportTask' }, { - path: ROUTE_PATHS.BASE.CLOUD_BEAVER.index.path, - key: 'cloudBeaver', - element: + path: ROUTE_PATHS.BASE.DATA_EXPORT.detail.path, + element: , + key: 'ExportTaskDetail' } ] + + // #endif + }, + { + path: ROUTE_PATHS.BASE.CLOUD_BEAVER.index.path, + key: 'cloudBeaver', + element: } ]; diff --git a/packages/base/src/router/router.tsx b/packages/base/src/router/router.tsx index 29179a2b9..f3ee13b1a 100644 --- a/packages/base/src/router/router.tsx +++ b/packages/base/src/router/router.tsx @@ -1,7 +1,7 @@ import { Navigate, RouteObject } from 'react-router-dom'; import { RouterConfigItem } from '@actiontech/shared/lib/types/common.type'; import { lazy } from 'react'; -import { BaseRouterConfig } from './router.base'; +import { BaseGlobalRouterConfig, BaseProjectRouterConfig } from './router.base'; import { ROUTE_PATHS } from '@actiontech/shared/lib/data/routePaths'; // #if [sqle] @@ -14,12 +14,18 @@ import { const ProjectDetail = lazy(() => import('../page/Project/Detail')); export const AuthRouterConfig: RouterConfigItem[] = [ - ...BaseRouterConfig, + ...BaseGlobalRouterConfig, + { + key: 'projectDetail', + path: ROUTE_PATHS.BASE.PROJECT_DETAIL, + element: , + children: BaseProjectRouterConfig + }, // #if [sqle] ...SQLEGlobalRouterConfig, { - key: 'projectDetail', + key: 'sqleProjectDetail', path: ROUTE_PATHS.BASE.SQLE_PROJECT_DETAIL, element: , children: SQLEProjectDetailRouterConfig diff --git a/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap index dbfb5fce5..06e8fb076 100644 --- a/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap @@ -201,7 +201,7 @@ exports[`base/router-base-ee render base route data snap 1`] = ` "path": ":projectID/cloud-beaver", }, ], - "element": , + "element": , "key": "projectDetail", "path": "/project/*", }, diff --git a/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap index bf9f0fad9..863fdc41b 100644 --- a/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap @@ -100,7 +100,7 @@ exports[`base/router-base-ce render base route data snap 1`] = ` "path": ":projectID/cloud-beaver", }, ], - "element": , + "element": , "key": "projectDetail", "path": "/project/*", }, diff --git a/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap index 1747e7fdd..a8d0a4540 100644 --- a/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap @@ -997,7 +997,7 @@ exports[`base/router-sqle-ce render sqle route data snap 1`] = ` }, ], "element": , - "key": "projectDetail", + "key": "sqleProjectDetail", "path": "/sqle/project/*", }, { diff --git a/packages/base/src/router/test/data.tsx b/packages/base/src/router/test/data.tsx index b57dd5039..996e645a4 100644 --- a/packages/base/src/router/test/data.tsx +++ b/packages/base/src/router/test/data.tsx @@ -1,10 +1,23 @@ import { RouteObject, useRoutes, Outlet } from 'react-router-dom'; import { RouterConfigItem } from '@actiontech/shared/lib/types/common.type'; import { AuthRouterConfig, unAuthRouterConfig } from '../router'; -import { BaseRouterConfig } from '../router.base'; +import { + BaseGlobalRouterConfig, + BaseProjectRouterConfig +} from '../router.base'; +import { ROUTE_PATHS } from '@actiontech/shared/lib/data/routePaths'; +import ProjectDetail from '../../page/Project/Detail'; const routeData = { - base: BaseRouterConfig, + base: [ + ...BaseGlobalRouterConfig, + { + key: 'projectDetail', + path: ROUTE_PATHS.BASE.PROJECT_DETAIL, + element: , + children: BaseProjectRouterConfig + } + ], sqle: AuthRouterConfig, unAuth: unAuthRouterConfig }; diff --git a/packages/sqle/src/locale/zh-CN/index.ts b/packages/sqle/src/locale/zh-CN/index.ts index 8e1c0fa2b..f28dc0c9a 100644 --- a/packages/sqle/src/locale/zh-CN/index.ts +++ b/packages/sqle/src/locale/zh-CN/index.ts @@ -1,3 +1,5 @@ +// @warn/cli/create-dms-page + import audit from './audit'; import dashboard from './dashboard'; import menu from './menu'; diff --git a/packages/sqle/src/router/config.tsx b/packages/sqle/src/router/config.tsx index 460ce3dc3..f9530ec2f 100644 --- a/packages/sqle/src/router/config.tsx +++ b/packages/sqle/src/router/config.tsx @@ -1,3 +1,5 @@ +// @warn/cli/create-dms-page + import React from 'react'; import { Navigate } from 'react-router-dom'; import { RouterConfigItem } from '@actiontech/shared/lib/types/common.type'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 64aded0e0..95b51720c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -122,6 +122,9 @@ importers: specifier: ^12.2.4 version: 12.2.4 devDependencies: + '@actiontech/cli-create-dms-page': + specifier: workspace:^ + version: link:scripts/cli/create-dms-page '@cfaester/enzyme-adapter-react-18': specifier: ^0.7.0 version: 0.7.0(enzyme@3.11.0)(react-dom@18.2.0)(react@18.2.0) @@ -307,7 +310,7 @@ importers: version: 8.1.0 dumi: specifier: ^2.3.8 - version: 2.3.8(@babel/core@7.24.6)(@types/node@18.15.11)(@types/react@18.0.15)(eslint@8.38.0)(jest@29.1.2)(postcss-less@6.0.0)(prettier@2.8.7)(react-dom@18.2.0)(react@18.2.0)(stylelint@14.16.1)(typescript@5.4.3)(webpack@5.92.0) + version: 2.3.8(@babel/core@7.24.6)(@types/node@18.15.11)(@types/react@18.0.15)(eslint@8.38.0)(jest@29.1.2)(postcss-less@6.0.0)(prettier@3.3.3)(react-dom@18.2.0)(react@18.2.0)(stylelint@14.16.1)(typescript@5.4.3)(webpack@5.92.0) father: specifier: ^4.1.0 version: 4.1.0(webpack@5.92.0) @@ -352,6 +355,46 @@ importers: specifier: ^2.2.0 version: 2.2.0 + scripts/cli/create-dms-page: + dependencies: + '@babel/generator': + specifier: ^7.25.0 + version: 7.25.0 + '@babel/parser': + specifier: ^7.24.8 + version: 7.24.8 + '@babel/traverse': + specifier: ^7.24.8 + version: 7.24.8 + '@babel/types': + specifier: ^7.24.9 + version: 7.24.9 + '@inquirer/prompts': + specifier: ^5.1.2 + version: 5.1.2 + chalk: + specifier: ^4.1.2 + version: 4.1.2 + commander: + specifier: ^12.1.0 + version: 12.1.0 + node-clipboardy: + specifier: ^1.0.3 + version: 1.0.3 + prettier: + specifier: ^3.3.3 + version: 3.3.3 + zod: + specifier: ^3.23.8 + version: 3.23.8 + devDependencies: + '@types/babel__generator': + specifier: ^7.6.8 + version: 7.6.8 + '@types/babel__traverse': + specifier: ^7.20.6 + version: 7.20.6 + packages: /@adobe/css-tools@4.3.2: @@ -666,6 +709,14 @@ packages: '@babel/highlight': 7.24.6 picocolors: 1.0.0 + /@babel/code-frame@7.26.2: + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.0.0 + /@babel/compat-data@7.24.6: resolution: {integrity: sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==} engines: {node: '>=6.9.0'} @@ -675,15 +726,15 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.24.6 - '@babel/generator': 7.24.6 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.25.0 '@babel/helper-compilation-targets': 7.24.6 '@babel/helper-module-transforms': 7.24.6(@babel/core@7.23.6) '@babel/helpers': 7.24.6 - '@babel/parser': 7.24.6 - '@babel/template': 7.24.6 - '@babel/traverse': 7.24.6 - '@babel/types': 7.24.6 + '@babel/parser': 7.24.8 + '@babel/template': 7.25.9 + '@babel/traverse': 7.24.8 + '@babel/types': 7.24.9 convert-source-map: 2.0.0 debug: 4.3.4 gensync: 1.0.0-beta.2 @@ -699,14 +750,14 @@ packages: dependencies: '@ampproject/remapping': 2.2.1 '@babel/code-frame': 7.24.6 - '@babel/generator': 7.24.6 + '@babel/generator': 7.25.0 '@babel/helper-compilation-targets': 7.24.6 '@babel/helper-module-transforms': 7.24.6(@babel/core@7.24.3) '@babel/helpers': 7.24.6 - '@babel/parser': 7.24.6 + '@babel/parser': 7.24.8 '@babel/template': 7.24.6 - '@babel/traverse': 7.24.6 - '@babel/types': 7.24.6 + '@babel/traverse': 7.24.8 + '@babel/types': 7.24.9 convert-source-map: 2.0.0 debug: 4.3.4 gensync: 1.0.0-beta.2 @@ -722,14 +773,14 @@ packages: dependencies: '@ampproject/remapping': 2.2.1 '@babel/code-frame': 7.24.6 - '@babel/generator': 7.24.6 + '@babel/generator': 7.25.0 '@babel/helper-compilation-targets': 7.24.6 '@babel/helper-module-transforms': 7.24.6(@babel/core@7.24.6) '@babel/helpers': 7.24.6 - '@babel/parser': 7.24.6 + '@babel/parser': 7.24.8 '@babel/template': 7.24.6 - '@babel/traverse': 7.24.6 - '@babel/types': 7.24.6 + '@babel/traverse': 7.24.8 + '@babel/types': 7.24.9 convert-source-map: 2.0.0 debug: 4.3.4 gensync: 1.0.0-beta.2 @@ -769,18 +820,18 @@ packages: /@babel/generator@7.2.0: resolution: {integrity: sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 jsesc: 2.5.2 lodash: 4.17.21 source-map: 0.5.7 trim-right: 1.0.1 dev: true - /@babel/generator@7.24.6: - resolution: {integrity: sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==} + /@babel/generator@7.25.0: + resolution: {integrity: sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.26.0 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 @@ -789,19 +840,19 @@ packages: resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-annotate-as-pure@7.24.6: resolution: {integrity: sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-builder-binary-assignment-operator-visitor@7.24.6: resolution: {integrity: sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-compilation-targets@7.24.6: resolution: {integrity: sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==} @@ -821,13 +872,13 @@ packages: dependencies: '@babel/core': 7.24.6 '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-function-name': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 '@babel/helper-member-expression-to-functions': 7.24.6 '@babel/helper-optimise-call-expression': 7.24.6 '@babel/helper-replace-supers': 7.24.6(@babel/core@7.24.6) '@babel/helper-skip-transparent-expression-wrappers': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 + '@babel/helper-split-export-declaration': 7.24.7 semver: 6.3.1 /@babel/helper-create-class-features-plugin@7.24.6(@babel/core@7.24.6): @@ -838,13 +889,13 @@ packages: dependencies: '@babel/core': 7.24.6 '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-function-name': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 '@babel/helper-member-expression-to-functions': 7.24.6 '@babel/helper-optimise-call-expression': 7.24.6 '@babel/helper-replace-supers': 7.24.6(@babel/core@7.24.6) '@babel/helper-skip-transparent-expression-wrappers': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 + '@babel/helper-split-export-declaration': 7.24.7 semver: 6.3.1 /@babel/helper-create-regexp-features-plugin@7.24.6(@babel/core@7.24.6): @@ -887,40 +938,42 @@ packages: transitivePeerDependencies: - supports-color - /@babel/helper-environment-visitor@7.24.6: - resolution: {integrity: sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==} + /@babel/helper-environment-visitor@7.24.7: + resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.9 - /@babel/helper-function-name@7.24.6: - resolution: {integrity: sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==} + /@babel/helper-function-name@7.24.7: + resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/template': 7.24.6 - '@babel/types': 7.24.6 + '@babel/template': 7.25.9 + '@babel/types': 7.24.9 - /@babel/helper-hoist-variables@7.24.6: - resolution: {integrity: sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==} + /@babel/helper-hoist-variables@7.24.7: + resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-member-expression-to-functions@7.24.6: resolution: {integrity: sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-module-imports@7.22.15: resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-module-imports@7.24.6: resolution: {integrity: sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-module-transforms@7.24.6(@babel/core@7.23.6): resolution: {integrity: sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==} @@ -929,11 +982,11 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.23.6 - '@babel/helper-environment-visitor': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-module-imports': 7.24.6 '@babel/helper-simple-access': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-validator-identifier': 7.25.9 dev: true /@babel/helper-module-transforms@7.24.6(@babel/core@7.24.3): @@ -943,11 +996,11 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.24.3 - '@babel/helper-environment-visitor': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-module-imports': 7.24.6 '@babel/helper-simple-access': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-validator-identifier': 7.25.9 dev: true /@babel/helper-module-transforms@7.24.6(@babel/core@7.24.6): @@ -957,17 +1010,17 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-module-imports': 7.24.6 '@babel/helper-simple-access': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-validator-identifier': 7.25.9 /@babel/helper-optimise-call-expression@7.24.6: resolution: {integrity: sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-plugin-utils@7.22.5: resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} @@ -986,7 +1039,7 @@ packages: dependencies: '@babel/core': 7.24.6 '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-wrap-function': 7.24.6 /@babel/helper-replace-supers@7.22.20(@babel/core@7.24.6): @@ -996,7 +1049,7 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-member-expression-to-functions': 7.24.6 '@babel/helper-optimise-call-expression': 7.24.6 @@ -1007,7 +1060,7 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-member-expression-to-functions': 7.24.6 '@babel/helper-optimise-call-expression': 7.24.6 @@ -1015,38 +1068,38 @@ packages: resolution: {integrity: sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-skip-transparent-expression-wrappers@7.22.5: resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-skip-transparent-expression-wrappers@7.24.6: resolution: {integrity: sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/helper-split-export-declaration@7.22.6: resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 - /@babel/helper-split-export-declaration@7.24.6: - resolution: {integrity: sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==} + /@babel/helper-split-export-declaration@7.24.7: + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 - /@babel/helper-string-parser@7.24.6: - resolution: {integrity: sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==} + /@babel/helper-string-parser@7.25.9: + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier@7.24.6: - resolution: {integrity: sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==} + /@babel/helper-validator-identifier@7.25.9: + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} /@babel/helper-validator-option@7.24.6: @@ -1057,22 +1110,22 @@ packages: resolution: {integrity: sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-function-name': 7.24.6 - '@babel/template': 7.24.6 - '@babel/types': 7.24.6 + '@babel/helper-function-name': 7.24.7 + '@babel/template': 7.25.9 + '@babel/types': 7.24.9 /@babel/helpers@7.24.6: resolution: {integrity: sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.24.6 - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/highlight@7.18.6: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-validator-identifier': 7.25.9 chalk: 2.4.2 js-tokens: 4.0.0 dev: true @@ -1081,17 +1134,24 @@ packages: resolution: {integrity: sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-validator-identifier': 7.25.9 chalk: 2.4.2 js-tokens: 4.0.0 picocolors: 1.0.0 - /@babel/parser@7.24.6: - resolution: {integrity: sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==} + /@babel/parser@7.24.8: + resolution: {integrity: sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.24.9 + + /@babel/parser@7.26.2: + resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.26.0 /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.6(@babel/core@7.24.6): resolution: {integrity: sha512-bYndrJ6Ph6Ar+GaB5VAc0JPoP80bQCm4qon6JEzXfRl5QZyQ8Ur1K6k7htxWmPA5z+k7JQvaMUrtXlqclWYzKw==} @@ -1100,7 +1160,7 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-plugin-utils': 7.24.6 /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.6(@babel/core@7.24.6): @@ -1130,7 +1190,7 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-plugin-utils': 7.24.6 /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.24.6): @@ -1433,7 +1493,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-plugin-utils': 7.24.6 '@babel/helper-remap-async-to-generator': 7.24.6(@babel/core@7.24.6) '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.6) @@ -1497,11 +1557,11 @@ packages: '@babel/core': 7.24.6 '@babel/helper-annotate-as-pure': 7.24.6 '@babel/helper-compilation-targets': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-function-name': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 '@babel/helper-plugin-utils': 7.24.6 '@babel/helper-replace-supers': 7.24.6(@babel/core@7.24.6) - '@babel/helper-split-export-declaration': 7.24.6 + '@babel/helper-split-export-declaration': 7.24.7 globals: 11.12.0 /@babel/plugin-transform-computed-properties@7.24.6(@babel/core@7.24.6): @@ -1600,7 +1660,7 @@ packages: dependencies: '@babel/core': 7.24.6 '@babel/helper-compilation-targets': 7.24.6 - '@babel/helper-function-name': 7.24.6 + '@babel/helper-function-name': 7.24.7 '@babel/helper-plugin-utils': 7.24.6 /@babel/plugin-transform-json-strings@7.24.6(@babel/core@7.24.6): @@ -1681,10 +1741,10 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.24.6 - '@babel/helper-hoist-variables': 7.24.6 + '@babel/helper-hoist-variables': 7.24.7 '@babel/helper-module-transforms': 7.24.6(@babel/core@7.24.6) '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-validator-identifier': 7.25.9 /@babel/plugin-transform-modules-umd@7.24.6(@babel/core@7.24.6): resolution: {integrity: sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg==} @@ -1867,7 +1927,7 @@ packages: '@babel/helper-module-imports': 7.24.6 '@babel/helper-plugin-utils': 7.24.6 '@babel/plugin-syntax-jsx': 7.24.6(@babel/core@7.24.6) - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 /@babel/plugin-transform-react-pure-annotations@7.18.6(@babel/core@7.24.6): resolution: {integrity: sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==} @@ -2109,7 +2169,7 @@ packages: dependencies: '@babel/core': 7.24.6 '@babel/helper-plugin-utils': 7.24.6 - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 esutils: 2.0.3 /@babel/preset-react@7.18.6(@babel/core@7.24.6): @@ -2164,35 +2224,50 @@ packages: resolution: {integrity: sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.24.6 - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.24.8 + '@babel/types': 7.24.9 - /@babel/traverse@7.24.6: - resolution: {integrity: sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==} + /@babel/template@7.25.9: + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.24.6 - '@babel/generator': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-function-name': 7.24.6 - '@babel/helper-hoist-variables': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + + /@babel/traverse@7.24.8: + resolution: {integrity: sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.25.0 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/parser': 7.24.8 + '@babel/types': 7.24.9 debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: - supports-color - /@babel/types@7.24.6: - resolution: {integrity: sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==} + /@babel/types@7.24.9: + resolution: {integrity: sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-string-parser': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 to-fast-properties: 2.0.0 + /@babel/types@7.26.0: + resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + /@bcoe/v8-coverage@0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true @@ -3359,6 +3434,140 @@ packages: - supports-color dev: true + /@inquirer/checkbox@2.5.0: + resolution: {integrity: sha512-sMgdETOfi2dUHT8r7TT1BTKOwNvdDGFDXYWtQ2J69SvlYNntk9I/gJe7r5yvMwwsuKnYbuRs3pNhx4tgNck5aA==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.8 + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/confirm@3.2.0: + resolution: {integrity: sha512-oOIwPs0Dvq5220Z8lGL/6LHRTEr9TgLHmiI99Rj1PJ1p1czTys+olrgBqZk4E2qC0YTzeHprxSQmoHioVdJ7Lw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + dev: false + + /@inquirer/core@9.2.1: + resolution: {integrity: sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==} + engines: {node: '>=18'} + dependencies: + '@inquirer/figures': 1.0.8 + '@inquirer/type': 2.0.0 + '@types/mute-stream': 0.0.4 + '@types/node': 22.9.0 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/editor@2.2.0: + resolution: {integrity: sha512-9KHOpJ+dIL5SZli8lJ6xdaYLPPzB8xB9GZItg39MBybzhxA16vxmszmQFrRwbOA918WA2rvu8xhDEg/p6LXKbw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + external-editor: 3.1.0 + dev: false + + /@inquirer/expand@2.3.0: + resolution: {integrity: sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/figures@1.0.8: + resolution: {integrity: sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==} + engines: {node: '>=18'} + dev: false + + /@inquirer/input@2.3.0: + resolution: {integrity: sha512-XfnpCStx2xgh1LIRqPXrTNEEByqQWoxsWYzNRSEUxJ5c6EQlhMogJ3vHKu8aXuTacebtaZzMAHwEL0kAflKOBw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + dev: false + + /@inquirer/number@1.1.0: + resolution: {integrity: sha512-ilUnia/GZUtfSZy3YEErXLJ2Sljo/mf9fiKc08n18DdwdmDbOzRcTv65H1jjDvlsAuvdFXf4Sa/aL7iw/NanVA==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + dev: false + + /@inquirer/password@2.2.0: + resolution: {integrity: sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + dev: false + + /@inquirer/prompts@5.1.2: + resolution: {integrity: sha512-E+ndnfwtVQtcmPt888Hc/HAxJUHSaA6OIvyvLAQ5BLQv+t20GbYdFSjXeLgb47OpMU+aRsKA/ys+Zoylw3kTVg==} + engines: {node: '>=18'} + dependencies: + '@inquirer/checkbox': 2.5.0 + '@inquirer/confirm': 3.2.0 + '@inquirer/editor': 2.2.0 + '@inquirer/expand': 2.3.0 + '@inquirer/input': 2.3.0 + '@inquirer/number': 1.1.0 + '@inquirer/password': 2.2.0 + '@inquirer/rawlist': 2.3.0 + '@inquirer/select': 2.5.0 + dev: false + + /@inquirer/rawlist@2.3.0: + resolution: {integrity: sha512-zzfNuINhFF7OLAtGHfhwOW2TlYJyli7lOUoJUXw/uyklcwalV6WRXBXtFIicN8rTRK1XTiPWB4UY+YuW8dsnLQ==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/select@2.5.0: + resolution: {integrity: sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.8 + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/type@1.5.5: + resolution: {integrity: sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==} + engines: {node: '>=18'} + dependencies: + mute-stream: 1.0.0 + dev: false + + /@inquirer/type@2.0.0: + resolution: {integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==} + engines: {node: '>=18'} + dependencies: + mute-stream: 1.0.0 + dev: false + /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -4649,7 +4858,7 @@ packages: resolution: {integrity: sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==} engines: {node: '>=10'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 entities: 4.4.0 dev: true @@ -4657,7 +4866,7 @@ packages: resolution: {integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==} engines: {node: '>=14'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 entities: 4.4.0 dev: true @@ -4975,40 +5184,40 @@ packages: /@types/babel__core@7.20.0: resolution: {integrity: sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==} dependencies: - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 - '@types/babel__generator': 7.6.4 + '@babel/parser': 7.24.8 + '@babel/types': 7.24.9 + '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.1 - '@types/babel__traverse': 7.18.3 + '@types/babel__traverse': 7.20.6 dev: true /@types/babel__core@7.20.5: resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} dependencies: - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 - '@types/babel__generator': 7.6.4 + '@babel/parser': 7.24.8 + '@babel/types': 7.24.9 + '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.1 - '@types/babel__traverse': 7.18.3 + '@types/babel__traverse': 7.20.6 dev: true - /@types/babel__generator@7.6.4: - resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} + /@types/babel__generator@7.6.8: + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 dev: true /@types/babel__template@7.4.1: resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} dependencies: - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 + '@babel/parser': 7.24.8 + '@babel/types': 7.24.9 dev: true - /@types/babel__traverse@7.18.3: - resolution: {integrity: sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==} + /@types/babel__traverse@7.20.6: + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 dev: true /@types/cheerio@0.22.31: @@ -5225,6 +5434,12 @@ packages: /@types/ms@0.7.31: resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + /@types/mute-stream@0.0.4: + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + dependencies: + '@types/node': 18.15.11 + dev: false + /@types/node@12.20.24: resolution: {integrity: sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==} dev: true @@ -5239,7 +5454,12 @@ packages: /@types/node@18.15.11: resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==} - dev: true + + /@types/node@22.9.0: + resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==} + dependencies: + undici-types: 6.19.8 + dev: false /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} @@ -5361,6 +5581,10 @@ packages: resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==} dev: false + /@types/wrap-ansi@3.0.0: + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + dev: false + /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} dev: true @@ -6679,7 +6903,6 @@ packages: engines: {node: '>=8'} dependencies: type-fest: 0.21.3 - dev: true /ansi-escapes@6.1.0: resolution: {integrity: sha512-bQyg9bzRntwR/8b89DOEhGwctcwCrbWW/TuqTQnpqpy5Fz3aovcOTj5i8NJV6AHc8OGNdMaqdxAWww8pz2kiKg==} @@ -6712,7 +6935,6 @@ packages: /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - dev: true /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} @@ -6735,7 +6957,6 @@ packages: engines: {node: '>=8'} dependencies: color-convert: 2.0.1 - dev: true /ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} @@ -6825,6 +7046,10 @@ packages: resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} dev: true + /arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + dev: false + /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} dev: true @@ -7105,10 +7330,10 @@ packages: resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/template': 7.24.6 - '@babel/types': 7.24.6 + '@babel/template': 7.25.9 + '@babel/types': 7.24.9 '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.18.3 + '@types/babel__traverse': 7.20.6 dev: true /babel-plugin-macros@3.1.0: @@ -7200,7 +7425,7 @@ packages: resolution: {integrity: sha512-0XN2gmpT55QtAz5n7d5g91y1AuO9tRhWBaLgCRyc4ExHrlr7+LfxW+YTb3mOwxngkkiggwM8HyYsaEK9MqhnlQ==} dependencies: '@babel/generator': 7.2.0 - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 chalk: 4.1.2 invariant: 2.2.4 pretty-format: 24.9.0 @@ -7724,7 +7949,6 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true /chalk@5.2.0: resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} @@ -7755,7 +7979,6 @@ packages: /chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true /cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -7877,6 +8100,11 @@ packages: engines: {node: '>= 10'} dev: true + /cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + dev: false + /click-to-react-component@1.1.0(@types/react@18.0.15)(react-dom@18.1.0)(react@18.1.0): resolution: {integrity: sha512-/DjZemufS1BkxyRgZL3r7HXVVOFRWVQi5Xd4EBnjxZMwrHEh0OlUVA2N9CjXkZ0x8zMf8dL1cKnnx+xUWUg4VA==} peerDependencies: @@ -7991,14 +8219,12 @@ packages: engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 - dev: true /color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true /color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} @@ -8040,6 +8266,11 @@ packages: /comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + /commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + dev: false + /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -8345,7 +8576,6 @@ packages: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true /crypto-browserify@3.12.0: resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==} @@ -9165,7 +9395,7 @@ packages: resolution: {integrity: sha512-mM6UoGTgTNoo8lA4dwaIwoeSGT+4PeQeiFylr2+kCB5z3/7NEf7lIM4tqrAsEyzecE/HX0+w7Z78hnFZQ9k5vQ==} dev: true - /dumi@2.3.8(@babel/core@7.24.6)(@types/node@18.15.11)(@types/react@18.0.15)(eslint@8.38.0)(jest@29.1.2)(postcss-less@6.0.0)(prettier@2.8.7)(react-dom@18.2.0)(react@18.2.0)(stylelint@14.16.1)(typescript@5.4.3)(webpack@5.92.0): + /dumi@2.3.8(@babel/core@7.24.6)(@types/node@18.15.11)(@types/react@18.0.15)(eslint@8.38.0)(jest@29.1.2)(postcss-less@6.0.0)(prettier@3.3.3)(react-dom@18.2.0)(react@18.2.0)(stylelint@14.16.1)(typescript@5.4.3)(webpack@5.92.0): resolution: {integrity: sha512-Hriz1EQ/b+wWtoUd19koonmUXPJA9kwVE7QcxZphZnXnF0RItbuaUC8we0xuYMGnElkgjpLIouEbUfTWSHXSDg==} hasBin: true peerDependencies: @@ -9235,7 +9465,7 @@ packages: sass: 1.77.5 sitemap: 7.1.2 sucrase: 3.35.0 - umi: 4.2.10(@babel/core@7.24.6)(@types/node@18.15.11)(@types/react@18.0.15)(eslint@8.38.0)(jest@29.1.2)(postcss-less@6.0.0)(prettier@2.8.7)(react-dom@18.2.0)(react@18.2.0)(sass@1.77.5)(stylelint@14.16.1)(typescript@5.4.3)(webpack@5.92.0) + umi: 4.2.10(@babel/core@7.24.6)(@types/node@18.15.11)(@types/react@18.0.15)(eslint@8.38.0)(jest@29.1.2)(postcss-less@6.0.0)(prettier@3.3.3)(react-dom@18.2.0)(react@18.2.0)(sass@1.77.5)(stylelint@14.16.1)(typescript@5.4.3)(webpack@5.92.0) unified: 10.1.2 unist-util-visit: 4.1.2 unist-util-visit-parents: 5.1.3 @@ -9342,7 +9572,6 @@ packages: /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} @@ -10282,7 +10511,6 @@ packages: onetime: 5.1.2 signal-exit: 3.0.7 strip-final-newline: 2.0.0 - dev: true /execa@7.2.0: resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} @@ -10378,7 +10606,6 @@ packages: chardet: 0.7.0 iconv-lite: 0.4.24 tmp: 0.0.33 - dev: true /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -10699,7 +10926,7 @@ packages: typescript: '>3.6.0' webpack: ^5.11.0 dependencies: - '@babel/code-frame': 7.24.6 + '@babel/code-frame': 7.26.2 chalk: 4.1.2 chokidar: 3.5.3 cosmiconfig: 7.1.0 @@ -10722,7 +10949,7 @@ packages: typescript: '>3.6.0' webpack: ^5.11.0 dependencies: - '@babel/code-frame': 7.24.6 + '@babel/code-frame': 7.26.2 chalk: 4.1.2 chokidar: 3.5.3 cosmiconfig: 7.1.0 @@ -10921,7 +11148,6 @@ packages: /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - dev: true /get-symbol-description@1.0.2: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} @@ -11197,7 +11423,6 @@ packages: /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - dev: true /has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -11688,7 +11913,6 @@ packages: /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - dev: true /human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} @@ -11720,7 +11944,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 - dev: true /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} @@ -12033,7 +12256,6 @@ packages: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} hasBin: true - dev: true /is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} @@ -12093,7 +12315,6 @@ packages: /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - dev: true /is-generator-fn@2.1.0: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} @@ -12247,7 +12468,6 @@ packages: /is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - dev: true /is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} @@ -12316,7 +12536,6 @@ packages: engines: {node: '>=8'} dependencies: is-docker: 2.2.1 - dev: true /isarray@0.0.1: resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} @@ -12331,7 +12550,6 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true /isobject@2.1.0: resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} @@ -12367,7 +12585,7 @@ packages: engines: {node: '>=8'} dependencies: '@babel/core': 7.24.6 - '@babel/parser': 7.24.6 + '@babel/parser': 7.24.8 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.1 @@ -12380,7 +12598,7 @@ packages: engines: {node: '>=10'} dependencies: '@babel/core': 7.24.6 - '@babel/parser': 7.24.6 + '@babel/parser': 7.24.8 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 7.5.4 @@ -12736,7 +12954,7 @@ packages: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/code-frame': 7.24.6 + '@babel/code-frame': 7.26.2 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.1 chalk: 4.1.2 @@ -12871,10 +13089,10 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/core': 7.24.6 - '@babel/generator': 7.24.6 + '@babel/generator': 7.25.0 '@babel/plugin-syntax-jsx': 7.24.6(@babel/core@7.24.6) '@babel/plugin-syntax-typescript': 7.24.6(@babel/core@7.24.6) - '@babel/types': 7.24.6 + '@babel/types': 7.24.9 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 @@ -12964,7 +13182,7 @@ packages: dependencies: '@jest/test-result': 29.5.0 '@jest/types': 29.5.0 - '@types/node': 13.9.3 + '@types/node': 18.15.11 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -13966,7 +14184,6 @@ packages: /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -14265,7 +14482,6 @@ packages: /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - dev: true /mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} @@ -14448,6 +14664,11 @@ packages: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} dev: true + /mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: false + /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} dependencies: @@ -14517,6 +14738,15 @@ packages: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} dev: true + /node-clipboardy@1.0.3: + resolution: {integrity: sha512-/ErAFOtWDNhZh38rrwlAo05Soxbht/rgWugLOt2Ds+NDpZ+2sPiGiwOmFWzV+65fUYjwi+EJfHByIJ4waTHbVg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + arch: 2.2.0 + execa: 5.1.1 + is-wsl: 2.2.0 + dev: false + /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -14684,7 +14914,6 @@ packages: engines: {node: '>=8'} dependencies: path-key: 3.1.1 - dev: true /npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} @@ -14862,7 +15091,6 @@ packages: engines: {node: '>=6'} dependencies: mimic-fn: 2.1.0 - dev: true /onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} @@ -14958,7 +15186,6 @@ packages: /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} - dev: true /osenv@0.1.5: resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==} @@ -15131,7 +15358,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.24.6 + '@babel/code-frame': 7.26.2 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -15215,7 +15442,6 @@ packages: /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - dev: true /path-key@4.0.0: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} @@ -15860,7 +16086,7 @@ packages: fast-diff: 1.2.0 dev: true - /prettier-plugin-organize-imports@3.2.4(prettier@2.8.7)(typescript@5.4.3): + /prettier-plugin-organize-imports@3.2.4(prettier@3.3.3)(typescript@5.4.3): resolution: {integrity: sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog==} peerDependencies: '@volar/vue-language-plugin-pug': ^1.0.4 @@ -15873,11 +16099,11 @@ packages: '@volar/vue-typescript': optional: true dependencies: - prettier: 2.8.7 + prettier: 3.3.3 typescript: 5.4.3 dev: true - /prettier-plugin-packagejson@2.4.3(prettier@2.8.7): + /prettier-plugin-packagejson@2.4.3(prettier@3.3.3): resolution: {integrity: sha512-kPeeviJiwy0BgOSk7No8NmzzXfW4R9FYWni6ziA5zc1kGVVrKnBzMZdu2TUhI+I7h8/5Htt3vARYOk7KKJTTNQ==} peerDependencies: prettier: '>= 1.16.0' @@ -15885,7 +16111,7 @@ packages: prettier: optional: true dependencies: - prettier: 2.8.7 + prettier: 3.3.3 sort-package-json: 2.4.1 synckit: 0.8.5 dev: true @@ -15896,6 +16122,11 @@ packages: hasBin: true dev: true + /prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + engines: {node: '>=14'} + hasBin: true + /pretty-error@4.0.0: resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} dependencies: @@ -16121,6 +16352,13 @@ packages: side-channel: 1.0.6 dev: true + /qs@6.13.1: + resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.6 + dev: true + /query-string@6.14.1: resolution: {integrity: sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==} engines: {node: '>=6'} @@ -17939,7 +18177,6 @@ packages: /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true /sass@1.77.5: resolution: {integrity: sha512-oDfX1mukIlxacPdQqNb6mV2tVCrnE+P3nVYioy72V5tlk56CPNcO4TCuFcaCRKKfJ1M3lH95CleRS+dVKL2qMg==} @@ -18138,7 +18375,6 @@ packages: engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 - dev: true /shebang-regex@1.0.0: resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} @@ -18148,7 +18384,6 @@ packages: /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - dev: true /shortid@2.2.16: resolution: {integrity: sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==} @@ -18168,12 +18403,10 @@ packages: /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - dev: true /simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -18527,7 +18760,6 @@ packages: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: true /string-width@5.1.2: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} @@ -18634,7 +18866,6 @@ packages: engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 - dev: true /strip-ansi@7.0.1: resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} @@ -18661,7 +18892,6 @@ packages: /strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} - dev: true /strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} @@ -18936,7 +19166,6 @@ packages: engines: {node: '>=8'} dependencies: has-flag: 4.0.0 - dev: true /supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} @@ -19244,7 +19473,6 @@ packages: engines: {node: '>=0.6.0'} dependencies: os-tmpdir: 1.0.2 - dev: true /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -19464,7 +19692,6 @@ packages: /type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - dev: true /type-fest@0.6.0: resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} @@ -19579,7 +19806,7 @@ packages: dev: false optional: true - /umi@4.2.10(@babel/core@7.24.6)(@types/node@18.15.11)(@types/react@18.0.15)(eslint@8.38.0)(jest@29.1.2)(postcss-less@6.0.0)(prettier@2.8.7)(react-dom@18.2.0)(react@18.2.0)(sass@1.77.5)(stylelint@14.16.1)(typescript@5.4.3)(webpack@5.92.0): + /umi@4.2.10(@babel/core@7.24.6)(@types/node@18.15.11)(@types/react@18.0.15)(eslint@8.38.0)(jest@29.1.2)(postcss-less@6.0.0)(prettier@3.3.3)(react-dom@18.2.0)(react@18.2.0)(sass@1.77.5)(stylelint@14.16.1)(typescript@5.4.3)(webpack@5.92.0): resolution: {integrity: sha512-PUnrHWTJVZ3ynr5BnpYalBeu9ugb4C8CNKZrFPSOeTaHQ4dLeJl3rL/ubdhaQVhSWKgMQlv1susQULecEjxlHQ==} engines: {node: '>=14'} hasBin: true @@ -19594,8 +19821,8 @@ packages: '@umijs/server': 4.2.10 '@umijs/test': 4.2.10(@babel/core@7.24.6) '@umijs/utils': 4.2.10 - prettier-plugin-organize-imports: 3.2.4(prettier@2.8.7)(typescript@5.4.3) - prettier-plugin-packagejson: 2.4.3(prettier@2.8.7) + prettier-plugin-organize-imports: 3.2.4(prettier@3.3.3)(typescript@5.4.3) + prettier-plugin-packagejson: 2.4.3(prettier@3.3.3) transitivePeerDependencies: - '@babel/core' - '@types/node' @@ -19638,6 +19865,10 @@ packages: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + /undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + dev: false + /unfetch@5.0.0: resolution: {integrity: sha512-3xM2c89siXg0nHvlmYsQ2zkLASvVMBisZm5lF3gFDqfF2xonNStDJyMpvaOBe0a1Edxmqrf2E0HBdmy9QyZaeg==} dev: true @@ -19813,7 +20044,7 @@ packages: resolution: {integrity: sha512-AM6OVeZNwKiirK3IwKxHuopgjX1jB0F8srK9OlCXN+wdmTNg6vgnN9xyQ5abhxq8Oj/kTleLU8OCfZ1FaEW37w==} dependencies: punycode: 1.4.1 - qs: 6.12.1 + qs: 6.13.1 dev: true /url-parse-lax@1.0.0: @@ -20333,7 +20564,6 @@ packages: hasBin: true dependencies: isexe: 2.0.0 - dev: true /widest-line@2.0.1: resolution: {integrity: sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==} @@ -20368,7 +20598,6 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} @@ -20525,6 +20754,11 @@ packages: engines: {node: '>=10'} dev: true + /yoctocolors-cjs@2.1.2: + resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} + engines: {node: '>=18'} + dev: false + /z-schema@5.0.5: resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} engines: {node: '>=8.0.0'} @@ -20548,7 +20782,6 @@ packages: /zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - dev: true /zustand@4.5.5(@types/react@18.0.15)(react@18.2.0): resolution: {integrity: sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 600b4bb48..8cba9f65c 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,3 @@ packages: - 'packages/**' + - 'scripts/cli/create-dms-page' diff --git a/scripts/cli/create-dms-page/README.md b/scripts/cli/create-dms-page/README.md new file mode 100644 index 000000000..1ea974748 --- /dev/null +++ b/scripts/cli/create-dms-page/README.md @@ -0,0 +1,49 @@ +# CLI: create-dms-page + +## 背景 + +在现有的 DMS-UI 架构下,添加一个新的页面需要以下步骤: + +1. 添加菜单图标(SVG 文件)并生成对应的图标组件。 +2. 添加菜单语言包数据以及页面语言包文件。 +3. 添加页面路由配置数据,并在 ROUTE_PATHS 文件中新增对应的页面路径数据。 +4. 添加菜单相关数据。 + +由于上述流程涉及多个分散在项目不同位置的文件,导致整个过程较为繁琐。因此,设计了本脚手架来自动化这些流程。 + +## 使用方式 + +### 前提条件 + +复制菜单图标 SVG 文件(可选):粘贴板内容将用于生成菜单图标 SVG 文件。如果粘贴板内容不是 SVG 内容或没有内容,将使用默认 SVG 生成。请在流程结束后替换 SVG 内容并重新生成图标组件。 + +### 执行命令 + +在 dms-ui/dms-ui-ee 项目的根目录下执行以下命令: + +`pnpm dms:g ` + +其中 `` 支持以下选项: + +- base +- sqle +- provision + +### 输入信息 + +执行命令后,系统将提示输入以下信息: + +1. 菜单图标组件名称:用于生成菜单图标组件的名称。 +2. 页面组件名称:用于生成页面组件的名称。 +3. 页面的中文菜单标题:用于生成对应的菜单语言包。 +4. 路由路径 (Route Path):用于定义页面的 URL 路径。 +5. 当前页面是否为项目内页面:用于生成最终的页面路径。 + +### 后续操作 + +手动添加菜单数据:生成结束后,需手动将生成的菜单数据添加至 menu.data.tsx 文件中。如果在 dms-ui-ee 仓库中添加 provision 类型的页面,则需要将数据添加至 menu.data.dms.tsx 文件中,用于确定新菜单在左侧菜单树上的具体位置。 + +>注意事项 +> +>1. 格式要求:请确保输入的信息符合相应的格式要求。 +>2. 项目结构关联:本脚手架与项目结构强关联。当相关联的代码或页面文件发生变动时,脚手架可能无法正常工作。快速找到相关联文件或变量的方法:在项目全局搜索 @warn/cli/create-dms-page。 diff --git a/scripts/cli/create-dms-page/bin/core.js b/scripts/cli/create-dms-page/bin/core.js new file mode 100755 index 000000000..5dad674fd --- /dev/null +++ b/scripts/cli/create-dms-page/bin/core.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('../dist/index.js'); diff --git a/scripts/cli/create-dms-page/package.json b/scripts/cli/create-dms-page/package.json new file mode 100644 index 000000000..f15923848 --- /dev/null +++ b/scripts/cli/create-dms-page/package.json @@ -0,0 +1,33 @@ +{ + "name": "@actiontech/cli-create-dms-page", + "description": "使用自动化流程创建一个 DMS 的页面", + "version": "0.0.1", + "bin": { + "create-dms-page": "./bin/core.js" + }, + "files": [ + "dist" + ], + "scripts": { + "build:watch": "tsc -w", + "build": "tsc" + }, + "keywords": [], + "license": "ISC", + "devDependencies": { + "@types/babel__generator": "^7.6.8", + "@types/babel__traverse": "^7.20.6" + }, + "dependencies": { + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.24.8", + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.9", + "@inquirer/prompts": "^5.1.2", + "chalk": "^4.1.2", + "commander": "^12.1.0", + "node-clipboardy": "^1.0.3", + "prettier": "^3.3.3", + "zod": "^3.23.8" + } +} \ No newline at end of file diff --git a/scripts/cli/create-dms-page/src/common/Task.ts b/scripts/cli/create-dms-page/src/common/Task.ts new file mode 100644 index 000000000..69b0653ec --- /dev/null +++ b/scripts/cli/create-dms-page/src/common/Task.ts @@ -0,0 +1,7 @@ +import { Command } from 'commander'; + +export interface Task { + register(program: Command): void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + run(...arg: any[]): void; +} diff --git a/scripts/cli/create-dms-page/src/create-dms-page.ts b/scripts/cli/create-dms-page/src/create-dms-page.ts new file mode 100644 index 000000000..b3ba493a5 --- /dev/null +++ b/scripts/cli/create-dms-page/src/create-dms-page.ts @@ -0,0 +1,74 @@ +import { Command } from 'commander'; +import { Task } from './common/Task'; +import { z } from 'zod'; +import chalk from 'chalk'; +import { ModuleOrchestrator } from './module/module-orchestrator'; +import { IconManager } from './module/icon-manager'; +import { logger } from './utils/logger'; +import { PageComponentManager } from './module/page-component-manager'; +import { LocaleManager } from './module/locale-manager'; +import { RoutePathConfigManager } from './module/route-path-config-manager'; +import { MenuManager } from './module/menu-manager'; +import { handleError } from './utils/handle-error'; + +const initOptionsSchema = z.object({ + verbose: z.boolean(), + info: z.boolean() +}); + +const initComponentTypeSchema = z.enum(['sqle', 'base', 'provision']); + +export type IOptions = z.infer; +export type IComponentType = z.infer; + +export class CreateDMSPage implements Task { + register(program: Command): void { + program + .description('自动化创建dms页面模板代码') + .arguments('') + .usage(`${chalk.green('')} [options]`) + .option('--verbose', 'print additional logs') + .option('--info', 'print environment debug info') + .on('--help', () => { + logger.info('\nAllowed page types:'); + logger.info(Object.keys(initComponentTypeSchema.Values).join(', ')); + }) + .action((type: IComponentType, options: IOptions) => { + this.run(type, options); + }); + } + async run(type: IComponentType, options: IOptions): Promise { + try { + await initComponentTypeSchema.parseAsync(type); + + const iconManager = new IconManager(); + const pageComponentManager = new PageComponentManager(type); + const localeManager = new LocaleManager(type, pageComponentManager); + + const routePathManager = new RoutePathConfigManager( + type, + pageComponentManager + ); + + const menuManager = new MenuManager( + type, + iconManager, + pageComponentManager, + localeManager, + routePathManager + ); + + const orchestrator = new ModuleOrchestrator( + iconManager, + pageComponentManager, + localeManager, + routePathManager, + menuManager + ); + + await orchestrator.createDmsPage(); + } catch (error) { + handleError(error); + } + } +} diff --git a/scripts/cli/create-dms-page/src/index.ts b/scripts/cli/create-dms-page/src/index.ts new file mode 100644 index 000000000..209f59f55 --- /dev/null +++ b/scripts/cli/create-dms-page/src/index.ts @@ -0,0 +1,14 @@ +#!/user/bin/env node +import { Command } from 'commander'; +// import pkg from '../package.json'; +import { CreateDMSPage } from './create-dms-page'; + +const program = new Command(); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pkg = require('../package.json'); + +program.name(pkg.name).description(pkg.description).version(pkg.version); + +new CreateDMSPage().register(program); + +program.parse(); diff --git a/scripts/cli/create-dms-page/src/module/icon-manager/index.ts b/scripts/cli/create-dms-page/src/module/icon-manager/index.ts new file mode 100644 index 000000000..a41c1496d --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/icon-manager/index.ts @@ -0,0 +1,105 @@ +import { input } from '@inquirer/prompts'; +import { IIconConfig, IIconManager } from './interface'; +import clipboard from 'node-clipboardy'; +import { PathUtils } from '../../utils/path-utils'; +import path from 'path'; +import { Writer } from '../../utils/writer-utils'; +import { spawnWrapper } from '../../utils/spawn-util'; +import { Template } from '../../template'; +import { StrUtils } from '../../utils/str-utils'; +import { readdir } from 'fs/promises'; + +export class IconManager implements IIconManager { + private readonly iconNamePattern = /^[A-Z][a-zA-Z]*(Filled|Outlined)$/; + public config!: IIconConfig; + + private async getIconConfig(): Promise { + const clipboardData = await clipboard.read(); + + const iconSvgContent = StrUtils.isSvgContent(clipboardData) + ? clipboardData + : Template.iconSvgTemplate; + + const iconName = await input({ + message: + '请输入菜单 icon 名称。(格式:/^[A-Z][a-zA-Z]*(Filled|Outlined)$/)', + required: true, + validate: this.validateIconName.bind(this) + }); + + const match = iconName.match(this.iconNamePattern); + if (!match || !match[1]) { + throw new Error(`Unable to extract icon type from: ${iconName}`); + } + + const iconPath = PathUtils.getIconDirectoryAtPath( + match[1].toLocaleLowerCase(), + 'Common' + ); + + this.config = { + iconSvgContent, + iconName, + iconPath, + iconLibName: '@actiontech/icons' + }; + } + + private generateIconFileName(iconName: string): string { + return `${iconName}.svg`; + } + + private async validateIconName(iconName: string): Promise { + const match = iconName.match(this.iconNamePattern); + + if (!match || !match[1]) { + return ( + `Invalid icon name format: ${iconName}\n` + + 'Icon name must:\n' + + '1. Start with an uppercase letter\n' + + '2. Use camelCase\n' + + '3. End with either "Filled" or "Outlined"\n' + + 'Example: BookMarkFilled, UserOutlined' + ); + } + + const style = match[1].toLowerCase(); + + try { + const styleDirectories = await readdir( + PathUtils.getIconDirectoryAtPath(style) + ); + + for (const dir of styleDirectories) { + const typeDirectoryName = PathUtils.getIconDirectoryAtPath(style, dir); + const icons = await readdir(typeDirectoryName); + if (icons.includes(this.generateIconFileName(iconName))) { + return `Icon file ${iconName} already exists in ${typeDirectoryName}`; + } + } + } catch (error) { + throw new Error(`Failed to validate icon name: ${iconName}`); + } + + return true; + } + + private async createIconSvgFile(): Promise { + await Writer.writeFile( + path.join( + this.config.iconPath, + this.generateIconFileName(this.config.iconName) + ), + this.config.iconSvgContent + ); + } + async run(): Promise { + try { + await this.getIconConfig(); + await this.createIconSvgFile(); + await spawnWrapper('pnpm', ['icon:g']); + } catch (error) { + throw new Error(`generate menu icon: ${error}`); + } + } +} diff --git a/scripts/cli/create-dms-page/src/module/icon-manager/interface.ts b/scripts/cli/create-dms-page/src/module/icon-manager/interface.ts new file mode 100644 index 000000000..9c73c88a6 --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/icon-manager/interface.ts @@ -0,0 +1,10 @@ +import { IModuleBase } from '../interface'; + +export interface IIconConfig { + iconName: string; + iconPath: string; + iconSvgContent: string; + iconLibName: string; +} + +export interface IIconManager extends IModuleBase {} diff --git a/scripts/cli/create-dms-page/src/module/interface.ts b/scripts/cli/create-dms-page/src/module/interface.ts new file mode 100644 index 000000000..27b6e508b --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/interface.ts @@ -0,0 +1,4 @@ +export interface IModuleBase> { + config: T; + run: () => Promise; +} diff --git a/scripts/cli/create-dms-page/src/module/locale-manager/index.ts b/scripts/cli/create-dms-page/src/module/locale-manager/index.ts new file mode 100644 index 000000000..2ee77fd2d --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/locale-manager/index.ts @@ -0,0 +1,91 @@ +import { IComponentType } from '../../create-dms-page'; +import { Writer } from '../../utils/writer-utils'; +import { IPageComponentManager } from '../page-component-manager/interface'; +import { ILocaleConfig, ILocaleManager } from './interface'; +import { PathUtils } from '../../utils/path-utils'; +import { Template } from '../../template'; +import { BabelUtils } from '../../utils/babel-utils'; +import { StrUtils } from '../../utils/str-utils'; + +export class LocaleManager implements ILocaleManager { + constructor( + private readonly componentType: IComponentType, + private readonly pageComponentManager: IPageComponentManager + ) {} + config!: ILocaleConfig; + + private getLocaleConfig() { + const localeDirAtPath = PathUtils.getLocaleDirectoryAtPath( + this.componentType + ); + const localeIndexFileAtPath = PathUtils.getLocaleIndexFileAtPath( + this.componentType + ); + const localeModuleName = StrUtils.convertFirstLetterToLowerCase( + this.pageComponentManager.config.componentName + ); + const localeModuleFileAtPath = PathUtils.getLocaleModuleFileAtPath( + this.componentType, + localeModuleName + ); + const menuI18nFileAtPath = PathUtils.getMenu18nLocaleFileAtPath(); + + this.config = { + localeDirAtPath, + localeModuleName, + menuI18nFileAtPath, + localeIndexFileAtPath, + localeModuleFileAtPath, + menuI18nKeyPath: `dmsMenu.${localeModuleName}` + }; + } + + private async writeMenuLocalFile() { + await BabelUtils.addKeyToObject({ + filePath: this.config.menuI18nFileAtPath, + isDefaultExportObject: true, + keyPath: [this.config.localeModuleName], + value: { + type: 'literal', + value: this.pageComponentManager.config.pageTitle + } + }); + } + + private async writeLocaleFile() { + await Writer.formattedWriteFile( + this.config.localeModuleFileAtPath, + Template.localeTemplate, + PathUtils.DMS_ROOT_CWD + ); + } + + private async updateLocaleImportDeclare() { + await BabelUtils.addImportDefaultDeclaration({ + filePath: this.config.localeIndexFileAtPath, + moduleSpecifier: `./${this.config.localeModuleName}`, + defaultImport: this.config.localeModuleName + }); + } + + private async updateLocaleExports() { + await BabelUtils.addKeyToObject({ + filePath: this.config.localeIndexFileAtPath, + isDefaultExportObject: true, + keyPath: ['translation', this.config.localeModuleName], + value: { type: 'shorthand', name: this.config.localeModuleName } + }); + } + + public async run(): Promise { + try { + this.getLocaleConfig(); + await this.writeLocaleFile(); + await this.updateLocaleExports(); + await this.updateLocaleImportDeclare(); + await this.writeMenuLocalFile(); + } catch (error) { + throw new Error(`generate page locale: ${error}`); + } + } +} diff --git a/scripts/cli/create-dms-page/src/module/locale-manager/interface.ts b/scripts/cli/create-dms-page/src/module/locale-manager/interface.ts new file mode 100644 index 000000000..4e2cd0830 --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/locale-manager/interface.ts @@ -0,0 +1,11 @@ +import { IModuleBase } from '../interface'; + +export interface ILocaleConfig { + localeDirAtPath: string; + localeIndexFileAtPath: string; + localeModuleName: string; + localeModuleFileAtPath: string; + menuI18nKeyPath: string; + menuI18nFileAtPath: string; +} +export interface ILocaleManager extends IModuleBase {} diff --git a/scripts/cli/create-dms-page/src/module/menu-manager/index.ts b/scripts/cli/create-dms-page/src/module/menu-manager/index.ts new file mode 100644 index 000000000..bcf3086ef --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/menu-manager/index.ts @@ -0,0 +1,186 @@ +import { IComponentType } from '../../create-dms-page'; +import { PathUtils } from '../../utils/path-utils'; +import { IMenuConfig, IMenuManager } from './interface'; +import { IPageComponentManager } from '../page-component-manager/interface'; +import { IRoutePathConfigManager } from '../route-path-config-manager/interface'; +import { IIconManager } from '../icon-manager/interface'; +import { BabelUtils, ObjectValue } from '../../utils/babel-utils'; +import { StrUtils } from '../../utils/str-utils'; +import { ILocaleManager } from '../locale-manager/interface'; + +export class MenuManager implements IMenuManager { + config!: IMenuConfig; + + constructor( + private readonly componentType: IComponentType, + private readonly iconManager: IIconManager, + private readonly pageComponentManager: IPageComponentManager, + private readonly localeManager: ILocaleManager, + private readonly routePathManager: IRoutePathConfigManager + ) {} + + private getMenuConfig() { + this.config = { + menuAtPath: PathUtils.getMenuDataAtPath(this.componentType), + menuStructTreeKeyTypeAnnotationAtPath: + PathUtils.getMenuDataTypeAnnotationAtPath(), + menuItemVariableName: `${StrUtils.convertFirstLetterToLowerCase( + this.pageComponentManager.config.componentName + )}`, + menuStructTreeKeyTypeAnnotationName: `${StrUtils.convertFirstLetterToUpperCase( + this.componentType + )}MenuStructTreeKey`, + menuItemArrowFunctionTypeAnnotationName: 'GenerateMenuItemType', + menuStructKey: this.routePathManager.config.routePath, + menusCollectionVariableName: `${this.componentType}MenusCollection` + }; + } + + private generateMenuItemKey(): ObjectValue { + if (this.routePathManager.config.isProjectRoute) { + const prefix = + this.componentType === 'base' + ? 'project/' + : `${this.componentType}/project/`; + + const suffix = `/${this.routePathManager.config.routePath}`; + + return { + type: 'templateLiteral', + quasis: [ + { + raw: prefix, + tail: false + }, + { + raw: suffix, + tail: true + } + ], + names: ['SIDE_MENU_DATA_PLACEHOLDER_KEY'] + }; + } + + return { + type: 'literal', + value: this.routePathManager.config.routePath + }; + } + + private generateMenuItemValueData(): Record { + return { + label: { + type: 'JSXElement', + name: 'TypedLink', + attribute: this.routePathManager.config.isProjectRoute + ? [ + { + name: 'to', + value: { + type: 'identifier', + name: this.routePathManager.config + .routeDataIndexObjectPathWithComponent + } + }, + { + name: 'params', + value: { + type: 'literal', + value: { + projectID: { + type: 'shorthand', + name: 'projectID' + } + } + } + } + ] + : [ + { + name: 'to', + value: { + type: 'identifier', + name: this.routePathManager.config + .routeDataIndexObjectPathWithComponent + } + } + ], + selfClosing: false, + children: [ + { + type: 'function', + functionName: 't', + params: [ + { + type: 'literal', + value: this.localeManager.config.menuI18nKeyPath + } + ] + } + ] + }, + icon: { + type: 'JSXElement', + name: this.iconManager.config.iconName, + selfClosing: true, + attribute: [ + { + name: 'width', + value: { + type: 'identifier', + name: '18' + } + }, + { + name: 'height', + value: { + type: 'identifier', + name: '18' + } + } + ] + }, + key: this.generateMenuItemKey(), + structKey: { + type: 'literal', + value: this.config.menuStructKey + } + }; + } + + private async generateMenuItemArrowFunctionExpression() { + await BabelUtils.addStringLiteralToType({ + filePath: this.config.menuStructTreeKeyTypeAnnotationAtPath, + typeName: this.config.menuStructTreeKeyTypeAnnotationName, + stringLiteral: this.config.menuStructKey + }); + await BabelUtils.updateImportDeclaration({ + filePath: this.config.menuAtPath, + moduleSpecifier: this.iconManager.config.iconLibName, + specifiers: [this.iconManager.config.iconName] + }); + await BabelUtils.addMenuItemVariable({ + filePath: this.config.menuAtPath, + variableName: this.config.menuItemVariableName, + value: { + type: 'literal', + value: this.generateMenuItemValueData() + } + }); + } + + private async exportMenuItemArrowFunctionExpression() { + await BabelUtils.addItemToArray({ + filePath: this.config.menuAtPath, + variableName: this.config.menusCollectionVariableName, + value: { type: 'identifier', name: this.config.menuItemVariableName } + }); + } + + async run(): Promise { + this.getMenuConfig(); + + await this.generateMenuItemArrowFunctionExpression(); + await this.exportMenuItemArrowFunctionExpression(); + } +} diff --git a/scripts/cli/create-dms-page/src/module/menu-manager/interface.ts b/scripts/cli/create-dms-page/src/module/menu-manager/interface.ts new file mode 100644 index 000000000..1bfb5e9bf --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/menu-manager/interface.ts @@ -0,0 +1,13 @@ +import { IModuleBase } from '../interface'; + +export interface IMenuConfig { + menuAtPath: string; + menuItemVariableName: string; + menuItemArrowFunctionTypeAnnotationName: string; + menuStructTreeKeyTypeAnnotationName: string; + menuStructTreeKeyTypeAnnotationAtPath: string; + menuStructKey: string; + menusCollectionVariableName: string; +} + +export interface IMenuManager extends IModuleBase {} diff --git a/scripts/cli/create-dms-page/src/module/module-orchestrator.ts b/scripts/cli/create-dms-page/src/module/module-orchestrator.ts new file mode 100644 index 000000000..abda6daf0 --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/module-orchestrator.ts @@ -0,0 +1,23 @@ +import { IIconManager } from './icon-manager/interface'; +import { ILocaleManager } from './locale-manager/interface'; +import { IMenuManager } from './menu-manager/interface'; +import { IPageComponentManager } from './page-component-manager/interface'; +import { IRoutePathConfigManager } from './route-path-config-manager/interface'; + +export class ModuleOrchestrator { + constructor( + private readonly iconManager: IIconManager, + private readonly pageComponentManager: IPageComponentManager, + private readonly localeManager: ILocaleManager, + private readonly routePathManager: IRoutePathConfigManager, + private readonly menuManager: IMenuManager + ) {} + + async createDmsPage() { + await this.iconManager.run(); + await this.pageComponentManager.run(); + await this.localeManager.run(); + await this.routePathManager.run(); + await this.menuManager.run(); + } +} diff --git a/scripts/cli/create-dms-page/src/module/page-component-manager/index.ts b/scripts/cli/create-dms-page/src/module/page-component-manager/index.ts new file mode 100644 index 000000000..4bc52381c --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/page-component-manager/index.ts @@ -0,0 +1,88 @@ +import { input } from '@inquirer/prompts'; +import { IPageComponentManager, IComponentConfig } from './interface'; +import { IComponentType } from '../../create-dms-page'; +import path from 'path'; +import { PathUtils } from '../../utils/path-utils'; +import { Writer } from '../../utils/writer-utils'; +import { Template } from '../../template'; +import { readdir } from 'fs/promises'; + +export class PageComponentManager implements IPageComponentManager { + constructor(private readonly componentType: IComponentType) {} + + private readonly pageNamePattern = /^[A-Z][a-z]*([A-Z][a-z]*)*$/; + + config!: IComponentConfig; + + private async getPageConfig() { + const componentName = await input({ + message: '请输入页面组件名称。(格式:/^[A-Z][a-z]*([A-Z][a-z]*)*$/)', + required: true, + validate: this.validatePageName.bind(this) + }); + + const componentPath = PathUtils.getComponentIndexFileAtPath( + this.componentType, + componentName + ); + + const pageTitle = await input({ + message: '请输入页面中文标题', + required: true, + validate: this.validatePageTile.bind(this) + }); + + this.config = { + componentName, + componentPath, + pageTitle + }; + } + + private validatePageTile(pageTitle: string): string | boolean { + for (let i = 0; i < pageTitle.length; i++) { + const charCode = pageTitle.charCodeAt(i); + if (charCode < 0x4e00 || charCode > 0x9fff) { + return 'The string contains non-Chinese characters'; + } + } + + return true; + } + + private async validatePageName(pageName: string): Promise { + if (!this.pageNamePattern.test(pageName)) { + return `Invalid page component naming: "${pageName}"\n. + The string must start with an uppercase letter and be followed by lowercase letters or numbers, with subsequent words starting with an uppercase letter.\n + Example: DataSourceManagement, SqlExecWorkflow`; + } + + const componentDirAtPath = PathUtils.getComponentDirectoryAtPath( + this.componentType + ); + const componentDirs = await readdir(componentDirAtPath); + + if (componentDirs.includes(pageName)) { + return `Component ${pageName} already exists in ${componentDirAtPath}`; + } + + return true; + } + + private async createPageComponent(): Promise { + await Writer.formattedWriteFile( + path.join(this.config.componentPath), + Template.pageComponentTemplate(this.config.componentName), + PathUtils.DMS_ROOT_CWD + ); + } + + async run(): Promise { + try { + await this.getPageConfig(); + await this.createPageComponent(); + } catch (error) { + throw new Error(`generate page component: ${error}`); + } + } +} diff --git a/scripts/cli/create-dms-page/src/module/page-component-manager/interface.ts b/scripts/cli/create-dms-page/src/module/page-component-manager/interface.ts new file mode 100644 index 000000000..ffed501e3 --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/page-component-manager/interface.ts @@ -0,0 +1,8 @@ +import { IModuleBase } from '../interface'; + +export interface IComponentConfig { + componentName: string; + componentPath: string; + pageTitle: string; +} +export interface IPageComponentManager extends IModuleBase {} diff --git a/scripts/cli/create-dms-page/src/module/route-path-config-manager/index.ts b/scripts/cli/create-dms-page/src/module/route-path-config-manager/index.ts new file mode 100644 index 000000000..ee71311f0 --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/route-path-config-manager/index.ts @@ -0,0 +1,186 @@ +import { input, confirm } from '@inquirer/prompts'; +import { IRoutePathConfig, IRoutePathConfigManager } from './interface'; +import { IComponentType } from '../../create-dms-page'; +import { PathUtils } from '../../utils/path-utils'; +import { BabelUtils, ObjectValue } from '../../utils/babel-utils'; +import { IPageComponentManager } from '../page-component-manager/interface'; +import { StrUtils } from '../../utils/str-utils'; + +export class RoutePathConfigManager implements IRoutePathConfigManager { + constructor( + private readonly componentType: IComponentType, + private readonly pageComponentManager: IPageComponentManager + ) {} + config!: IRoutePathConfig; + private readonly routePathPattern = /^[a-z]+(-[a-z]+)*$/; + + private async getRoutePathConfig() { + const routePath = await input({ + message: '请输入页面路由地址。(格式:/^[a-z]+(-[a-z]+)*$/)', + required: true, + validate: this.validateRoutePath.bind(this) + }); + + const isProjectRoute = await confirm({ + message: `当前路由是否属于项目内路由?(项目内路由最终生成路由格式为 ${ + this.componentType === 'base' ? '/' : `/${this.componentType}/` + }project/{projectID}/${routePath})`, + default: true + }); + + const getRouteConfigVariableName = () => { + if (this.componentType === 'sqle') { + return isProjectRoute + ? 'projectDetailRouterConfig' + : 'globalRouterConfig'; + } + + if (this.componentType === 'base') { + return isProjectRoute + ? 'BaseProjectRouterConfig' + : 'BaseGlobalRouterConfig'; + } + + return 'AuthRouterConfig'; + }; + + this.config = { + routePath, + isProjectRoute, + routeConfigVariableName: getRouteConfigVariableName(), + routeConfigAtPath: PathUtils.getRouteConfigAtPath(this.componentType), + routeDataAtPath: PathUtils.getRouteDataAtPath(), + routeDataVariableName: 'ROUTE_PATHS', + routeDataIndexObjectPathWithComponent: `ROUTE_PATHS.${this.componentType.toLocaleUpperCase()}.${StrUtils.camelCaseToUpperCaseSnakeCase( + this.pageComponentManager.config.componentName + )}.index` + }; + } + + private validateRoutePath(routePath: string): string | boolean { + if (!this.routePathPattern.test(routePath)) { + return `Invalid route path format: "${routePath}". The string must be all lowercase and use hyphens to separate words.`; + } + + return true; + } + + private getAddRoutePathsObject(): Record { + const projectParams = ':projectID'; + if (this.config.isProjectRoute) { + if (this.componentType === 'base') { + return { + prefix: { type: 'literal', value: '/project' }, + path: { + type: 'literal', + value: `${projectParams}/${this.config.routePath}` + } + }; + } + + return { + prefix: { type: 'literal', value: `/${this.componentType}/project` }, + path: { + type: 'literal', + value: `${projectParams}/${this.config.routePath}` + } + }; + } + + if (this.componentType === 'base') { + return { + path: { + type: 'literal', + value: `/${this.config.routePath}` + } + }; + } + + return { + path: { + type: 'literal', + value: `/${this.componentType}/${this.config.routePath}` + } + }; + } + + private getAddRouteConfigObject(): Record { + return { + key: { + type: 'literal', + value: StrUtils.convertFirstLetterToLowerCase( + this.pageComponentManager.config.componentName + ) + }, + path: { + type: 'identifier', + name: `${this.config.routeDataIndexObjectPathWithComponent}.path` + }, + element: { + type: 'JSXElement', + name: this.pageComponentManager.config.componentName, + selfClosing: true + } + }; + } + + private async updateRoutePaths() { + const addObject = this.getAddRoutePathsObject(); + + await BabelUtils.addKeyToObject({ + filePath: this.config.routeDataAtPath, + objectName: this.config.routeDataVariableName, + keyPath: [ + this.componentType.toLocaleUpperCase(), + StrUtils.camelCaseToUpperCaseSnakeCase( + this.pageComponentManager.config.componentName + ) + ], + value: { + type: 'literal', + value: { + index: { + type: 'literal', + value: addObject + } + } + } + }); + } + + private async createComponentLoaderDeclaration() { + const importPath = PathUtils.getRelativePath( + this.config.routeConfigAtPath, + this.pageComponentManager.config.componentPath, + true + ); + + await BabelUtils.addReactLoaderComponentDeclaration({ + filePath: this.config.routeConfigAtPath, + componentName: this.pageComponentManager.config.componentName, + importPath + }); + } + + private async updateRouteConfig() { + await this.createComponentLoaderDeclaration(); + + await BabelUtils.addItemToArray({ + filePath: this.config.routeConfigAtPath, + variableName: this.config.routeConfigVariableName, + value: { + type: 'literal', + value: this.getAddRouteConfigObject() + } + }); + } + + run: () => Promise = async () => { + try { + await this.getRoutePathConfig(); + await Promise.all([this.updateRoutePaths(), this.updateRouteConfig()]); + } catch (error) { + throw new Error(`generate route config: ${error}`); + } + }; +} diff --git a/scripts/cli/create-dms-page/src/module/route-path-config-manager/interface.ts b/scripts/cli/create-dms-page/src/module/route-path-config-manager/interface.ts new file mode 100644 index 000000000..360df48ae --- /dev/null +++ b/scripts/cli/create-dms-page/src/module/route-path-config-manager/interface.ts @@ -0,0 +1,14 @@ +import { IModuleBase } from '../interface'; + +export interface IRoutePathConfig { + isProjectRoute: boolean; + routePath: string; + routeDataAtPath: string; + routeDataVariableName: string; + routeDataIndexObjectPathWithComponent: string; + routeConfigAtPath: string; + routeConfigVariableName: string; +} + +export interface IRoutePathConfigManager + extends IModuleBase {} diff --git a/scripts/cli/create-dms-page/src/template/index.ts b/scripts/cli/create-dms-page/src/template/index.ts new file mode 100644 index 000000000..1713aa90a --- /dev/null +++ b/scripts/cli/create-dms-page/src/template/index.ts @@ -0,0 +1,25 @@ +export class Template { + static localeTemplate = ` + // eslint-disable-next-line import/no-anonymous-default-export + export default { + } + `; + static pageComponentTemplate: (name: string) => string = (name) => { + return ` + const ${name}:React.FC = () => { + return ( +
+ ${name} +
+ ) + } + + export default ${name}; + `; + }; + static iconSvgTemplate = ` + + + `; +} diff --git a/scripts/cli/create-dms-page/src/types.d.ts b/scripts/cli/create-dms-page/src/types.d.ts new file mode 100644 index 000000000..99e6074f4 --- /dev/null +++ b/scripts/cli/create-dms-page/src/types.d.ts @@ -0,0 +1 @@ +declare module 'node-clipboardy'; diff --git a/scripts/cli/create-dms-page/src/utils/babel-utils.ts b/scripts/cli/create-dms-page/src/utils/babel-utils.ts new file mode 100644 index 000000000..1b4313161 --- /dev/null +++ b/scripts/cli/create-dms-page/src/utils/babel-utils.ts @@ -0,0 +1,535 @@ +import { readFile } from 'fs/promises'; +import * as parser from '@babel/parser'; +import traverse from '@babel/traverse'; +import generate from '@babel/generator'; +import * as t from '@babel/types'; +import { resolve } from 'path'; +import { Writer } from './writer-utils'; +import { PathUtils } from './path-utils'; + +interface IObjectValueBase { + type: + | 'literal' + | 'identifier' + | 'shorthand' + | 'JSXElement' + | 'function' + | 'templateLiteral'; +} + +interface ILiteralValue extends IObjectValueBase { + type: 'literal'; + value: + | string + | number + | boolean + | null + | undefined + | Array + | Record; +} + +interface IIdentifierValue extends IObjectValueBase { + type: 'identifier'; + name: string; +} + +interface IShorthandValue extends IObjectValueBase { + type: 'shorthand'; + name: string; +} + +interface IJSXElementValue extends IObjectValueBase { + type: 'JSXElement'; + name: string; + attribute?: Array<{ name: string; value: ObjectValue }>; + selfClosing?: boolean; + children?: Array; +} + +interface IFunctionValue extends IObjectValueBase { + type: 'function'; + params?: ObjectValue[]; + functionName: string; +} + +interface ITemplateLiteral extends IObjectValueBase { + type: 'templateLiteral'; + quasis: Array<{ raw: string; tail: boolean }>; + names: string[]; +} + +export type ObjectValue = + | ILiteralValue + | IIdentifierValue + | IShorthandValue + | IJSXElementValue + | IFunctionValue + | ITemplateLiteral; + +interface IAddKeyOptions { + filePath: string; // 文件路径 + objectName?: string; // 要修改的对象名称 + keyPath: string[]; // 要添加的键路径 + value: ObjectValue; // 要添加的值 + isDefaultExportObject?: boolean; +} + +interface IAddItemOptions { + filePath: string; // 文件路径 + variableName: string; // 要修改的对象名称 + value: ObjectValue; // 要添加的值 +} + +interface IUpdateImportOptions { + // 要添加 import 语句的文件路径 + filePath: string; + // 要导入的模块名称或路径 + moduleSpecifier: string; + + specifiers: string[]; +} + +interface IAddDefaultImportOptions { + // 要添加 import 语句的文件路径 + filePath: string; + // 要导入的模块名称或路径 + moduleSpecifier: string; + // 默认导入的名称 + defaultImport: string; +} + +interface IAddReactLoaderComponentDeclarationOptions { + filePath: string; // 文件路径 + componentName: string; //组件名称 + importPath: string; //导入路径 +} + +interface IAddMenuItemVariableOptions { + filePath: string; // 文件路径 + value: ObjectValue; // 要添加的值 + variableName: string; //菜单变量名 +} + +interface IAddStringLiteralOptions { + filePath: string; + typeName: string; + stringLiteral: string; +} + +export class BabelUtils { + static async addKeyToObject(options: IAddKeyOptions) { + const { filePath, objectName, keyPath, value, isDefaultExportObject } = + options; + + const ast = await this.fileCodeToAst(filePath); + + const valueNode = this.valueToAst(value); + + let targetObjectFound = false; + + const addKeyWithObjectExpression = (currentObject: t.ObjectExpression) => { + for (let i = 0; i < keyPath.length - 1; i++) { + const key = keyPath[i]; + let nestedObject = currentObject.properties.find( + (prop): prop is t.ObjectProperty => + t.isObjectProperty(prop) && + ((t.isIdentifier(prop.key) && prop.key.name === key) || + (t.isStringLiteral(prop.key) && prop.key.value === key)) + ); + + if (!nestedObject) { + nestedObject = t.objectProperty( + t.identifier(key), + t.objectExpression([]) + ); + currentObject.properties.push(nestedObject); + } + + currentObject = nestedObject.value as t.ObjectExpression; + } + + const lastKey = keyPath[keyPath.length - 1]; + + if ( + currentObject.properties.some((item) => { + return ( + t.isObjectProperty(item) && + t.isIdentifier(item.key) && + item.key.name === lastKey + ); + }) + ) { + throw new Error( + `The current object ${objectName} has an object path with the value [${keyPath.join( + ',' + )}] and cannot be added repeatedly!` + ); + } + currentObject.properties.push( + t.objectProperty( + t.identifier(lastKey), + valueNode, + false, + value.type === 'shorthand' + ) + ); + }; + + traverse(ast, { + VariableDeclaration(path) { + const declaration = path.node.declarations[0]; + + if ( + t.isIdentifier(declaration.id) && + declaration.id.name === objectName + ) { + targetObjectFound = true; + + if (t.isTSAsExpression(declaration.init)) { + const objectExpression = declaration.init; + const currentObject = + objectExpression.expression as t.ObjectExpression; + addKeyWithObjectExpression(currentObject); + } + } + }, + ExportDefaultDeclaration(path) { + if (isDefaultExportObject) { + targetObjectFound = true; + const declaration = path.node.declaration; + + if (t.isObjectExpression(declaration)) { + addKeyWithObjectExpression(declaration); + } + } + } + }); + + if (!targetObjectFound) { + throw new Error(`Object "${objectName}" not found in ${filePath}`); + } + + await this.formattedWriteFileCodeWithAst(ast, filePath); + } + + static async addItemToArray(options: IAddItemOptions) { + const { filePath, variableName, value } = options; + + const ast = await this.fileCodeToAst(filePath); + + const valueNode = this.valueToAst(value); + + let targetObjectFound = false; + + traverse(ast, { + VariableDeclaration(path) { + const declaration = path.node.declarations[0]; + + if ( + t.isIdentifier(declaration.id) && + declaration.id.name === variableName + ) { + targetObjectFound = true; + + if (t.isArrayExpression(declaration.init)) { + const arrayExpression = declaration.init; + arrayExpression.elements.push(valueNode); + } + } + } + }); + + if (!targetObjectFound) { + throw new Error(`Array "${variableName}" not found in ${filePath}`); + } + + await this.formattedWriteFileCodeWithAst(ast, filePath); + } + + private static transformJSXAttributes( + attributes: IJSXElementValue['attribute'] + ): Array { + if (!attributes) { + return []; + } + + return attributes.map((item) => { + return t.jSXAttribute( + t.jsxIdentifier(item.name), + t.jsxExpressionContainer(this.valueToAst(item.value)) + ); + }); + } + private static transformJSXChildren(children: IJSXElementValue['children']) { + if (!children) { + return []; + } + return children.map((item) => + t.jsxExpressionContainer(this.valueToAst(item)) + ); + } + + private static valueToAst(value: ObjectValue): t.Expression { + switch (value.type) { + case 'literal': + // 处理字面量 + if (value.value === null) { + return t.nullLiteral(); + } + if (value.value === undefined) { + return t.identifier('undefined'); + } + if (typeof value.value === 'string') { + return t.stringLiteral(value.value); + } + if (typeof value.value === 'number') { + return t.numericLiteral(value.value); + } + if (typeof value.value === 'boolean') { + return t.booleanLiteral(value.value); + } + if (typeof value.value === 'object') { + const properties = Object.entries(value.value).map(([key, val]) => + t.objectProperty(t.identifier(key), this.valueToAst(val), false) + ); + return t.objectExpression(properties); + } + throw new Error(`Unsupported literal type: ${typeof value.value}`); + + case 'identifier': + // 处理变量引用 + return t.identifier(value.name); + + case 'shorthand': + // shorthand 属性在 ObjectProperty 中特殊处理 + return t.identifier(value.name); + + case 'function': + return t.callExpression( + t.identifier(value.functionName), + value.params ? value.params.map((item) => this.valueToAst(item)) : [] + ); + + case 'templateLiteral': + return t.templateLiteral( + value.quasis.map((item) => + t.templateElement({ raw: item.raw }, item.tail) + ), + value.names.map((item) => t.identifier(item)) + ); + + case 'JSXElement': + return t.jSXElement( + { + type: 'JSXOpeningElement', + name: t.jsxIdentifier(value.name), + attributes: this.transformJSXAttributes(value.attribute), + selfClosing: !!value.selfClosing + }, + !value.selfClosing + ? t.jsxClosingElement(t.jsxIdentifier(value.name)) + : null, + this.transformJSXChildren(value.children) + ); + + default: + throw new Error(`Unsupported value type: ${(value as any).type}`); + } + } + + private static async fileCodeToAst(filePath: string) { + const code = await readFile(resolve(filePath), 'utf-8'); + + return parser.parse(code, { + sourceType: 'module', + plugins: ['typescript', 'jsx'] + }); + } + + private static async formattedWriteFileCodeWithAst( + ast: parser.ParseResult, + filePath: string + ) { + const output = generate(ast, { + retainLines: true, + compact: false, + filename: filePath, + jsescOption: { + minimal: true + } + }).code; + + await Writer.formattedWriteFile(filePath, output, PathUtils.DMS_ROOT_CWD); + } + + static async updateImportDeclaration(options: IUpdateImportOptions) { + const { filePath, moduleSpecifier, specifiers } = options; + + const ast = await this.fileCodeToAst(filePath); + + traverse(ast, { + Program(path) { + const currentImportIsExisting = path.node.body.some((item) => { + if ( + t.isImportDeclaration(item) && + item.source.value === moduleSpecifier + ) { + specifiers.forEach((specifier) => { + item.specifiers.push( + t.importSpecifier( + t.identifier(specifier), + t.identifier(specifier) + ) + ); + }); + return true; + } + return false; + }); + + if (!currentImportIsExisting) { + path.node.body.unshift( + t.importDeclaration( + specifiers.map((item) => + t.importSpecifier(t.identifier(item), t.identifier(item)) + ), + t.stringLiteral(moduleSpecifier) + ) + ); + } + } + }); + + await this.formattedWriteFileCodeWithAst(ast, filePath); + } + + static async addImportDefaultDeclaration(options: IAddDefaultImportOptions) { + const { filePath, moduleSpecifier, defaultImport } = options; + + const ast = await this.fileCodeToAst(filePath); + + traverse(ast, { + Program(path) { + const currentDefaultImportIsExisting = path.node.body.some((item) => { + if (t.isImportDeclaration(item)) { + return item.source.value === moduleSpecifier; + } + return false; + }); + + if (!currentDefaultImportIsExisting) { + path.node.body.unshift( + t.importDeclaration( + [t.importDefaultSpecifier(t.identifier(defaultImport))], + t.stringLiteral(moduleSpecifier) + ) + ); + } + } + }); + + await this.formattedWriteFileCodeWithAst(ast, filePath); + } + + static async addReactLoaderComponentDeclaration( + options: IAddReactLoaderComponentDeclarationOptions + ) { + const { filePath, componentName, importPath } = options; + + const ast = await this.fileCodeToAst(filePath); + let lastConstDeclaration = null; + + traverse(ast, { + VariableDeclaration(path) { + //todo 校验 componentName 是否已经定义 + + //找到最后一个 const + React.lazy 的语句 + if ( + path.node.kind === 'const' && + t.isCallExpression(path.node.declarations[0].init) + ) { + lastConstDeclaration = path; + } + } + }); + + if (lastConstDeclaration) { + const newConstDeclaration = parser.parse( + `\nconst ${componentName} = React.lazy(() => import('${importPath}'));` + ).program.body[0]; + + (lastConstDeclaration as any).insertAfter(newConstDeclaration); + } + + await this.formattedWriteFileCodeWithAst(ast, filePath); + } + + static async addMenuItemVariable(options: IAddMenuItemVariableOptions) { + const { filePath, value, variableName } = options; + + const ast = await this.fileCodeToAst(filePath); + let lastMenuItemDeclaration = null; + + traverse(ast, { + VariableDeclaration(path) { + //找到最后一个菜单函数 + if ( + path.node.kind === 'const' && + t.isArrowFunctionExpression(path.node.declarations[0].init) + ) { + lastMenuItemDeclaration = path; + } + } + }); + + if (lastMenuItemDeclaration) { + const newConstDeclaration = this.valueToAst(value); + + const functionId = t.identifier(variableName); + functionId.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('GenerateMenuItemType')) + ); + + const arrowFunction = t.arrowFunctionExpression( + [t.identifier('projectID')], + newConstDeclaration + ); + + const declaration = t.variableDeclaration('const', [ + t.variableDeclarator(functionId, arrowFunction) + ]); + + (lastMenuItemDeclaration as any).insertAfter(declaration); + } + + await this.formattedWriteFileCodeWithAst(ast, filePath); + } + + static async addStringLiteralToType(options: IAddStringLiteralOptions) { + const { filePath, typeName, stringLiteral } = options; + + const ast = await this.fileCodeToAst(filePath); + let existingTypeName = false; + + traverse(ast, { + TSTypeAliasDeclaration(path) { + if ( + path.node.id.name === typeName && + t.isTSUnionType(path.node.typeAnnotation) + ) { + existingTypeName = true; + path.node.typeAnnotation.types.push( + t.tsLiteralType(t.stringLiteral(stringLiteral)) + ); + } + } + }); + + if (!existingTypeName) { + throw new Error(`TSUnionType "${typeName}" not found in ${filePath}`); + } + + await this.formattedWriteFileCodeWithAst(ast, filePath); + } +} diff --git a/scripts/cli/create-dms-page/src/utils/handle-error.ts b/scripts/cli/create-dms-page/src/utils/handle-error.ts new file mode 100644 index 000000000..ee9eacb92 --- /dev/null +++ b/scripts/cli/create-dms-page/src/utils/handle-error.ts @@ -0,0 +1,14 @@ +import { logger } from './logger'; + +export function handleError(error: unknown) { + if (typeof error === 'string') { + logger.error(error); + } + + if (error instanceof Error) { + logger.error(error.message); + } + + logger.error('Something went wrong. Please try again.'); + process.exit(1); +} diff --git a/scripts/cli/create-dms-page/src/utils/logger.ts b/scripts/cli/create-dms-page/src/utils/logger.ts new file mode 100644 index 000000000..f4c76f733 --- /dev/null +++ b/scripts/cli/create-dms-page/src/utils/logger.ts @@ -0,0 +1,54 @@ +/* eslint-disable no-console */ +import chalk from 'chalk'; + +function stringify(arg: unknown): string { + if (typeof arg === 'string') { + return arg; + } else if (arg === null) { + return 'null'; + } else if (arg === undefined) { + return 'undefined'; + } else if (typeof arg === 'object') { + try { + return JSON.stringify(arg, null, 2); + } catch (error) { + return '[Circular]'; + } + } else { + return String(arg); + } +} + +function createLogFunction(chalkColor: chalk.Chalk) { + return (...args: unknown[]) => { + const message = args.map(stringify).join(' '); + console.log(chalkColor(message)); + }; +} + +export const logger = { + error: createLogFunction(chalk.red), + warn: createLogFunction(chalk.yellow), + info: createLogFunction(chalk.cyan), + success: createLogFunction(chalk.green), + break() { + console.log(''); + } +}; + +export const verboseLogger = (show = false) => { + const createConditionalLogFunction = (chalkColor: chalk.Chalk) => { + return (...args: unknown[]) => { + if (show) { + createLogFunction(chalkColor)(...args); + } + }; + }; + + return { + error: createConditionalLogFunction(chalk.red), + warn: createConditionalLogFunction(chalk.yellow), + info: createConditionalLogFunction(chalk.cyan), + success: createConditionalLogFunction(chalk.green) + }; +}; diff --git a/scripts/cli/create-dms-page/src/utils/path-utils.ts b/scripts/cli/create-dms-page/src/utils/path-utils.ts new file mode 100644 index 000000000..493cfa534 --- /dev/null +++ b/scripts/cli/create-dms-page/src/utils/path-utils.ts @@ -0,0 +1,250 @@ +// @warn/cli/create-dms-page +import { existsSync } from 'fs'; +import path from 'path'; +import { IComponentType } from '../create-dms-page'; +export class PathUtils { + static CLI_ROOT_CWD = path.resolve(__dirname, '..', '..'); + static DMS_ROOT_CWD = path.join(this.CLI_ROOT_CWD, '..', '..', '..'); + static SQLE_ROOT_CWD = path.join(this.DMS_ROOT_CWD, 'packages', 'sqle'); + static BASE_ROOT_CWD = path.join(this.DMS_ROOT_CWD, 'packages', 'base'); + static SHARED_ROOT_CWD = path.join(this.DMS_ROOT_CWD, 'packages', 'shared'); + + // icon path + static ICON_ROOT_CWD = path.join(this.DMS_ROOT_CWD, 'packages', 'icons'); + static getIconDirectoryAtPath(style: string, type?: string): string { + const iconPath = type + ? path.join(PathUtils.ICON_ROOT_CWD, 'svg', style, type) + : path.join(PathUtils.ICON_ROOT_CWD, 'svg', style); + + if (!existsSync(iconPath)) { + throw new Error( + `${iconPath} does not exist. Please check the icon package path under the packages directory!` + ); + } + + return iconPath; + } + + // local path + static getLocaleDirectoryAtPath(type: IComponentType) { + const localeDirAtPath = path.join( + PathUtils.getRootCWDWithType(type), + 'src', + 'locale', + 'zh-CN' + ); + + if (!existsSync(localeDirAtPath)) { + throw new Error( + `${localeDirAtPath} does not exist. Please check the path under the packages directory!` + ); + } + + return localeDirAtPath; + } + static getLocaleIndexFileAtPath(type: IComponentType) { + const localeDirAtPath = this.getLocaleDirectoryAtPath(type); + + const indexFileAtPath = path.join(localeDirAtPath, 'index.ts'); + + if (!existsSync(indexFileAtPath)) { + throw new Error( + `${indexFileAtPath} does not exist. Please check the path under the packages directory!` + ); + } + + return indexFileAtPath; + } + static getLocaleModuleFileAtPath(type: IComponentType, moduleName: string) { + const localeModuleFileAtPath = path.join( + this.getLocaleDirectoryAtPath(type), + `${moduleName}.ts` + ); + + if (existsSync(localeModuleFileAtPath)) { + throw new Error( + `${localeModuleFileAtPath} does exist. Please check the path under the packages directory!` + ); + } + + return localeModuleFileAtPath; + } + static getMenu18nLocaleFileAtPath() { + const menuI18nFileAtPath = path.join( + PathUtils.getRootCWDWithType('base'), + 'src', + 'locale', + 'zh-CN', + 'dmsMenu.ts' + ); + + if (!existsSync(menuI18nFileAtPath)) { + throw new Error( + `${menuI18nFileAtPath} does not exist. Please check the path under the packages directory!` + ); + } + + return menuI18nFileAtPath; + } + + // component path + static getComponentDirectoryAtPath(type: IComponentType) { + const componentDirAtPath = path.join( + PathUtils.getRootCWDWithType(type), + 'src', + 'page' + ); + + if (!existsSync(componentDirAtPath)) { + throw new Error( + `${componentDirAtPath} does not exist. Please check the path under the packages directory!` + ); + } + + return componentDirAtPath; + } + static getComponentIndexFileAtPath( + type: IComponentType, + componentName: string + ) { + const componentDirAtPath = this.getComponentDirectoryAtPath(type); + + return path.join(componentDirAtPath, componentName, 'index.tsx'); + } + + // router path + static getRouteConfigAtPath(type: IComponentType) { + let configAtPath = ''; + if (type === 'base') { + configAtPath = path.join( + PathUtils.getRootCWDWithType('base'), + 'src', + 'router', + 'router.base.tsx' + ); + } + + if (type === 'sqle') { + configAtPath = path.join( + PathUtils.getRootCWDWithType('sqle'), + 'src', + 'router', + 'config.tsx' + ); + } + if (type === 'provision') { + configAtPath = path.join( + PathUtils.getRootCWDWithType('provision'), + 'src', + 'router', + 'router.tsx' + ); + } + + if (!configAtPath) { + throw new Error( + `No routing configuration file corresponding to ${type} was found` + ); + } + + if (!existsSync(configAtPath)) { + throw new Error( + `${configAtPath} does not exist. Please check the path under the packages directory!` + ); + } + + return configAtPath; + } + static getRouteDataAtPath() { + const routeDataAtPath = path.join( + PathUtils.SHARED_ROOT_CWD, + 'lib', + 'data', + 'routePaths.ts' + ); + + if (!existsSync(routeDataAtPath)) { + throw new Error( + `${routeDataAtPath} does not exist. Please check the path under the packages directory!` + ); + } + + return routeDataAtPath; + } + + // menu path + static getMenuDataAtPath(type: IComponentType) { + const menuDataAtPath = path.join( + PathUtils.getRootCWDWithType('base'), + 'src', + 'page', + 'Nav', + 'sideMenu', + 'menuList', + 'menus', + `${type}.tsx` + ); + + if (!existsSync(menuDataAtPath)) { + throw new Error( + `${menuDataAtPath} does not exist. Please check the path under the packages directory!` + ); + } + + return menuDataAtPath; + } + static getMenuDataTypeAnnotationAtPath() { + const menuStructTreeKeyTypeAnnotationAtPath = path.join( + PathUtils.getRootCWDWithType('base'), + 'src', + 'page', + 'Nav', + 'sideMenu', + 'menuList', + 'menus', + `index.type.ts` + ); + + if (!existsSync(menuStructTreeKeyTypeAnnotationAtPath)) { + throw new Error( + `${menuStructTreeKeyTypeAnnotationAtPath} does not exist. Please check the path under the packages directory!` + ); + } + + return menuStructTreeKeyTypeAnnotationAtPath; + } + + static getRootCWDWithType( + type: 'sqle' | 'base' | 'shared' | 'icons' | 'provision' + ) { + return path.join(this.DMS_ROOT_CWD, 'packages', type); + } + + static getRelativePath(from: string, to: string, isFile?: boolean): string { + const normalize = (str: string) => { + return str.replace(/[\\/]+$/, '').split(/[\\/]+/); + }; + + const fromParts = normalize(from); + const toParts = normalize(to); + + if (isFile) { + fromParts.pop(); + toParts.pop(); + } + + let i = 0; + while ( + i < fromParts.length && + i < toParts.length && + fromParts[i] === toParts[i] + ) { + i++; + } + + const upCount = fromParts.length - i; + const relativeParts = [...Array(upCount).fill('..'), ...toParts.slice(i)]; + + return relativeParts.length === 0 ? '.' : relativeParts.join('/'); + } +} diff --git a/scripts/cli/create-dms-page/src/utils/spawn-util.ts b/scripts/cli/create-dms-page/src/utils/spawn-util.ts new file mode 100644 index 000000000..4989921bf --- /dev/null +++ b/scripts/cli/create-dms-page/src/utils/spawn-util.ts @@ -0,0 +1,19 @@ +import { spawn } from 'node:child_process'; + +export const spawnWrapper = ( + command: string, + args: string[] +): Promise => { + return new Promise((resolve, reject) => { + const child = spawn(command, args, { stdio: 'inherit' }); + child.on('close', (code) => { + if (code !== 0) { + reject({ + command: `${command} ${args.join(' ')}` + }); + return; + } + resolve(); + }); + }); +}; diff --git a/scripts/cli/create-dms-page/src/utils/str-utils.ts b/scripts/cli/create-dms-page/src/utils/str-utils.ts new file mode 100644 index 000000000..0d0f87a21 --- /dev/null +++ b/scripts/cli/create-dms-page/src/utils/str-utils.ts @@ -0,0 +1,28 @@ +export class StrUtils { + static convertFirstLetterToLowerCase(str: string) { + return str.replace(/^[A-Z]/, (match) => match.toLowerCase()); + } + + static convertFirstLetterToUpperCase(str: string) { + return str.replace(/^[a-z]/, (match) => match.toUpperCase()); + } + + static camelCaseToUpperCaseSnakeCase(str: string): string { + const firstChar = str.charAt(0).toLowerCase(); + const remainingChars = str + .slice(1) + .replace(/([A-Z])/g, '_$1') + .toLowerCase(); + return `${firstChar}${remainingChars}`.toUpperCase(); + } + + static isSvgContent(str: string): boolean { + try { + const parser = new DOMParser(); + const doc = parser.parseFromString(str, 'image/svg+xml'); + return doc.documentElement.tagName.toLowerCase() === 'svg'; + } catch (error) { + return false; + } + } +} diff --git a/scripts/cli/create-dms-page/src/utils/writer-utils.ts b/scripts/cli/create-dms-page/src/utils/writer-utils.ts new file mode 100644 index 000000000..c084487ea --- /dev/null +++ b/scripts/cli/create-dms-page/src/utils/writer-utils.ts @@ -0,0 +1,89 @@ +import { promises as fs, existsSync, readFileSync } from 'fs'; +import * as path from 'path'; +import * as prettier from 'prettier'; +import type { RequiredOptions } from 'prettier'; +import { logger } from './logger'; + +export class Writer { + private static options: Partial; + + public static async writeFile(src: string, content: string) { + try { + await this.makeDir(path.dirname(src)); + await fs.writeFile(src, content); + } catch (error) { + logger.error(`Write file:: ${src}`); + logger.error(error); + } + } + + public static async formattedWriteFile( + src: string, + content: string, + cwd: string + ) { + try { + this.getPrettierOption(cwd); + await this.makeDir(path.dirname(src)); + const formattedCode = await prettier.format(content, this.options); + await fs.writeFile(src, formattedCode); + } catch (error) { + logger.error(`Formatted write file:: ${src}`); + logger.error(error); + } + } + + private static getPrettierOption(cwd: string) { + if (this.options) { + return; + } + + ['.prettierrc', '.prettierrc.json'].forEach((v) => { + const configPath = path.resolve(cwd, v); + if (existsSync(configPath)) { + this.options = { + parser: 'typescript', + ...JSON.parse(readFileSync(configPath, 'utf-8')) + }; + } + }); + + if (this.options) { + return; + } + + ['.prettierrc.js', 'prettier.config.js', '.prettierrc.cjs'].forEach((v) => { + const configPath = path.resolve(cwd, v); + if (existsSync(configPath)) { + this.options = { + parser: 'typescript', + ...require(configPath) + }; + } + }); + + if (this.options) { + return; + } + + this.options = { + parser: 'typescript', + tabWidth: 2, + semi: true, + printWidth: 80, + trailingComma: 'none', + arrowParens: 'avoid', + proseWrap: 'preserve', + useTabs: false, + singleQuote: true, + bracketSpacing: true, + jsxBracketSameLine: false + }; + } + + private static async makeDir(dirname: string) { + if (!existsSync(dirname)) { + await fs.mkdir(dirname, { recursive: true }); + } + } +} diff --git a/scripts/cli/create-dms-page/tsconfig.json b/scripts/cli/create-dms-page/tsconfig.json new file mode 100644 index 000000000..af9c7a141 --- /dev/null +++ b/scripts/cli/create-dms-page/tsconfig.json @@ -0,0 +1,106 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "ES6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "CommonJS" /* Specify what module code is generated. */, + "rootDir": "./src" /* Specify the root folder within your source files. */, + "moduleResolution": "Node" /* Specify how TypeScript looks up a file from a given module specifier. */, + "baseUrl": "./" /* Specify the base directory to resolve non-relative module names. */, + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [ + // "./src", + // "./package.json" + // ] /* Allow multiple folders to be treated as one when resolving modules. */, + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + "resolveJsonModule": true /* Enable importing .json files */, + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + "allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */, + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + "skipDefaultLibCheck": true /* Skip type checking .d.ts files that are included with TypeScript. */, + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "exclude": ["node_modules", "dist", "./bin"], + "include": ["./src"] +}