From 5b5758c0eed7cfb40a46c6f6940f66e1b24bf17b Mon Sep 17 00:00:00 2001 From: koushenhai <2413176044@qq.com> Date: Sat, 27 Jul 2024 12:46:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=A7=BB=E9=99=A4seata=EF=BC=8C?= =?UTF-8?q?=E5=88=86=E5=B8=83=E5=BC=8F=E7=94=B1rocketmq=E6=9D=A5=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.adoc | 5 +- doc/db/kcloud_platform.sql | 154 - doc/db/kcloud_platform_nacos.sql | 592 +- doc/deploy/docker-compose.yml | 23 - doc/deploy/env/seata.env | 7 - laokou-cloud/laokou-gateway/pom.xml | 10 + .../.babelrc | 20 - .../.eslintignore | 4 - .../.eslintrc.json | 30 - .../.gitignore | 5 - .../LICENSE | 14 - .../README-zh.md | 633 - .../README.md | 497 - .../assets/context-pad.png | Bin 47316 -> 0 bytes .../assets/control.png | Bin 19872 -> 0 bytes .../assets/header.png | Bin 20968 -> 0 bytes .../assets/layout-connection.png | Bin 45856 -> 0 bytes .../assets/no-layout-connection.png | Bin 46879 -> 0 bytes .../assets/palette.png | Bin 42422 -> 0 bytes .../assets/placeholder.png | Bin 79236 -> 0 bytes .../assets/properties-panel.png | Bin 290167 -> 0 bytes .../assets/provider.png | Bin 257875 -> 0 bytes .../assets/waypoint.png | Bin 52075 -> 0 bytes .../package-lock.json | 17651 ---------------- .../package.json | 65 - .../public/banner.png | Bin 21024 -> 0 bytes .../public/favicon.ico | Bin 3870 -> 0 bytes .../public/logo.jpeg | Bin 3692 -> 0 bytes .../public/robots.txt | 3 - .../public/test.json | 108 - .../src/Editor.js | 264 - .../src/control/ExportControl.js | 78 - .../src/control/ImportControl.js | 56 - .../src/control/index.js | 35 - .../src/index.css | 78 - .../src/index.html | 52 - .../src/index.js | 49 - .../src/layout/Layouter.js | 93 - .../layout/behavior/AttachCatchBehavior.js | 43 - .../behavior/LayoutConnectionBehavior.js | 326 - .../layout/behavior/LayoutUpdateBehavior.js | 94 - .../behavior/ReplaceConnectionBehavior.js | 56 - .../src/layout/behavior/index.js | 34 - .../src/layout/index.js | 26 - .../src/modeling/ElementFactory.js | 59 - .../src/modeling/Modeling.js | 120 - .../src/modeling/SagaExporter.js | 107 - .../src/modeling/SagaFactory.js | 66 - .../src/modeling/SagaImporter.js | 207 - .../src/modeling/SagaRules.js | 138 - .../src/modeling/index.js | 50 - .../properties-panel/PanelHeaderProvider.js | 32 - .../PanelPlaceholderProvider.js | 35 - .../src/properties-panel/PropertiesPanel.js | 232 - .../PropertiesPanelContext.js | 28 - .../PropertiesPanelRenderer.js | 235 - .../src/properties-panel/index.js | 28 - .../provider/PropertiesProvider.js | 93 - .../src/properties-panel/provider/index.js | 23 - .../provider/properties/BaseText.js | 54 - .../provider/properties/BaseTextArea.js | 54 - .../provider/properties/CommentProps.js | 38 - .../provider/properties/NameProps.js | 39 - .../provider/properties/StateProps.js | 91 - .../provider/properties/StyleProps.js | 62 - .../provider/properties/VersionProps.js | 37 - .../src/providers/ContextPadProvider.js | 129 - .../src/providers/PaletteProvider.js | 94 - .../src/providers/index.js | 28 - .../src/render/PathMap.js | 269 - .../src/render/Renderer.js | 697 - .../src/render/TextRenderer.js | 59 - .../src/render/index.js | 27 - .../src/spec/BaseSpec.js | 21 - .../src/spec/Catch.js | 31 - .../src/spec/Choice.js | 45 - .../src/spec/ChoiceEntry.js | 36 - .../src/spec/Compensation.js | 26 - .../src/spec/CompensationTrigger.js | 31 - .../src/spec/ExceptionMatch.js | 40 - .../src/spec/Fail.js | 35 - .../src/spec/ScriptTask.js | 30 - .../src/spec/ServiceTask.js | 30 - .../src/spec/StartState.js | 31 - .../src/spec/State.js | 39 - .../src/spec/StateMachine.js | 40 - .../src/spec/SubStateMachine.js | 29 - .../src/spec/Succeed.js | 30 - .../src/spec/TaskState.js | 53 - .../src/spec/Transition.js | 30 - .../src/spec/style/Edge.js | 37 - .../src/spec/style/EdgeStyle.js | 40 - .../src/spec/style/Node.js | 33 - .../src/spec/style/NodeStyle.js | 28 - .../src/utils/index.js | 73 - .../webpack.config.js | 46 - laokou-cloud/laokou-seata/Dockerfile | 25 - laokou-cloud/laokou-seata/pom.xml | 234 - .../server/AbstractTCInboundHandler.java | 344 - .../java/io/seata/server/ParameterParser.java | 200 - .../main/java/io/seata/server/SeataApp.java | 39 - .../src/main/java/io/seata/server/Server.java | 105 - .../java/io/seata/server/ServerRunner.java | 118 - .../java/io/seata/server/UUIDGenerator.java | 52 - .../server/auth/AbstractCheckAuthHandler.java | 54 - .../server/auth/DefaultCheckAuthHandler.java | 38 - .../cluster/listener/ClusterChangeEvent.java | 72 - .../listener/ClusterChangeListener.java | 29 - .../manager/ClusterWatcherManager.java | 110 - .../seata/server/cluster/raft/RaftServer.java | 128 - .../cluster/raft/RaftServerFactory.java | 250 - .../server/cluster/raft/RaftStateMachine.java | 321 - .../raft/context/SeataClusterContext.java | 75 - .../raft/execute/AbstractRaftMsgExecute.java | 33 - .../cluster/raft/execute/RaftMsgExecute.java | 33 - .../branch/AddBranchSessionExecute.java | 50 - .../branch/RemoveBranchSessionExecute.java | 51 - .../branch/UpdateBranchSessionExecute.java | 47 - .../global/AddGlobalSessionExecute.java | 44 - .../global/RemoveGlobalSessionExecute.java | 71 - .../global/UpdateGlobalSessionExecute.java | 56 - .../lock/BranchReleaseLockExecute.java | 45 - .../lock/GlobalReleaseLockExecute.java | 44 - .../raft/serializer/JacksonSerializer.java | 87 - .../cluster/raft/snapshot/RaftSnapshot.java | 139 - .../raft/snapshot/RaftSnapshotSerializer.java | 71 - .../raft/snapshot/StoreSnapshotFile.java | 58 - .../metadata/LeaderMetadataSnapshotFile.java | 96 - .../snapshot/session/RaftSessionSnapshot.java | 92 - .../snapshot/session/SessionSnapshotFile.java | 107 - .../raft/sync/RaftSyncMessageSerializer.java | 71 - .../cluster/raft/sync/msg/RaftBaseMsg.java | 47 - .../sync/msg/RaftBranchSessionSyncMsg.java | 63 - .../raft/sync/msg/RaftClusterMetadataMsg.java | 51 - .../sync/msg/RaftGlobalSessionSyncMsg.java | 51 - .../raft/sync/msg/RaftSyncMessage.java | 110 - .../raft/sync/msg/RaftSyncMsgType.java | 60 - .../sync/msg/dto/BranchTransactionDTO.java | 45 - .../sync/msg/dto/GlobalTransactionDTO.java | 35 - .../sync/msg/dto/RaftClusterMetadata.java | 94 - .../cluster/raft/util/RaftTaskUtil.java | 83 - .../seata/server/cluster/watch/Watcher.java | 106 - .../controller/BranchSessionController.java | 36 - .../controller/GlobalLockController.java | 51 - .../controller/GlobalSessionController.java | 51 - .../impl/db/BranchSessionDBServiceImpl.java | 105 - .../impl/db/GlobalLockDBServiceImpl.java | 147 - .../impl/db/GlobalSessionDBServiceImpl.java | 163 - .../file/BranchSessionFileServiceImpl.java | 40 - .../impl/file/GlobalLockFileServiceImpl.java | 165 - .../file/GlobalSessionFileServiceImpl.java | 100 - .../raft/BranchSessionRaftServiceImpl.java | 32 - .../impl/raft/GlobalLockRaftServiceImpl.java | 32 - .../raft/GlobalSessionRaftServiceImpl.java | 32 - .../redis/BranchSessionRedisServiceImpl.java | 66 - .../redis/GlobalLockRedisServiceImpl.java | 121 - .../redis/GlobalSessionRedisServiceImpl.java | 115 - .../server/console/param/GlobalLockParam.java | 116 - .../console/param/GlobalSessionParam.java | 102 - .../console/service/BranchSessionService.java | 35 - .../console/service/GlobalLockService.java | 36 - .../console/service/GlobalSessionService.java | 36 - .../server/console/vo/BranchSessionVO.java | 213 - .../seata/server/console/vo/GlobalLockVO.java | 188 - .../server/console/vo/GlobalSessionVO.java | 203 - .../server/controller/ClusterController.java | 139 - .../server/controller/HealthController.java | 44 - .../server/coordinator/AbstractCore.java | 256 - .../io/seata/server/coordinator/Core.java | 56 - .../coordinator/DefaultCoordinator.java | 629 - .../seata/server/coordinator/DefaultCore.java | 426 - .../server/coordinator/RaftCoordinator.java | 81 - .../TransactionCoordinatorInbound.java | 29 - .../TransactionCoordinatorOutbound.java | 51 - .../io/seata/server/env/ContainerHelper.java | 103 - .../java/io/seata/server/env/PortHelper.java | 134 - .../seata/server/event/EventBusManager.java | 38 - .../server/lock/AbstractLockManager.java | 196 - .../io/seata/server/lock/LockManager.java | 100 - .../server/lock/LockerManagerFactory.java | 76 - .../distributed/DistributedLockerFactory.java | 71 - .../SystemPropertyLoggerContextListener.java | 76 - ...ndedWhitespaceThrowableProxyConverter.java | 36 - .../appender/EnhancedLogstashEncoder.java | 45 - .../appender/MetricLogbackAppender.java | 55 - .../server/metrics/MeterIdConstants.java | 157 - .../seata/server/metrics/MetricsManager.java | 70 - .../server/metrics/MetricsPublisher.java | 96 - .../server/metrics/MetricsSubscriber.java | 232 - .../session/AbstractSessionManager.java | 206 - .../seata/server/session/BranchSession.java | 471 - .../server/session/BranchSessionHandler.java | 42 - .../seata/server/session/GlobalSession.java | 795 - .../server/session/GlobalSessionHandler.java | 36 - .../io/seata/server/session/Lockable.java | 41 - .../io/seata/server/session/Reloadable.java | 30 - .../server/session/SessionCondition.java | 143 - .../seata/server/session/SessionHelper.java | 469 - .../seata/server/session/SessionHolder.java | 406 - .../server/session/SessionLifecycle.java | 96 - .../session/SessionLifecycleListener.java | 91 - .../seata/server/session/SessionManager.java | 187 - .../session/SessionStatusValidator.java | 77 - .../listener/SeataPropertiesLoader.java | 81 - .../listener/ServerApplicationListener.java | 123 - .../server/storage/SessionConverter.java | 212 - .../db/lock/DataBaseDistributedLocker.java | 301 - .../storage/db/lock/DataBaseLockManager.java | 80 - .../storage/db/lock/DataBaseLocker.java | 151 - .../storage/db/lock/LockStoreDataBaseDAO.java | 464 - .../db/session/DataBaseSessionManager.java | 157 - .../DataBaseTransactionStoreManager.java | 256 - .../storage/db/store/LogStoreDataBaseDAO.java | 667 - .../server/storage/file/FlushDiskMode.java | 45 - .../server/storage/file/ReloadableStore.java | 42 - .../storage/file/TransactionWriteStore.java | 128 - .../storage/file/lock/FileLockManager.java | 61 - .../server/storage/file/lock/FileLocker.java | 225 - .../file/session/FileSessionManager.java | 397 - .../store/FileTransactionStoreManager.java | 685 - .../raft/lock/RaftDistributedLocker.java | 62 - .../storage/raft/lock/RaftLockManager.java | 99 - .../raft/session/RaftSessionManager.java | 237 - .../storage/redis/JedisPooledFactory.java | 152 - .../seata/server/storage/redis/LuaParser.java | 180 - .../redis/lock/RedisDistributedLocker.java | 90 - .../storage/redis/lock/RedisLockManager.java | 69 - .../storage/redis/lock/RedisLocker.java | 314 - .../redis/lock/RedisLockerFactory.java | 51 - .../storage/redis/lock/RedisLuaLocker.java | 237 - .../redis/session/RedisSessionManager.java | 146 - .../RedisLuaTransactionStoreManager.java | 361 - .../store/RedisTransactionStoreManager.java | 861 - .../RedisTransactionStoreManagerFactory.java | 50 - .../AbstractTransactionStoreManager.java | 61 - .../server/store/DbcpDataSourceProvider.java | 60 - .../server/store/DruidDataSourceProvider.java | 62 - .../store/HikariDataSourceProvider.java | 64 - .../seata/server/store/SessionStorable.java | 37 - .../io/seata/server/store/StoreConfig.java | 267 - .../server/store/TransactionStoreManager.java | 141 - .../seata/server/transaction/at/ATCore.java | 105 - .../server/transaction/saga/SagaCore.java | 240 - .../seata/server/transaction/tcc/TccCore.java | 38 - .../seata/server/transaction/xa/XACore.java | 46 - ...io.seata.core.rpc.RegisterCheckAuthHandler | 1 - .../io.seata.core.serializer.Serializer | 1 - .../io.seata.core.store.DistributedLocker | 3 - .../io.seata.core.store.db.DataSourceProvider | 3 - .../io.seata.server.coordinator.AbstractCore | 4 - .../services/io.seata.server.lock.LockManager | 4 - .../io.seata.server.session.SessionManager | 4 - .../spring-configuration-metadata.json | 22 - .../main/resources/META-INF/spring.factories | 4 - .../src/main/resources/application.yml | 92 - .../src/main/resources/banner.txt | 7 - .../docker/seata-server-entrypoint.sh | 23 - .../src/main/resources/logback-spring.xml | 110 - .../resources/logback/console-appender.xml | 29 - .../main/resources/logback/file-appender.xml | 85 - .../main/resources/logback/kafka-appender.xml | 50 - .../resources/logback/logstash-appender.xml | 45 - .../resources/logback/metric-appender.xml | 21 - .../lua/redisStore/deleteTransactionDO.lua | 56 - .../lua/redisStore/insertTransactionDO.lua | 49 - .../rollbackGlobalTransactionDO.lua | 57 - .../redisStore/updateBranchTransactionDO.lua | 55 - .../redisStore/updateGlobalTransactionDO.lua | 109 - .../lua/redislocker/acquireRedisLock.lua | 98 - .../resources/lua/redislocker/isLockable.lua | 33 - .../lua/redislocker/releaseRedisLock.lua | 117 - .../lua/redislocker/updateLockStatus.lua | 82 - .../src/main/resources/scg-keystore.p12 | Bin 2756 -> 0 bytes laokou-cloud/pom.xml | 3 +- laokou-common/laokou-common-bom/pom.xml | 26 +- laokou-common/laokou-common-core/pom.xml | 16 + .../common/exception/SystemException.java | 10 - .../main/resources/i18n/message.properties | 2 - .../main/resources/i18n/message_en.properties | 2 - .../resources/i18n/message_en_US.properties | 2 - .../resources/i18n/message_zh_CN.properties | 2 - laokou-common/laokou-common-nacos/pom.xml | 11 + laokou-common/laokou-common-seata/pom.xml | 40 - .../seata/handler/SeataExceptionHandler.java | 51 - .../common/seata/handler/package-info.java | 21 - laokou-common/pom.xml | 3 +- .../laokou-admin-infrastructure/pom.xml | 14 +- .../src/main/resources/bootstrap.yml | 3 - pom.xml | 16 - .../asciidoc/\345\274\200\347\257\207.adoc" | 2 +- test_error | 3 - 291 files changed, 65 insertions(+), 47106 deletions(-) delete mode 100644 doc/deploy/env/seata.env delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/.babelrc delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/.eslintignore delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/.eslintrc.json delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/.gitignore delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/LICENSE delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/README-zh.md delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/README.md delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/context-pad.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/control.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/header.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/layout-connection.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/no-layout-connection.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/palette.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/placeholder.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/properties-panel.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/provider.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/assets/waypoint.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/package-lock.json delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/package.json delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/public/banner.png delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/public/favicon.ico delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/public/logo.jpeg delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/public/robots.txt delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/public/test.json delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/Editor.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/ExportControl.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/ImportControl.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.css delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.html delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/Layouter.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/AttachCatchBehavior.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/LayoutConnectionBehavior.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/LayoutUpdateBehavior.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/ReplaceConnectionBehavior.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/ElementFactory.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/Modeling.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaExporter.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaFactory.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaImporter.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaRules.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PanelHeaderProvider.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PanelPlaceholderProvider.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanel.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanelContext.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanelRenderer.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/PropertiesProvider.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/BaseText.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/BaseTextArea.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/CommentProps.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/NameProps.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/StateProps.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/StyleProps.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/VersionProps.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/ContextPadProvider.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/PaletteProvider.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/PathMap.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/Renderer.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/TextRenderer.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/BaseSpec.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Catch.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Choice.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ChoiceEntry.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Compensation.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/CompensationTrigger.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ExceptionMatch.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Fail.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ScriptTask.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ServiceTask.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/StartState.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/State.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/StateMachine.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/SubStateMachine.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Succeed.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/TaskState.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Transition.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/Edge.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/EdgeStyle.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/Node.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/NodeStyle.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/src/utils/index.js delete mode 100644 laokou-cloud/laokou-seata-saga-statemachine-designer/webpack.config.js delete mode 100644 laokou-cloud/laokou-seata/Dockerfile delete mode 100644 laokou-cloud/laokou-seata/pom.xml delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/AbstractTCInboundHandler.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/ParameterParser.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/SeataApp.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/Server.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/ServerRunner.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/UUIDGenerator.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/auth/AbstractCheckAuthHandler.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/auth/DefaultCheckAuthHandler.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/listener/ClusterChangeEvent.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/listener/ClusterChangeListener.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/manager/ClusterWatcherManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftServer.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftServerFactory.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftStateMachine.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/context/SeataClusterContext.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/AbstractRaftMsgExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/RaftMsgExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/AddBranchSessionExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/RemoveBranchSessionExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/UpdateBranchSessionExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/AddGlobalSessionExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/RemoveGlobalSessionExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/UpdateGlobalSessionExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/lock/BranchReleaseLockExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/lock/GlobalReleaseLockExecute.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/serializer/JacksonSerializer.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/RaftSnapshot.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/RaftSnapshotSerializer.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/StoreSnapshotFile.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/metadata/LeaderMetadataSnapshotFile.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/session/RaftSessionSnapshot.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/session/SessionSnapshotFile.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/RaftSyncMessageSerializer.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftBaseMsg.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftBranchSessionSyncMsg.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftClusterMetadataMsg.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftGlobalSessionSyncMsg.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftSyncMessage.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftSyncMsgType.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/BranchTransactionDTO.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/GlobalTransactionDTO.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/util/RaftTaskUtil.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/watch/Watcher.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/BranchSessionController.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/GlobalLockController.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/GlobalSessionController.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/BranchSessionDBServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/GlobalLockDBServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/GlobalSessionDBServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/BranchSessionFileServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/GlobalLockFileServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/GlobalSessionFileServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/BranchSessionRaftServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/GlobalLockRaftServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/GlobalSessionRaftServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/BranchSessionRedisServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/GlobalLockRedisServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/GlobalSessionRedisServiceImpl.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/param/GlobalLockParam.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/param/GlobalSessionParam.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/BranchSessionService.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/GlobalLockService.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/GlobalSessionService.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/BranchSessionVO.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/GlobalLockVO.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/GlobalSessionVO.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/controller/ClusterController.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/controller/HealthController.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/AbstractCore.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/Core.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/DefaultCore.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/RaftCoordinator.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/TransactionCoordinatorInbound.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/TransactionCoordinatorOutbound.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/env/ContainerHelper.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/env/PortHelper.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/event/EventBusManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/AbstractLockManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/LockManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/LockerManagerFactory.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/distributed/DistributedLockerFactory.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/listener/SystemPropertyLoggerContextListener.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/ExtendedWhitespaceThrowableProxyConverter.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/appender/EnhancedLogstashEncoder.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/appender/MetricLogbackAppender.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MeterIdConstants.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsPublisher.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsSubscriber.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/AbstractSessionManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/BranchSession.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/BranchSessionHandler.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/GlobalSession.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/GlobalSessionHandler.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/Lockable.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/Reloadable.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionCondition.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionHelper.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionHolder.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionLifecycle.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionLifecycleListener.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionStatusValidator.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/spring/listener/SeataPropertiesLoader.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/spring/listener/ServerApplicationListener.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/SessionConverter.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseDistributedLocker.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseLocker.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/LockStoreDataBaseDAO.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/FlushDiskMode.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/ReloadableStore.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/TransactionWriteStore.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/lock/FileLockManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/lock/FileLocker.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/store/FileTransactionStoreManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/lock/RaftDistributedLocker.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/lock/RaftLockManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/session/RaftSessionManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/LuaParser.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisDistributedLocker.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLocker.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLockerFactory.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLuaLocker.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisLuaTransactionStoreManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManagerFactory.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/AbstractTransactionStoreManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/DruidDataSourceProvider.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/HikariDataSourceProvider.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/SessionStorable.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/StoreConfig.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/TransactionStoreManager.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/at/ATCore.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/saga/SagaCore.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/tcc/TccCore.java delete mode 100644 laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/xa/XACore.java delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.rpc.RegisterCheckAuthHandler delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.serializer.Serializer delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.store.DistributedLocker delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceProvider delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.coordinator.AbstractCore delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.lock.LockManager delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.session.SessionManager delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/META-INF/spring-configuration-metadata.json delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/META-INF/spring.factories delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/application.yml delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/banner.txt delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/docker/seata-server-entrypoint.sh delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/logback-spring.xml delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/logback/console-appender.xml delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/logback/file-appender.xml delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/logback/kafka-appender.xml delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/logback/logstash-appender.xml delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/logback/metric-appender.xml delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/deleteTransactionDO.lua delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/insertTransactionDO.lua delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/rollbackGlobalTransactionDO.lua delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/updateBranchTransactionDO.lua delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/updateGlobalTransactionDO.lua delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/acquireRedisLock.lua delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/isLockable.lua delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/releaseRedisLock.lua delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/updateLockStatus.lua delete mode 100644 laokou-cloud/laokou-seata/src/main/resources/scg-keystore.p12 delete mode 100644 laokou-common/laokou-common-seata/pom.xml delete mode 100644 laokou-common/laokou-common-seata/src/main/java/org/laokou/common/seata/handler/SeataExceptionHandler.java delete mode 100644 laokou-common/laokou-common-seata/src/main/java/org/laokou/common/seata/handler/package-info.java diff --git a/README.adoc b/README.adoc index ee4c277bec..6dddd00793 100644 --- a/README.adoc +++ b/README.adoc @@ -90,7 +90,6 @@ image::doc/image/老寇IoT云平台架构图-阿里巴巴.png[架构图,align=ce |Spring Authorization Server |1.3.1 |Mybatis Plus |3.5.7 |Nacos |2.4.0.1 -|Seata |2.0.0 |Sentinel |1.8.8 |Redis |7.2.5 |Elasticsearch |8.14.3 @@ -113,7 +112,7 @@ image::doc/image/老寇IoT云平台架构图-阿里巴巴.png[架构图,align=ce - 负载均衡:Spring Cloud Loadbalancer - 服务熔断&降级&限流:Sentinel - 分库分表:Mybatis Plus -- 分布式事务:Seata & RocketMQ +- 分布式事务:RocketMQ - 消息队列:RocketMQ & Kafka & MQTT - 服务监控:Spring Boot Admin & Prometheus - 高亮搜索:Elasticsearch @@ -167,7 +166,6 @@ image::doc/image/老寇IoT云平台架构图-阿里巴巴.png[架构图,align=ce └── laokou-common-openfeign --- 远程调用组件 └── laokou-common-data-cache --- 数据缓存组件 └── laokou-common-mybatis-plus --- 对象映射组件 - └── laokou-common-seata --- 分布式事务组件 └── laokou-common-tdengine --- 时序数据库组件 └── laokou-common-sentinel --- 服务限流&熔断降级组件 ├── laokou-cloud @@ -175,7 +173,6 @@ image::doc/image/老寇IoT云平台架构图-阿里巴巴.png[架构图,align=ce └── laokou-monitor --- 服务监控 └── laokou-register --- 服务治理 └── laokou-sentinel --- 流量治理 - └── laokou-seata --- 分布式事务 └── laokou-snail-job --- 分布式任务调度 ├── laokou-service └── laokou-iot --- 物联网模块 diff --git a/doc/db/kcloud_platform.sql b/doc/db/kcloud_platform.sql index 755377e89e..53a6496b1f 100644 --- a/doc/db/kcloud_platform.sql +++ b/doc/db/kcloud_platform.sql @@ -2350,160 +2350,6 @@ VALUES ('95TxSsTPFA3tF12TBSMmUVK0da', '95TxSsTPFA3tF12TBSMmUVK0da', '2024-04-30 '{"@class":"java.util.Collections$UnmodifiableMap","settings.client.require-proof-key":false,"settings.client.require-authorization-consent":true}', '{"@class":"java.util.Collections$UnmodifiableMap","settings.token.reuse-refresh-tokens":true,"settings.token.id-token-signature-algorithm":["org.springframework.security.oauth2.jose.jws.SignatureAlgorithm","RS256"],"settings.token.access-token-time-to-live":["java.time.Duration",3600.000000000],"settings.token.access-token-format":{"@class":"org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat","value":"self-contained"},"settings.token.refresh-token-time-to-live":["java.time.Duration",21600.000000000],"settings.token.authorization-code-time-to-live":["java.time.Duration",3600.000000000],"settings.token.device-code-time-to-live":["java.time.Duration",3600.000000000]}'); -create table if not exists public.seata_state_inst -( - id varchar(48) not null, - machine_inst_id varchar(128) not null, - name varchar(128) not null, - type varchar(20), - service_name varchar(128), - service_method varchar(128), - service_type varchar(16), - business_key varchar(48), - state_id_compensated_for varchar(50), - state_id_retried_for varchar(50), - gmt_started timestamp(3) not null, - is_for_update smallint, - input_params text, - output_params text, - status varchar(2) not null, - excep bytea, - gmt_updated timestamp(3), - gmt_end timestamp(3), - primary key (id, machine_inst_id) -); - -comment on column public.seata_state_inst.id is 'id'; - -comment on column public.seata_state_inst.machine_inst_id is 'state machine instance id'; - -comment on column public.seata_state_inst.name is 'state name'; - -comment on column public.seata_state_inst.type is 'state type'; - -comment on column public.seata_state_inst.service_name is 'service name'; - -comment on column public.seata_state_inst.service_method is 'method name'; - -comment on column public.seata_state_inst.service_type is 'service type'; - -comment on column public.seata_state_inst.business_key is 'business key'; - -comment on column public.seata_state_inst.state_id_compensated_for is 'state compensated for'; - -comment on column public.seata_state_inst.state_id_retried_for is 'state retried for'; - -comment on column public.seata_state_inst.gmt_started is 'start time'; - -comment on column public.seata_state_inst.is_for_update is 'is service for update'; - -comment on column public.seata_state_inst.input_params is 'input parameters'; - -comment on column public.seata_state_inst.output_params is 'output parameters'; - -comment on column public.seata_state_inst.status is 'status(SU succeed|FA failed|UN unknown|SK skipped|RU running)'; - -comment on column public.seata_state_inst.excep is 'exception'; - -comment on column public.seata_state_inst.gmt_updated is 'update time'; - -comment on column public.seata_state_inst.gmt_end is 'end time'; - -alter table public.seata_state_inst - owner to root; - -create table if not exists public.seata_state_machine_def -( - id varchar(32) not null - primary key, - name varchar(128) not null, - tenant_id varchar(32) not null, - app_name varchar(32) not null, - type varchar(20), - comment_ varchar(255), - ver varchar(16) not null, - gmt_create timestamp(3) not null, - status varchar(2) not null, - content text, - recover_strategy varchar(16) -); - -comment on column public.seata_state_machine_def.id is 'id'; - -comment on column public.seata_state_machine_def.name is 'name'; - -comment on column public.seata_state_machine_def.tenant_id is 'tenant id'; - -comment on column public.seata_state_machine_def.app_name is 'application name'; - -comment on column public.seata_state_machine_def.type is 'state language type'; - -comment on column public.seata_state_machine_def.comment_ is 'comment'; - -comment on column public.seata_state_machine_def.ver is 'version'; - -comment on column public.seata_state_machine_def.gmt_create is 'create time'; - -comment on column public.seata_state_machine_def.status is 'status(AC:active|IN:inactive)'; - -comment on column public.seata_state_machine_def.content is 'content'; - -comment on column public.seata_state_machine_def.recover_strategy is 'transaction recover strategy(compensate|retry)'; - -alter table public.seata_state_machine_def - owner to root; - -create table if not exists public.seata_state_machine_inst -( - id varchar(128) not null - primary key, - machine_id varchar(32) not null, - tenant_id varchar(32) not null, - parent_id varchar(128), - gmt_started timestamp(3) not null, - business_key varchar(48), - start_params text, - gmt_end timestamp(3), - excep bytea, - end_params text, - status varchar(2), - compensation_status varchar(2), - is_running smallint, - gmt_updated timestamp(3) not null -); - -comment on column public.seata_state_machine_inst.id is 'id'; - -comment on column public.seata_state_machine_inst.machine_id is 'state machine definition id'; - -comment on column public.seata_state_machine_inst.tenant_id is 'tenant id'; - -comment on column public.seata_state_machine_inst.parent_id is 'parent id'; - -comment on column public.seata_state_machine_inst.gmt_started is 'start time'; - -comment on column public.seata_state_machine_inst.business_key is 'business key'; - -comment on column public.seata_state_machine_inst.start_params is 'start parameters'; - -comment on column public.seata_state_machine_inst.gmt_end is 'end time'; - -comment on column public.seata_state_machine_inst.excep is 'exception'; - -comment on column public.seata_state_machine_inst.end_params is 'end parameters'; - -comment on column public.seata_state_machine_inst.status is 'status(SU succeed|FA failed|UN unknown|SK skipped|RU running)'; - -comment on column public.seata_state_machine_inst.compensation_status is 'compensation status(SU succeed|FA failed|UN unknown|SK skipped|RU running)'; - -comment on column public.seata_state_machine_inst.is_running is 'is running(0 no|1 yes)'; - -alter table public.seata_state_machine_inst - owner to root; - -create unique index if not exists seata_state_machine_inst_business_key_tenant_id_idx - on public.seata_state_machine_inst (business_key, tenant_id); - create table boot_sys_api_log ( id bigint generated by default as identity diff --git a/doc/db/kcloud_platform_nacos.sql b/doc/db/kcloud_platform_nacos.sql index 52e1829a3b..3fb32f91cc 100644 --- a/doc/db/kcloud_platform_nacos.sql +++ b/doc/db/kcloud_platform_nacos.sql @@ -664,157 +664,7 @@ VALUES (2178, 'application-logstash.yaml', 'LAOKOU_GROUP', 'spring: access-token: yRagfkAddGXdTySYTFzhvMguinulMIMSCcXUbljWDhe intentionalities: 7', '81c3de6319db8560c68935977f2d141f', '2023-11-03 07:37:45', '2024-01-30 14:46:47', 'nacos', '0:0:0:0:0:0:0:1', 'laokou-logstash', 'a61abd4c-ef96-42a5-99a1-616adee531f3', '', '', '', 'yaml', '', ''); -INSERT INTO "public"."config_info" -VALUES (2260, 'seataServer.properties', 'SEATA_GROUP', '#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html -#Transport configuration, for client and server -transport.type=TCP -transport.server=NIO -transport.heartbeat=true -transport.enableTmClientBatchSendRequest=false -transport.enableRmClientBatchSendRequest=true -transport.enableTcServerBatchSendResponse=false -transport.rpcRmRequestTimeout=30000 -transport.rpcTmRequestTimeout=30000 -transport.rpcTcRequestTimeout=30000 -transport.threadFactory.bossThreadPrefix=NettyBoss -transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker -transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler -transport.threadFactory.shareBossWorker=false -transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector -transport.threadFactory.clientSelectorThreadSize=1 -transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread -transport.threadFactory.bossThreadSize=1 -transport.threadFactory.workerThreadSize=default -transport.shutdown.wait=3 -transport.serialization=seata -transport.compressor=none - -#Transaction routing rules configuration, only for the client -service.vgroupMapping.default_tx_group=default -#If you use a registry, you can ignore it -service.default.grouplist=seata.laokou.org:8091 -service.enableDegrade=false -service.disableGlobalTransaction=false - -client.metadataMaxAgeMs=30000 -#Transaction rule configuration, only for the client -client.rm.asyncCommitBufferLimit=10000 -client.rm.lock.retryInterval=10 -client.rm.lock.retryTimes=30 -client.rm.lock.retryPolicyBranchRollbackOnConflict=true -client.rm.reportRetryCount=5 -client.rm.tableMetaCheckEnable=true -client.rm.tableMetaCheckerInterval=60000 -client.rm.sqlParserType=hikari -client.rm.reportSuccessEnable=false -client.rm.sagaBranchRegisterEnable=false -client.rm.sagaJsonParser=jackson -client.rm.tccActionInterceptorOrder=-2147482648 -client.tm.commitRetryCount=5 -client.tm.rollbackRetryCount=5 -client.tm.defaultGlobalTransactionTimeout=60000 -client.tm.degradeCheck=false -client.tm.degradeCheckAllowTimes=10 -client.tm.degradeCheckPeriod=2000 -client.tm.interceptorOrder=-2147482648 -client.undo.dataValidation=true -client.undo.logSerialization=jackson -client.undo.onlyCareUpdateColumns=true -server.undo.logSaveDays=7 -server.undo.logDeletePeriod=86400000 -client.undo.logTable=undo_log -client.undo.compress.enable=true -client.undo.compress.type=zip -client.undo.compress.threshold=64k -#For TCC transaction mode -tcc.fence.logTableName=tcc_fence_log -tcc.fence.cleanPeriod=1h -# You can choose from the following options: fastjson, jackson, gson -tcc.contextJsonParserType=fastjson - -#Log rule configuration, for client and server -log.exceptionRate=100 - -#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional. -store.mode=redis -store.lock.mode=redis -store.session.mode=redis -#Used for password encryption -store.publicKey= - -#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block. -store.file.dir=file_store/data -store.file.maxBranchSessionSize=16384 -store.file.maxGlobalSessionSize=512 -store.file.fileWriteBufferCacheSize=16384 -store.file.flushDiskMode=async -store.file.sessionReloadReadSize=100 - -#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block. -store.db.datasource=hikari -store.db.dbType=mysql -store.db.driverClassName=com.mysql.cj.jdbc.Driver -store.db.url=jdbc:mysql://mysql.laokou.org:3306/kcloud_platform_alibaba_seata?useUnicode=true&rewriteBatchedStatements=true -store.db.user=root -store.db.password=laokou123 -store.db.minConn=5 -store.db.maxConn=30 -store.db.globalTable=global_table -store.db.branchTable=branch_table -store.db.distributedLockTable=distributed_lock -store.db.queryLimit=100 -store.db.lockTable=lock_table -store.db.maxWait=5000 - -#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block. -store.redis.mode=single -store.redis.type=pipeline -store.redis.single.host=redis.laokou.org -store.redis.single.port=6379 -store.redis.sentinel.masterName= -store.redis.sentinel.sentinelHosts= -store.redis.sentinel.sentinelPassword= -store.redis.maxConn=10 -store.redis.minConn=1 -store.redis.maxTotal=100 -store.redis.database=0 -store.redis.password=laokou123 -store.redis.queryLimit=100 - -#Transaction rule configuration, only for the server -server.recovery.committingRetryPeriod=1000 -server.recovery.asynCommittingRetryPeriod=1000 -server.recovery.rollbackingRetryPeriod=1000 -server.recovery.timeoutRetryPeriod=1000 -server.maxCommitRetryTimeout=-1 -server.maxRollbackRetryTimeout=-1 -server.rollbackRetryTimeoutUnlockEnable=false -server.distributedLockExpireTime=10000 -server.session.branchAsyncQueueSize=5000 -server.session.enableBranchAsyncRemove=false -server.enableParallelRequestHandle=true -server.enableParallelHandleBranch=false - -server.raft.cluster=seata.laokou.org:7091,seata.laokou.org:7092,seata.laokou.org:7093 -server.raft.snapshotInterval=600 -server.raft.applyBatch=32 -server.raft.maxAppendBufferSize=262144 -server.raft.maxReplicatorInflightMsgs=256 -server.raft.disruptorBufferSize=16384 -server.raft.electionTimeoutMs=2000 -server.raft.reporterEnabled=false -server.raft.reporterInitialDelay=60 -server.raft.serialization=jackson -server.raft.compressor=none -server.raft.sync=true - -#Metrics configuration, only for the server -metrics.enabled=false -metrics.registryType=compact -metrics.exporterList=prometheus -metrics.exporterPrometheusPort=9898', '26217408b5ee26c2fec37325ea785e2f', '2023-11-27 16:36:34', '2024-03-04 11:55:27', - 'nacos', '0:0:0:0:0:0:0:1', 'laokou-seata', 'a61abd4c-ef96-42a5-99a1-616adee531f3', 'seata配置', '', '', - 'properties', '', ''); + INSERT INTO "public"."config_info" VALUES (1570, 'admin-degrade.json', 'LAOKOU_GROUP', '[ { @@ -977,50 +827,7 @@ knife4j: gateway: enabled: true', 'b4ccbf4df335be2d07acf78a456ad733', '2024-05-25 18:13:33.458', '2024-05-25 18:46:18.892', 'nacos', '127.0.0.1', 'laokou-gateway', '0dac1a68-2f01-40df-bd26-bf0cb199057a', 'gateway配置', '', '', 'yaml', '', ''); -INSERT INTO "public"."config_info" -VALUES (1254, 'application-common-seata.yaml', 'LAOKOU_GROUP', '# seata -seata: - saga: - enabled: true - state-machine: - enable-async: true - table-prefix: seata_ - async-thread-pool: - core-pool-size: 1 - max-pool-size: 20 - keep-alive-time: 60 - trans-operation-timeout: 1800000 - service-invoke-timeout: 300000 - auto-register-resources: true - resources: - - classpath*:seata/saga/statelang/**/*.json - default-tenant-id: 0 - charset: UTF-8 - client: - tm: - default-global-transaction-timeout: 30000 - config: - type: nacos - nacos: - server-addr: https://nacos.laokou.org:8848 - namespace: a61abd4c-ef96-42a5-99a1-616adee531f3 - username: nacos - password: nacos - group: SEATA_GROUP - data-id: seataServer.properties - registry: - type: nacos - nacos: - namespace: a61abd4c-ef96-42a5-99a1-616adee531f3 - group: SEATA_GROUP - username: nacos - password: nacos - server-addr: https://nacos.laokou.org:8848 - enabled: true - tx-service-group: default_tx_group - data-source-proxy-mode: AT', '20aac9490838d442049d7ddfd8d0a7d2', '2023-01-18 13:53:56', '2024-05-15 00:13:12.626', - 'nacos', '0:0:0:0:0:0:0:1', '', 'a61abd4c-ef96-42a5-99a1-616adee531f3', 'seata公共配置', '', '', 'yaml', '', - ''); + INSERT INTO "public"."config_info" VALUES (33, 'gateway-flow.json', 'LAOKOU_GROUP', '[ { @@ -1095,157 +902,7 @@ VALUES (41, 'application-logstash.yaml', 'LAOKOU_GROUP', 'spring: access-token: yRagfkAddGXdTySYTFzhvMguinulMIMSCcXUbljWDhe intentionalities: 7', '81c3de6319db8560c68935977f2d141f', '2024-05-25 18:13:10.655', '2024-05-25 18:13:10.655', NULL, '127.0.0.1', 'laokou-logstash', '8140e92b-fb43-48f5-b63b-7506185206a5', '', NULL, NULL, 'yaml', NULL, ''); -INSERT INTO "public"."config_info" -VALUES (42, 'seataServer.properties', 'SEATA_GROUP', '#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html -#Transport configuration, for client and server -transport.type=TCP -transport.server=NIO -transport.heartbeat=true -transport.enableTmClientBatchSendRequest=false -transport.enableRmClientBatchSendRequest=true -transport.enableTcServerBatchSendResponse=false -transport.rpcRmRequestTimeout=30000 -transport.rpcTmRequestTimeout=30000 -transport.rpcTcRequestTimeout=30000 -transport.threadFactory.bossThreadPrefix=NettyBoss -transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker -transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler -transport.threadFactory.shareBossWorker=false -transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector -transport.threadFactory.clientSelectorThreadSize=1 -transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread -transport.threadFactory.bossThreadSize=1 -transport.threadFactory.workerThreadSize=default -transport.shutdown.wait=3 -transport.serialization=seata -transport.compressor=none - -#Transaction routing rules configuration, only for the client -service.vgroupMapping.default_tx_group=default -#If you use a registry, you can ignore it -service.default.grouplist=seata.laokou.org:8091 -service.enableDegrade=false -service.disableGlobalTransaction=false - -client.metadataMaxAgeMs=30000 -#Transaction rule configuration, only for the client -client.rm.asyncCommitBufferLimit=10000 -client.rm.lock.retryInterval=10 -client.rm.lock.retryTimes=30 -client.rm.lock.retryPolicyBranchRollbackOnConflict=true -client.rm.reportRetryCount=5 -client.rm.tableMetaCheckEnable=true -client.rm.tableMetaCheckerInterval=60000 -client.rm.sqlParserType=hikari -client.rm.reportSuccessEnable=false -client.rm.sagaBranchRegisterEnable=false -client.rm.sagaJsonParser=jackson -client.rm.tccActionInterceptorOrder=-2147482648 -client.tm.commitRetryCount=5 -client.tm.rollbackRetryCount=5 -client.tm.defaultGlobalTransactionTimeout=60000 -client.tm.degradeCheck=false -client.tm.degradeCheckAllowTimes=10 -client.tm.degradeCheckPeriod=2000 -client.tm.interceptorOrder=-2147482648 -client.undo.dataValidation=true -client.undo.logSerialization=jackson -client.undo.onlyCareUpdateColumns=true -server.undo.logSaveDays=7 -server.undo.logDeletePeriod=86400000 -client.undo.logTable=undo_log -client.undo.compress.enable=true -client.undo.compress.type=zip -client.undo.compress.threshold=64k -#For TCC transaction mode -tcc.fence.logTableName=tcc_fence_log -tcc.fence.cleanPeriod=1h -# You can choose from the following options: fastjson, jackson, gson -tcc.contextJsonParserType=fastjson - -#Log rule configuration, for client and server -log.exceptionRate=100 - -#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional. -store.mode=redis -store.lock.mode=redis -store.session.mode=redis -#Used for password encryption -store.publicKey= - -#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block. -store.file.dir=file_store/data -store.file.maxBranchSessionSize=16384 -store.file.maxGlobalSessionSize=512 -store.file.fileWriteBufferCacheSize=16384 -store.file.flushDiskMode=async -store.file.sessionReloadReadSize=100 - -#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block. -store.db.datasource=hikari -store.db.dbType=mysql -store.db.driverClassName=com.mysql.cj.jdbc.Driver -store.db.url=jdbc:mysql://mysql.laokou.org:3306/kcloud_platform_alibaba_seata?useUnicode=true&rewriteBatchedStatements=true -store.db.user=root -store.db.password=laokou123 -store.db.minConn=5 -store.db.maxConn=30 -store.db.globalTable=global_table -store.db.branchTable=branch_table -store.db.distributedLockTable=distributed_lock -store.db.queryLimit=100 -store.db.lockTable=lock_table -store.db.maxWait=5000 - -#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block. -store.redis.mode=single -store.redis.type=pipeline -store.redis.single.host=redis.laokou.org -store.redis.single.port=6379 -store.redis.sentinel.masterName= -store.redis.sentinel.sentinelHosts= -store.redis.sentinel.sentinelPassword= -store.redis.maxConn=10 -store.redis.minConn=1 -store.redis.maxTotal=100 -store.redis.database=0 -store.redis.password=laokou123 -store.redis.queryLimit=100 - -#Transaction rule configuration, only for the server -server.recovery.committingRetryPeriod=1000 -server.recovery.asynCommittingRetryPeriod=1000 -server.recovery.rollbackingRetryPeriod=1000 -server.recovery.timeoutRetryPeriod=1000 -server.maxCommitRetryTimeout=-1 -server.maxRollbackRetryTimeout=-1 -server.rollbackRetryTimeoutUnlockEnable=false -server.distributedLockExpireTime=10000 -server.session.branchAsyncQueueSize=5000 -server.session.enableBranchAsyncRemove=false -server.enableParallelRequestHandle=true -server.enableParallelHandleBranch=false - -server.raft.cluster=seata.laokou.org:7091,seata.laokou.org:7092,seata.laokou.org:7093 -server.raft.snapshotInterval=600 -server.raft.applyBatch=32 -server.raft.maxAppendBufferSize=262144 -server.raft.maxReplicatorInflightMsgs=256 -server.raft.disruptorBufferSize=16384 -server.raft.electionTimeoutMs=2000 -server.raft.reporterEnabled=false -server.raft.reporterInitialDelay=60 -server.raft.serialization=jackson -server.raft.compressor=none -server.raft.sync=true - -#Metrics configuration, only for the server -metrics.enabled=false -metrics.registryType=compact -metrics.exporterList=prometheus -metrics.exporterPrometheusPort=9898', '26217408b5ee26c2fec37325ea785e2f', '2024-05-25 18:13:10.662', - '2024-05-25 18:13:10.662', NULL, '127.0.0.1', 'laokou-seata', '8140e92b-fb43-48f5-b63b-7506185206a5', - 'seata配置', NULL, NULL, 'properties', NULL, ''); + INSERT INTO "public"."config_info" VALUES (44, 'admin-degrade.json', 'LAOKOU_GROUP', '[ { @@ -1418,49 +1075,7 @@ springdoc: swagger-ui: path: /swagger-ui.html', 'e83a99587ac917866dee016df29fd662', '2024-05-25 18:13:10.622', '2024-05-26 00:02:32.884', 'nacos', '127.0.0.1', '', '8140e92b-fb43-48f5-b63b-7506185206a5', '', '', '', 'yaml', '', ''); -INSERT INTO "public"."config_info" -VALUES (45, 'application-common-seata.yaml', 'LAOKOU_GROUP', '# seata -seata: - saga: - enabled: true - state-machine: - enable-async: true - table-prefix: seata_ - async-thread-pool: - core-pool-size: 1 - max-pool-size: 20 - keep-alive-time: 60 - trans-operation-timeout: 1800000 - service-invoke-timeout: 300000 - auto-register-resources: true - resources: - - classpath*:seata/saga/statelang/**/*.json - default-tenant-id: 0 - charset: UTF-8 - client: - tm: - default-global-transaction-timeout: 30000 - config: - type: nacos - nacos: - server-addr: https://nacos.laokou.org:8848 - namespace: 8140e92b-fb43-48f5-b63b-7506185206a5 - username: nacos - password: nacos - group: SEATA_GROUP - data-id: seataServer.properties - registry: - type: nacos - nacos: - namespace: 8140e92b-fb43-48f5-b63b-7506185206a5 - group: SEATA_GROUP - username: nacos - password: nacos - server-addr: https://nacos.laokou.org:8848 - enabled: true - tx-service-group: default_tx_group - data-source-proxy-mode: AT', 'eeeffb74bfa083c4186b2690f4d16288', '2024-05-25 18:13:10.683', '2024-05-25 18:50:17.125', - 'nacos', '127.0.0.1', '', '8140e92b-fb43-48f5-b63b-7506185206a5', 'seata公共配置', '', '', 'yaml', '', ''); + INSERT INTO "public"."config_info" VALUES (27, 'application-common-redis.yaml', 'LAOKOU_GROUP', '# jasypt jasypt: @@ -2032,157 +1647,7 @@ VALUES (63, 'application-logstash.yaml', 'LAOKOU_GROUP', 'spring: access-token: yRagfkAddGXdTySYTFzhvMguinulMIMSCcXUbljWDhe intentionalities: 7', '81c3de6319db8560c68935977f2d141f', '2024-05-25 18:13:33.419', '2024-05-25 18:13:33.419', NULL, '127.0.0.1', 'laokou-logstash', '0dac1a68-2f01-40df-bd26-bf0cb199057a', '', NULL, NULL, 'yaml', NULL, ''); -INSERT INTO "public"."config_info" -VALUES (64, 'seataServer.properties', 'SEATA_GROUP', '#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html -#Transport configuration, for client and server -transport.type=TCP -transport.server=NIO -transport.heartbeat=true -transport.enableTmClientBatchSendRequest=false -transport.enableRmClientBatchSendRequest=true -transport.enableTcServerBatchSendResponse=false -transport.rpcRmRequestTimeout=30000 -transport.rpcTmRequestTimeout=30000 -transport.rpcTcRequestTimeout=30000 -transport.threadFactory.bossThreadPrefix=NettyBoss -transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker -transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler -transport.threadFactory.shareBossWorker=false -transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector -transport.threadFactory.clientSelectorThreadSize=1 -transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread -transport.threadFactory.bossThreadSize=1 -transport.threadFactory.workerThreadSize=default -transport.shutdown.wait=3 -transport.serialization=seata -transport.compressor=none - -#Transaction routing rules configuration, only for the client -service.vgroupMapping.default_tx_group=default -#If you use a registry, you can ignore it -service.default.grouplist=seata.laokou.org:8091 -service.enableDegrade=false -service.disableGlobalTransaction=false - -client.metadataMaxAgeMs=30000 -#Transaction rule configuration, only for the client -client.rm.asyncCommitBufferLimit=10000 -client.rm.lock.retryInterval=10 -client.rm.lock.retryTimes=30 -client.rm.lock.retryPolicyBranchRollbackOnConflict=true -client.rm.reportRetryCount=5 -client.rm.tableMetaCheckEnable=true -client.rm.tableMetaCheckerInterval=60000 -client.rm.sqlParserType=hikari -client.rm.reportSuccessEnable=false -client.rm.sagaBranchRegisterEnable=false -client.rm.sagaJsonParser=jackson -client.rm.tccActionInterceptorOrder=-2147482648 -client.tm.commitRetryCount=5 -client.tm.rollbackRetryCount=5 -client.tm.defaultGlobalTransactionTimeout=60000 -client.tm.degradeCheck=false -client.tm.degradeCheckAllowTimes=10 -client.tm.degradeCheckPeriod=2000 -client.tm.interceptorOrder=-2147482648 -client.undo.dataValidation=true -client.undo.logSerialization=jackson -client.undo.onlyCareUpdateColumns=true -server.undo.logSaveDays=7 -server.undo.logDeletePeriod=86400000 -client.undo.logTable=undo_log -client.undo.compress.enable=true -client.undo.compress.type=zip -client.undo.compress.threshold=64k -#For TCC transaction mode -tcc.fence.logTableName=tcc_fence_log -tcc.fence.cleanPeriod=1h -# You can choose from the following options: fastjson, jackson, gson -tcc.contextJsonParserType=fastjson - -#Log rule configuration, for client and server -log.exceptionRate=100 - -#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional. -store.mode=redis -store.lock.mode=redis -store.session.mode=redis -#Used for password encryption -store.publicKey= - -#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block. -store.file.dir=file_store/data -store.file.maxBranchSessionSize=16384 -store.file.maxGlobalSessionSize=512 -store.file.fileWriteBufferCacheSize=16384 -store.file.flushDiskMode=async -store.file.sessionReloadReadSize=100 - -#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block. -store.db.datasource=hikari -store.db.dbType=mysql -store.db.driverClassName=com.mysql.cj.jdbc.Driver -store.db.url=jdbc:mysql://mysql.laokou.org:3306/kcloud_platform_alibaba_seata?useUnicode=true&rewriteBatchedStatements=true -store.db.user=root -store.db.password=laokou123 -store.db.minConn=5 -store.db.maxConn=30 -store.db.globalTable=global_table -store.db.branchTable=branch_table -store.db.distributedLockTable=distributed_lock -store.db.queryLimit=100 -store.db.lockTable=lock_table -store.db.maxWait=5000 - -#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block. -store.redis.mode=single -store.redis.type=pipeline -store.redis.single.host=redis.laokou.org -store.redis.single.port=6379 -store.redis.sentinel.masterName= -store.redis.sentinel.sentinelHosts= -store.redis.sentinel.sentinelPassword= -store.redis.maxConn=10 -store.redis.minConn=1 -store.redis.maxTotal=100 -store.redis.database=0 -store.redis.password=laokou123 -store.redis.queryLimit=100 - -#Transaction rule configuration, only for the server -server.recovery.committingRetryPeriod=1000 -server.recovery.asynCommittingRetryPeriod=1000 -server.recovery.rollbackingRetryPeriod=1000 -server.recovery.timeoutRetryPeriod=1000 -server.maxCommitRetryTimeout=-1 -server.maxRollbackRetryTimeout=-1 -server.rollbackRetryTimeoutUnlockEnable=false -server.distributedLockExpireTime=10000 -server.session.branchAsyncQueueSize=5000 -server.session.enableBranchAsyncRemove=false -server.enableParallelRequestHandle=true -server.enableParallelHandleBranch=false - -server.raft.cluster=seata.laokou.org:7091,seata.laokou.org:7092,seata.laokou.org:7093 -server.raft.snapshotInterval=600 -server.raft.applyBatch=32 -server.raft.maxAppendBufferSize=262144 -server.raft.maxReplicatorInflightMsgs=256 -server.raft.disruptorBufferSize=16384 -server.raft.electionTimeoutMs=2000 -server.raft.reporterEnabled=false -server.raft.reporterInitialDelay=60 -server.raft.serialization=jackson -server.raft.compressor=none -server.raft.sync=true - -#Metrics configuration, only for the server -metrics.enabled=false -metrics.registryType=compact -metrics.exporterList=prometheus -metrics.exporterPrometheusPort=9898', '26217408b5ee26c2fec37325ea785e2f', '2024-05-25 18:13:33.425', - '2024-05-25 18:13:33.425', NULL, '127.0.0.1', 'laokou-seata', '0dac1a68-2f01-40df-bd26-bf0cb199057a', - 'seata配置', NULL, NULL, 'properties', NULL, ''); + INSERT INTO "public"."config_info" VALUES (66, 'admin-degrade.json', 'LAOKOU_GROUP', '[ { @@ -2204,49 +1669,7 @@ VALUES (66, 'admin-degrade.json', 'LAOKOU_GROUP', '[ ]', '2c0d4de0716f94bd6878b0a68d3faa0f', '2024-05-25 18:13:33.436', '2024-05-25 18:13:33.436', NULL, '127.0.0.1', 'laokou-admin', '0dac1a68-2f01-40df-bd26-bf0cb199057a', 'admin sentinel degrade rule', NULL, NULL, 'json', NULL, ''); -INSERT INTO "public"."config_info" -VALUES (67, 'application-common-seata.yaml', 'LAOKOU_GROUP', '# seata -seata: - saga: - enabled: true - state-machine: - enable-async: true - table-prefix: seata_ - async-thread-pool: - core-pool-size: 1 - max-pool-size: 20 - keep-alive-time: 60 - trans-operation-timeout: 1800000 - service-invoke-timeout: 300000 - auto-register-resources: true - resources: - - classpath*:seata/saga/statelang/**/*.json - default-tenant-id: 0 - charset: UTF-8 - client: - tm: - default-global-transaction-timeout: 30000 - config: - type: nacos - nacos: - server-addr: nacos.laokou.org - namespace: 0dac1a68-2f01-40df-bd26-bf0cb199057a - username: nacos - password: nacos - group: SEATA_GROUP - data-id: seataServer.properties - registry: - type: nacos - nacos: - namespace: 0dac1a68-2f01-40df-bd26-bf0cb199057a - group: SEATA_GROUP - username: nacos - password: nacos - server-addr: nacos.laokou.org - enabled: true - tx-service-group: default_tx_group - data-source-proxy-mode: AT', 'd121fc4a27f2da0223bc33374be43f73', '2024-05-25 18:13:33.441', '2024-05-25 18:49:36.942', - 'nacos', '127.0.0.1', '', '0dac1a68-2f01-40df-bd26-bf0cb199057a', 'seata公共配置', '', '', 'yaml', '', ''); + INSERT INTO "public"."config_info" VALUES (68, 'application-admin.yaml', 'LAOKOU_GROUP', '# jasypt jasypt: @@ -2795,8 +2218,7 @@ INSERT INTO "public"."config_tags_relation" VALUES (2118, 'report', '', 'application-report.yaml', 'LAOKOU_GROUP', 'a61abd4c-ef96-42a5-99a1-616adee531f3', 720); INSERT INTO "public"."config_tags_relation" VALUES (1570, 'admin', '', 'admin-degrade.json', 'LAOKOU_GROUP', 'a61abd4c-ef96-42a5-99a1-616adee531f3', 4); -INSERT INTO "public"."config_tags_relation" -VALUES (1254, 'seata', '', 'application-common-seata.yaml', 'LAOKOU_GROUP', 'a61abd4c-ef96-42a5-99a1-616adee531f3', 31); + INSERT INTO "public"."config_tags_relation" VALUES (26, 'gateway', '', 'router.json', 'LAOKOU_GROUP', 'a61abd4c-ef96-42a5-99a1-616adee531f3', 54); INSERT INTO "public"."config_tags_relation" diff --git a/doc/deploy/docker-compose.yml b/doc/deploy/docker-compose.yml index 5f63cec8cf..e25448441b 100644 --- a/doc/deploy/docker-compose.yml +++ b/doc/deploy/docker-compose.yml @@ -233,27 +233,6 @@ services: depends_on: - laokou-register network_mode: bridge - laokou-seata: - image: registry.cn-shenzhen.aliyuncs.com/koushenhai/laokou-seata:3.2.1 - container_name: laokou-seata - tty: true - env_file: - - env/common.env - - env/seata.env - ports: - - "7091:7091" - - "8091:8091" - volumes: - - ./seata/logs:/opt - extra_hosts: - - "postgresql.laokou.org:192.168.30.1" - - "nacos.laokou.org:192.168.30.1" - - "redis.laokou.org:192.168.30.1" - restart: always - privileged: true - depends_on: - - laokou-register - network_mode: bridge laokou-gateway: image: registry.cn-shenzhen.aliyuncs.com/koushenhai/laokou-gateway:3.2.1 container_name: laokou-gateway @@ -336,13 +315,11 @@ services: - "postgresql.laokou.org:192.168.30.1" - "rocketmq.laokou.org:192.168.30.1" - "elasticsearch.laokou.org:192.168.30.1" - - "seata.laokou.org:192.168.30.1" restart: always privileged: true network_mode: bridge depends_on: - laokou-register - - laokou-seata - elasticsearch laokou-logstash: image: registry.cn-shenzhen.aliyuncs.com/koushenhai/laokou-logstash-start:3.2.1 diff --git a/doc/deploy/env/seata.env b/doc/deploy/env/seata.env deleted file mode 100644 index 9535a8f7f0..0000000000 --- a/doc/deploy/env/seata.env +++ /dev/null @@ -1,7 +0,0 @@ -SEATA_GROUP=SEATA_GROUP -SEATA_GROUP=SEATA_GROUP -SEATA_USERNAME=seata -SEATA_PASSWORD=seata -SEATA_LOG_PATH=/opt -JASYPT_ENCRYPTOR_PASSWORD=5201314wumeihua -JVM_OPTS="-Xmx512m -Xms512m -Xmn256m -XX:+UseG1GC" diff --git a/laokou-cloud/laokou-gateway/pom.xml b/laokou-cloud/laokou-gateway/pom.xml index 043b6d6ab1..a8253d66fd 100644 --- a/laokou-cloud/laokou-gateway/pom.xml +++ b/laokou-cloud/laokou-gateway/pom.xml @@ -36,6 +36,16 @@ io.grpc grpc-netty + + + io.grpc + grpc-api + + + io.grpc + grpc-core + + org.laokou diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/.babelrc b/laokou-cloud/laokou-seata-saga-statemachine-designer/.babelrc deleted file mode 100644 index 56b133d788..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/.babelrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - [ - "@babel/preset-react", - { - "runtime": "automatic" - } - ] - ], - "plugins": [ - [ - "@babel/plugin-transform-react-jsx", - { - "importSource": "@bpmn-io/properties-panel/preact", - "runtime": "automatic" - } - ] - ] -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/.eslintignore b/laokou-cloud/laokou-seata-saga-statemachine-designer/.eslintignore deleted file mode 100644 index 3dda1c9d00..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -es -cjs -dist -scripts diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/.eslintrc.json b/laokou-cloud/laokou-seata-saga-statemachine-designer/.eslintrc.json deleted file mode 100644 index 8720470c67..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/.eslintrc.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "env": { - "browser": true - }, - "parser": "@babel/eslint-parser", - "extends": "airbnb", - "rules": { - "arrow-body-style": 0, - "class-methods-use-this": 0, - "func-names": 0, - "import/extensions": 0, - "import/no-extraneous-dependencies": 0, - "import/no-unresolved": 0, - "jsx-a11y/anchor-is-valid":0, - "jsx-a11y/no-static-element-interactions": 0, - "no-param-reassign": 0, - "no-plusplus": 0, - "object-curly-newline": 0, - "react/destructuring-assignment": 0, - "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], - "react/no-multi-comp": 0, - "react/prefer-stateless-function": 0, - "react/prop-types": 0, - "react/sort-comp": 0, - "react/no-deprecated": 0, - "react/react-in-jsx-scope": 0, - "react/jsx-no-bind": 0, - "no-underscore-dangle": 0 - } -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/.gitignore b/laokou-cloud/laokou-seata-saga-statemachine-designer/.gitignore deleted file mode 100644 index 60fc8df7a1..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/.idea/ -/.vscode/ - -/node_modules/ -/dist/ diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/LICENSE b/laokou-cloud/laokou-seata-saga-statemachine-designer/LICENSE deleted file mode 100644 index b916c3e8ef..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/README-zh.md b/laokou-cloud/laokou-seata-saga-statemachine-designer/README-zh.md deleted file mode 100644 index 27466c3e01..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/README-zh.md +++ /dev/null @@ -1,633 +0,0 @@ -# Seata Saga state machine designer - -由于旧版 Saga 状态机设计器的基座框架 ggeditor 不再维护,且 ggeditor 暴露出来的漏洞较多,影响了项目整体安全性。所以我们采取重构状态机设计器的做法,并使用新框架 diagram-js 为基座构建新的设计器。本文档涵盖 diagram-js 框架使用指南、设计器实现思路、代码结构等方面,旨在提供一个文档方便社区协作。 - - - -[TOC] - - - -## diagram-js - -[diagram-js](https://github.com/bpmn-io/diagram-js) 是 bpmn.io 组织开发维护的一款用于在网页上显示和修改流程图的框架。它使我们能够渲染视觉元素并在它们之上构建交互式体验。它为我们提供了一个非常简单的模块系统,用于构建服务发现的功能和依赖注入。该系统还提供了许多实现流程图要点的核心服务。此外 diagram-js 还定义了图形元素及其关系的数据模型。 - -基于 diagram-js 构建的知名项目有 bpmn-js, dmn-js 等等。在实现 Saga 状态机设计器时参考了很多 [bpmn-js](https://github.com/bpmn-io/bpmn-js) 的实现,一方面 Seata Saga 和 BPMN 规范有很多相似之处,且借鉴了很多 BPMN 的元素;另一方面,bpmn-js 就是基于 diagram-js 实现的,为 Saga 设计器的实现提供了一个模板。 - -下面我将总结一些 diagram-js 的整体架构,带大家快速入门。 - -### Diagram - -`Diagram` 是 diagram-js 提供的核心类入口,如果想要在页面的 canvas 块中挂载一个图,可以使用以下代码 - -```js -const editor = new Diagram({ - container: document.querySelector('#canvas'), - keyboard: { bindTo: document }, -}); -``` - -### 挂钩到生命周期 - -diagram-js 内部使用事件驱动架构,允许我们通过事件总线连接到 `Diagram` 的生命周期以及交互。以下代码展示了如何捕获一般变化的元素和建模操作, - -```js -diagram.get('eventBus').on('commandStack.changed', () => { - // user modeled something or - // performed an undo/redo operation -}); - -modeler.on('element.changed', (event) => { - const element = event.element; - - // the element was changed by the user -}); -``` - -### 模块系统 - -要向 `Diagram` 注册扩展可以将它们作为数组传递给构造函数的 `modules` 选项中,这将允许传递修改或替换现有功能的自定义模块。 - -```js -const diagram = new Diagram({ - container: document.querySelector('#canvas'), - keyboard: { bindTo: document }, - modules: [ - PropertiesPanel, - PropertiesProvider, - ], -}); -``` - -而模块在 diagram-js 中是是定义一个或多个命名服务的单元。这些服务提供附加功能,通过挂钩到 diagram 的生命周期来实现。在底层,diagram-js使用依赖注入 (DI) 来连接和发现图表组件。这个机制是建立在 [didi ](https://github.com/nikku/didi) 之上的。下面显示了一个 [挂钩到生命周期](#挂钩到生命周期) 而实现的服务。 - -```js -const MyLoggingPlugin = (eventBus) => { - eventBus.on('element.changed', (event) => { - console.log('element ', event.element, ' changed'); - }); -} - -// ensure the dependency names are still available after minification -MyLoggingPlugin.$inject = [ 'eventBus' ]; -``` - -我们必须使用模块定义以唯一的名称发布服务: - -```js -import CoreModule from 'diagram-js/lib/core'; - -// export as module -export default { - __depends__: [ CoreModule ], // {2} - __init__: [ 'myLoggingPlugin' ], // {3} - myLoggingPlugin: [ 'type', MyLoggingPlugin ] // {1} -}; -``` - -该定义告诉 DI 基础设施该服务叫做`myLoggingPlugin` `{1}`,它依赖于 diagram-js 核心模块 `{2}`,并且该服务应在创建图表时初始化 `{3}`。有关更多详细信息,请查看 [didi 文档](https://github.com/nikku/didi/blob/master/README.md)。 - -现在可以基于创建出的模块传递到 `Diagram` 当中, - -```js -import MyLoggingModule from 'path-to-my-logging-module'; - -const diagram = new Diagram({ - modules: [ - MyLoggingModule - ] -}); -``` - -### 核心服务 - -[diagram-js 核心](https://github.com/bpmn-io/diagram-js/tree/master/lib/core)是围绕许多基础服务构建的: - -- [`Canvas`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/Canvas.js)- 提供用于添加和删除图形元素的API;处理元素生命周期并提供 API 来缩放和滚动。 -- [`EventBus`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/EventBus.js)- 全局沟通渠道,采用 *fire and forget* 政策。感兴趣的各方可以订阅各种事件,并在事件发出后对其采取行动。事件总线帮助我们解耦关注点并模块化功能,以便新功能可以轻松地与现有行为挂钩。 -- [`ElementFactory`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/ElementFactory.js)- 根据 diagram-js 的内部数据模型创建形状和连接的工厂。 -- [`ElementRegistry`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/ElementRegistry.js)- 管理添加到图中的所有元素,并提供 API 来通过 id 检索元素及其图形表示。 - -### 数据模型 - -在底层,diagram-js 实现了一个由 `Shape` 和 `Connection` 组成的简单数据模型。`Shape` 具有父级、子级列表以及传入和传出 `Connections` 的列表。一个 `Connection` 有一个父级以及一个源和目标,分别指向一个 `Shape`。 - -[`ElementRegistry`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/ElementRegistry.js) 负责根据 [模型](https://github.com/bpmn-io/diagram-js/blob/master/lib/model/index.js) 创建 `Shape` 和 `Connection`。在建模过程中,[Modeling](https://github.com/bpmn-io/diagram-js/blob/master/lib/features/modeling/Modeling.js) 服务会根据用户操作更新元素关系。 - -### 辅助服务(工具箱) - -除了数据模型及其核心服务之外,diagram-js 还提供了丰富的附加帮助工具箱。 - -- [`CommandStack`](https://github.com/bpmn-io/diagram-js/blob/master/lib/command/CommandStack.js)- 负责建模期间的重做和撤消。 -- [`ContextPad`](https://github.com/bpmn-io/diagram-js/blob/master/lib/features/context-pad/ContextPad.js)- 提供围绕元素的上下文操作。 -- [`Overlays`](https://github.com/bpmn-io/diagram-js/blob/master/lib/features/overlays/Overlays.js)- 提供用于将附加信息附加到图表元素的 API。 -- [`Modeling`](https://github.com/bpmn-io/diagram-js/blob/master/lib/features/modeling/Modeling.js)- 提供用于更新画布上的元素(移动、删除)的 API -- [`Palette`](https://github.com/bpmn-io/diagram-js/blob/master/lib/features/palette/Palette.js) -- ... - - - -## Saga 设计器深入解析 - - - -### 代码入口 - -#### Editor.js - -在本文件中定义了名为 `Editor` 的类,继承自 diagram-js 的 `Diagram` 类。 - -首先定义 `Editor` 需要的模块,这里的模块指的是前文介绍的[模块系统](#模块系统)中的概念。`Editor` 的模块可以分为两类:定制化模块,和 diagram-js 内置模块。 - -```js -Editor.prototype.modules = [ - // Customized modules - Layout, - Modeling, - Providers, - Render, - - // Built-in modules - AlignElementsModule, - AutoScrollModule, - BendpointsModule, - // ... -]; -``` - -值得注意的是 `Editor` 的两个方法, - -**`Editor#import`** - -用于从 JSON 定义的状态机导入进 `Editor` 中,内部逻辑是先清楚图中当前所有元素,然后调用 `sagaImporter` 模块的 `import` 方法,其中 `sagaImporter` 是定制化模块 `Modeling` 中的子模块,后续会进行介绍。 - -```js -Editor.prototype.import = function (definitions) { - this.clear(); - this.get('sagaImporter') - .import(definitions); -}; -``` - -**`Editor#export`** - -用于将 `Editor` 当前图中元素导出为 JSON 文件,调用 `sagaExporter` 模块的 `export` 方法,其中 `sagaExporter` 是定制化模块 `Modeling` 中的子模块,后续会进行介绍。 - -```js -Editor.prototype.export = function () { - return this.get('sagaExporter') - .export(); -}; -``` - -除此之外,`Editor` 还提供了一系列的实用方法以供调用,比如 `clear` 清除图中所有元素, `detach` 从容器中卸载等等。 - - - -#### index.js - -新建 `Editor` 对象,挂载到 `canvas` block 中 - -```js -const editor = new Editor({ - container: document.querySelector('#canvas'), - keyboard: { bindTo: document }, - propertiesPanel: { parent: '#properties' }, - // Add properties panel as additional modules - additionalModules: [ - PropertiesPanel, - PropertiesProvider, - ], -}); -``` - -值得注意的是,这里将 `PropertiesPanel`, `PropertiesProvider` 作为附加模块添加到 `Editor` 中而不是在 `Editor.prototype.modules` 中直接加入,是基于属性面板是一个可插拔模块的考虑。如果后续打算把设计器作为一个 npm 包进行发布,用户使用 `Editor` 时不需要捆绑属性面板使用。 - - - -在创建 `Editor` 对象之后,通过以下这行代码, - -```js -control(editor); -``` - -是用于在画布上创建控制按钮,分别用于控制 `Editor` 进行导入、导出文件 - -![control](assets/control.png) - -### providers - -providers 文件夹用于为 diagram-js 工具箱(见[辅助服务(工具箱)](#辅助服务(工具箱))章节)提供对应条目的。 - -#### providers/ContextPadProvider.js - -![ContextPad](assets/context-pad.png) - -ContextPad 是 diagram-js 内置的辅助模块,可以定义 Provider 为其填充条目。实现的核心在于 `ContextPadProvider.prototype.getContextPadEntries` 方法,当前设计器针对于 Shape 会提供连接和删除两个条目,对于边则仅提供删除条目(边上再连边显然不合理)。 - - - -#### providers/PaletteProvider.js - -palette - -Palette 是 diagram-js 内置的左侧画板,实现的核心在于 `PaletteProvider.prototype.getPaletteEntries` 方法,这里目前只实现了(ServiceTask, Fail, Success 三种类型状态,还有一个开始节点,状态仍需扩充)除了各种状态之外,在最上方还提供了拉索工具,用于批量框选状态从而进行删除或移动等操作。 - - - -### spec - -spec 文件夹中内聚了所有状态的定义,主要作用是规定了每个状态新建时的默认属性,且通过 `importJson` 和 `exportJson` 定义了一些导入导出的转换逻辑。这里的代码文件不再展开介绍,可以通过比对代码和下方的类图进行理解。 - -```mermaid ---- -title: Spec Class Diagram ---- -classDiagram - BaseSpec <|-- StateMachine - - BaseSpec <|-- NodeStyle - BaseSpec <|-- Node - - Node <|-- StartState - Node <|-- State - - State <|-- TaskState - TaskState <|-- ServiceTask - TaskState <|-- ScriptTask - - BaseSpec <|-- EdgeStyle - BaseSpec <|-- Edge - - note for Transition "所有边的基类" - Edge <|-- Transition - Transition <|-- ChoiceEntry - Transition <|-- CatchEntry - - Node *-- NodeStyle - Edge *-- EdgeStyle - - BaseSpec : String Type - - class StateMachine { - String Name - String Comment - String Version - } - - NodeStyle : Object bounds - - class Node{ - NodeStyle style - } - - class EdgeStyle { - Object source - Object target - List waypoints - } - - class Edge{ - EdgeStyle style - } - - class State { - String Name - String Comment - } - - class TaskState { - List[Object] Input - Object Output - Object Status - List Retry - } - - class ServiceTask { - String ServiceName - String ServiceMethod - } -``` - -根据上图,可以了解 Spec 相关类图,和 Saga Java 代码中定义有类似之处。与 Java 代码不同的是,由于设计器需要将状态机以图的形式呈现给用户,所以状态、连接都需要通过 `style` 属性进行记录。 - - - -### modeling - -Modeling 模块是 Saga 状态机设计器的逻辑核心,这个模块逻辑内聚了 Saga 规范。每个文件都很重要,下文将针对每个代码文件分别展开进行描述。 - - - -#### modeling/Modeling.js - -`Modeling` 继承 diagram-js 的 `BaseModeling`,本文件主要定义了 - -1. 创建连接时基于 `rules` 模块判断是否可以连接 - - ```js - if (!attrs) { - attrs = rules.canConnect(source, target); - } - - return this.createConnection(source, target, attrs, rootElement, hints); - ``` - -2. 定义实用方法 `Modeling#updateProperties`,用于更新元素属性,实现了属性更新和撤回的逻辑,分别位于 `UpdatePropertiesHandler#execute` 和 `UpdatePropertiesHandler#revert` 中。 - - - -#### modeling/SagaFactory.js - -`SagaFacotry` 作为 Saga 规范的工厂类,其主要的方法是 - -```js -SagaFactory.prototype.create = function (type) { - const Spec = this.typeToSpec.get(type); - return new Spec(); -}; -``` - -传入字符串类型的元素类型,`SagaFactory` 获取类型对应的 `Spec` 并创建新对象进行返回。关于 `Spec` 请参考前文 [spec](#spec) 章节。 - - - -#### modeling/ElementFacotry.js - -`ElementFactory` 本身是 diagram-js 提供的核心模块之一,这里我们使用继承的方式对其进行扩展。主要重载了 `ElementFactory#create` 方法,使用 `SagaFactory` 创建业务对象保存在元素的 `businessObject` 字段中 - -```js -ElementFactory.prototype.create = function (elementType, attrs) { - const { sagaFactory } = this; - - attrs = attrs || {}; - - let { businessObject } = attrs; - - if (!businessObject) { - if (!attrs.type) { - throw new Error('no shape type specified'); - } - - businessObject = sagaFactory.create(attrs.type); - } - - const size = sagaFactory.getDefaultSize(businessObject); - - attrs = assign({ businessObject }, size, attrs); - - return this.baseCreate(elementType, attrs); -}; -``` - - - -#### modeling/SagaRules.js - -`SagaRules` 继承了 diagram-js 的 `RuleProvider` 类,旨在提供绘图的验证规则。比如说在 Saga 状态机中,一条边不能连向自身状态(否则会造成产生死循环),这里我们通过 `SagaRules#canConnect` 方法进行实现。 - - - -#### modeling/SagaImporter.js - -`SagaImporter` 的功能单一,聚焦于将 JSON 状态机定义导入到设计器中,核心的代码实现在于 `SagaImporter#import` 方法中,代码逻辑也不复杂, - -```js -try { - const root = this.sagaFactory.create('StateMachine'); - root.importJson(definitions); - this.root(root); - - // Add start state - const start = this.sagaFactory.create('StartState'); - start.importJson(definitions); - this.add(start); - - const edges = []; - forEach(definitions.States, (semantic) => { - const state = this.sagaFactory.create(semantic.Type); - state.importJson(semantic); - this.add(state); - if (semantic.edge) { - edges.push(...Object.values(semantic.edge)); - } - }); - - // Add start edge - if (definitions.edge) { - const startEdge = this.sagaFactory.create('Transition'); - startEdge.importJson(definitions.edge); - this.add(startEdge, { source: start }); - } - - forEach(edges, (semantic) => { - const transition = this.sagaFactory.create(semantic.Type); - transition.importJson(semantic); - this.add(transition); - }); -``` - -首先根据状态机 StateMachine 自身定义创建根元素,然后再基于 StateMachine 的 style 属性创建出一个起始元素“伪状态”,随后遍历 `States` 字段,创建出每个状态并收集边集 `edges` 。对于边的创建,需要从“伪状态”加一条边到 `StartState`,此后再根据 `edges` 依次创建即可。 - - - -#### modeling/SagaExporter.js - -`SagaExporter` 和 `SagaImporter` 的功能相反,是根据绘图导出为 JSON 文件定义。这里需要注意的是 `SagaExporter` 和 `SagaImporter` 的实现上可以相互对照,基本上互为彼此的逆操作。 - - - -### render - -render 模块,顾名思义就是渲染的核心模块,负责将状态机以 SVG 矢量图的形式呈现给用户。 - - - -#### render/Renderer.js - -`Renderer` 是所有元素的绘图入口,对于不同的元素类型我们使用 `handlers` 变量中定义的不同处理器进行绘图, - -```js -Transition(p, element) { - const fill = getFillColor(element, defaultFillColor); - const stroke = getStrokeColor(element, defaultStrokeColor); - const attrs = { - stroke, - strokeWidth: 1, - strokeLinecap: 'round', - strokeLinejoin: 'round', - markerEnd: marker('connection-end', fill, stroke), - }; - - return drawLine(p, element.waypoints, attrs); -}, -``` - - - -#### render/TextRenderer.js - -为渲染文字单独抽象出来的实用类,后续应该不需要改动。 - - - -#### render/PathMap.js - -核心定义了一个 `pathMap` 用于记录不同的绘图元素的 SVG 路径,比如 - -```js -this.pathMap = { - TASK_TYPE_SERVICE: { - d: 'm {mx},{my} v -1.71335 c 0.352326,-0.0705 0.703932,-0.17838 1.047628,-0.32133 ' - + '0.344416,-0.14465 0.665822,-0.32133 0.966377,-0.52145 l 1.19431,1.18005 1.567487,-1.57688 ' - + '-1.195028,-1.18014 c 0.403376,-0.61394 0.683079,-1.29908 0.825447,-2.01824 l 1.622133,-0.01 ' - + 'v -2.2196 l -1.636514,0.01 c -0.07333,-0.35153 -0.178319,-0.70024 -0.323564,-1.04372 ' - + '-0.145244,-0.34406 -0.321407,-0.6644 -0.522735,-0.96217 l 1.131035,-1.13631 -1.583305,-1.56293 ' - + '-1.129598,1.13589 c -0.614052,-0.40108 -1.302883,-0.68093 -2.022633,-0.82247 l 0.0093,-1.61852 ' - + 'h -2.241173 l 0.0042,1.63124 c -0.353763,0.0736 -0.705369,0.17977 -1.049785,0.32371 -0.344415,0.14437 ' - + '-0.665102,0.32092 -0.9635006,0.52046 l -1.1698628,-1.15823 -1.5667691,1.5792 1.1684265,1.15669 ' - + 'c -0.4026573,0.61283 -0.68308,1.29797 -0.8247287,2.01713 l -1.6588041,0.003 v 2.22174 ' - + 'l 1.6724648,-0.006 c 0.073327,0.35077 0.1797598,0.70243 0.3242851,1.04472 0.1452428,0.34448 ' - + '0.3214064,0.6644 0.5227339,0.96066 l -1.1993431,1.19723 1.5840256,1.56011 1.1964668,-1.19348 ' - + 'c 0.6140517,0.40346 1.3028827,0.68232 2.0233517,0.82331 l 7.19e-4,1.69892 h 2.226848 z ' - + 'm 0.221462,-3.9957 c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' - + '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' - + '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z', - }, - TASK_TYPE_SERVICE_FILL: { - d: 'm {mx},{my} c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' - + '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' - + '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z', - }, - MARKER_COMPENSATION: { - d: 'm {mx},{my} 7,-5 0,10 z m 7.1,-0.3 6.9,-4.7 0,10 -6.9,-4.7 z', - height: 10, - width: 21, - heightElements: [], - widthElements: [], - }, - MARKER_LOOP: { - d: 'm {mx},{my} c 3.526979,0 6.386161,-2.829858 6.386161,-6.320661 0,-3.490806 -2.859182,-6.320661 ' - + '-6.386161,-6.320661 -3.526978,0 -6.38616,2.829855 -6.38616,6.320661 0,1.745402 ' - + '0.714797,3.325567 1.870463,4.469381 0.577834,0.571908 1.265885,1.034728 2.029916,1.35457 ' - + 'l -0.718163,-3.909793 m 0.718163,3.909793 -3.885211,0.802902', - height: 13.9, - width: 13.7, - heightElements: [], - widthElements: [], - }, -}; -``` - -对于 Saga 状态机设计器而言,我们几乎所有的状态和元素绘图都可以参考 BPMN 规范的设计元素,所以可以直接参考使用 bpmn-js 的 [PathMap.js](https://github.com/bpmn-io/bpmn-js/blob/develop/lib/draw/PathMap.js) 文件即可。 - - - -### layout - -Layout 模块专注于布局变化。 - - - -#### layout/Layouter.js - -`Layouter` 继承自 diagram-js 的 `BaseLayouter` ,并在此基础上通过重载 `layoutConnection` 方法实现了连接线根据箭头朝向加入转折点的行为。 - -![waypoint](assets/waypoint.png) - - - -#### layout/behaviour/*.js - -在 layout/behaviour 文件夹中定义了一系列的行为用于在布局变动(比如添加新元素、连接,或者对现有图重布局等等)时对布局进行自动调整、逻辑适配。 - -##### layout/behaviour/LayoutConnectionBehaviour.js - -`LayoutConnectionBehaviour` 用于在布局变动时为边的连接点重新定位,如果不加入这个子模块,连接是这样的: - -![no-layout-connection](assets/no-layout-connection.png) - -加入这个子模块之后,无论在创建、移动边的时候指向哪里,最终的边都会指向元素中部位置,使得布局更清晰: - -![layout-connection](assets/layout-connection.png) - -这部分实现逻辑比较复杂和业务关系不大,主要实现在了 `LayoutConnectionBehaviour` 构造方法中,且附加上了代码注释。 - - - -##### layout/behaviour/ReplaceConnectionBehavior.js - -`ReplaceConnectionBehaviour` 用于配合 [rules](#modeling/SagaRules.js) 模块实现当连接更改连接点(即 `source` 或者 `target` )时验证是否可以进行连接,如可以再进行连接。 - - - -##### layout/behaviour/LayoutUpdateBehavior.js - -`LayoutUpdateBehavior` 用于在布局发生变化时为业务对象 `businessObject` 进行逻辑适配。目前主要是用于在布局变动时更新 `businessObject.style` 属性。 - - - -### properties-panel - -properties-panel 组件的开发基于 @bpmn-io/properties-panel 包,和 diagram-js 一样也是由 bpmn-io 组织开发,是一套属性面板基础组件。 - -属性面板目前类似于旧版设计器的实现,需要用户填写 JSON 来更新状态。 - -properties-panel - -在 properties-panel 根目录下的几个代码文件主要用于定义属性面板的样式,后续不太需要维护,这里简单介绍一下。 - -- `PropertiesPanelRenderer` 为属性面板的根元素,用于在页面上渲染出一个属性面板来 - -- `PropertiesPanel` 基于 diagram-js `PropertiesPanel` 的组件重新定制的组件,功能包含了向事件总线上注册一系列处理器,比如 selection 变化时更改属性面板的目标元素等等。 - -- `PropertiesPanelContext` 是一个 React Context,用于提供了一个在组件树间进行数据传递的方法。 - -- `PanelHeaderProvider` 用于定义属性面板头部显示内容 - - header - -- `PanelPlaceHolderProvider` 用于定义无元素选择时显示的内容 - - placeholder - -#### properties-panel/provider - -properties-panel 模块定义了属性面板,properties-panel/provider 模块则定义了为状态提供怎样的属性编辑。 - -provider - -##### properties-panel/provider/PropertiesProvider.js - -`PropertiesProvider` 该文件定义了针对不同的元素(状态或连接)应该展示怎样的属性编辑。 - -##### properties-panel/provider/properties - -目前支持的属性编辑都可以在 properties-panel/provider/properties 文件夹下找到,General 组提供了 `Name`, `Comment`, `Version` 的支持,JSON Props 组提供了 JSON 属性的编辑和 `style` 样式的展示。 - -比如说想要调整 `Name` 属性的编辑逻辑,则应该到 properties-panel/provider/properties/NameProps.js 文件中进行更改。 - - - -## Build - -项目基于 webpack 进行构建,构建文件 webpack.config.js 位于根目录下。使用 package.json 中定义的脚本可以完成构建、运行等操作。 - -``` -npm install -``` - -Bundle the editor contained in `src` and output it to `dist`: - -``` -npm run build -``` - -Start the development setup, opening the app and rebuild on changes: - -``` -npm run start -``` - - - diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/README.md b/laokou-cloud/laokou-seata-saga-statemachine-designer/README.md deleted file mode 100644 index d79cc0101a..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/README.md +++ /dev/null @@ -1,497 +0,0 @@ -# Seata Saga State Machine Designer - -Due to the discontinuation of maintenance for the old version of the Saga State Machine Designer's underlying framework, ggeditor, and the numerous vulnerabilities exposed by ggeditor, which affected the overall security of the project, we have chosen to refactor the State Machine Designer. We are using a new framework, diagram-js, as the foundation for building the new designer. This document covers aspects such as the usage guide for the diagram-js framework, the implementation approach of the designer, code structure, and more, aiming to provide a document that facilitates community collaboration. - -[TOC] - -## diagram-js - -[diagram-js](https://github.com/bpmn-io/diagram-js) is a framework developed and maintained by the bpmn.io organization for displaying and modifying process diagrams on web pages. It allows us to render visual elements and build interactive experiences on top of them. It provides a simple module system for building functionality and dependency injection for service discovery. The system also offers many core services that implement key points of a process diagram. Additionally, diagram-js defines the data model for graphical elements and their relationships. - -Well-known projects built on diagram-js include bpmn-js, dmn-js, and more. When implementing the Saga State Machine Designer, we referred to many implementations of [bpmn-js](https://github.com/bpmn-io/bpmn-js). On one hand, Seata Saga and BPMN specifications share many similarities, and we borrowed elements from BPMN. On the other hand, bpmn-js is implemented based on diagram-js, providing a template for implementing the Saga Designer. - -Below, I will summarize the overall architecture of diagram-js to help you quickly get started. - -### Diagram - -`Diagram` is the core class provided by diagram-js. If you want to mount a diagram in a canvas block on a page, you can use the following code: - -```js -const editor = new Diagram({ - container: document.querySelector('#canvas'), - keyboard: { bindTo: document }, -}); -``` - -### Hook into Lifecycle - -Diagram-js internally uses an event-driven architecture, allowing us to connect to the lifecycle and interactions of the `Diagram` through the event bus. The following code shows how to capture general changes to elements and modeling operations: - -```js -diagram.get('eventBus').on('commandStack.changed', () => { - // User modeled something or - // performed an undo/redo operation -}); - -modeler.on('element.changed', (event) => { - const element = event.element; - - // The element was changed by the user -}); -``` - -### Module System - -To register extensions with `Diagram`, you can pass them as an array to the `modules` option of the constructor. This allows custom modules to be passed that modify or replace existing functionality. - -```js -const diagram = new Diagram({ - container: document.querySelector('#canvas'), - keyboard: { bindTo: document }, - modules: [ - PropertiesPanel, - PropertiesProvider, - ], -}); -``` - -Modules in diagram-js define units that provide one or more named services. These services offer additional functionality by hooking into the lifecycle of the diagram. Under the hood, diagram-js uses Dependency Injection (DI) for connecting and discovering chart components, built on top of [didi](https://github.com/nikku/didi). The following example demonstrates a service implemented by [hooking into the lifecycle](#hook-into-lifecycle). - -```js -const MyLoggingPlugin = (eventBus) => { - eventBus.on('element.changed', (event) => { - console.log('element ', event.element, ' changed'); - }); -} - -// Ensure the dependency names are still available after minification -MyLoggingPlugin.$inject = [ 'eventBus' ]; -``` - -We must use a module definition to publish services with unique names: - -```js -import CoreModule from 'diagram-js/lib/core'; - -// Export as a module -export default { - __depends__: [ CoreModule ], // {2} - __init__: [ 'myLoggingPlugin' ], // {3} - myLoggingPlugin: [ 'type', MyLoggingPlugin ] // {1} -}; -``` - -This definition tells the DI infrastructure that the service is called `myLoggingPlugin` `{1}`, it depends on the diagram-js core module `{2}`, and the service should be initialized when the chart is created `{3}`. For more detailed information, refer to the [didi documentation](https://github.com/nikku/didi/blob/master/README.md). - -Now you can pass the created module to `Diagram`: - -```js -import MyLoggingModule from 'path-to-my-logging-module'; - -const diagram = new Diagram({ - modules: [ - MyLoggingModule - ] -}); -``` - -### Core Services - -[diagram-js core](https://github.com/bpmn-io/diagram-js/tree/master/lib/core) is built around many fundamental services: - -- [`Canvas`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/Canvas.js): Provides an API for adding and removing graphical elements; handles the lifecycle of elements and provides an API for zooming and scrolling. -- [`EventBus`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/EventBus.js): Global communication channel with a *fire and forget* policy. Interested parties can subscribe to various events and take action after the event is fired. The event bus helps decouple concerns and modularize functionality for easy integration of new features with existing behavior. -- [`ElementFactory`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/ElementFactory.js): Factory for creating shapes and connections based on the internal data model of diagram-js. -- [`ElementRegistry`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/ElementRegistry.js): Manages all elements added to the chart and provides an API to retrieve elements and their graphical representations by id. - -### Data Model - -At its core, diagram-js implements a simple data model consisting of `Shape` and `Connection`. `Shape` has a parent, a list of children, and lists of incoming and outgoing `Connections`. A `Connection` has a parent and source and target pointing to a `Shape`. - -[`ElementRegistry`](https://github.com/bpmn-io/diagram-js/blob/master/lib/core/ElementRegistry.js) is responsible for creating `Shape` and `Connection` based on the [model](https://github.com/bpmn-io/diagram-js/blob/master/lib/model/index.js). During modeling, the [Modeling](https://github.com/bpmn-io/diagram-js/blob/master/lib/features/modeling/Modeling.js) service updates element relationships based on user actions. - -### Auxiliary Services (Toolbox) - -In addition to the data model and its core services, diagram-js also provides a rich set of additional auxiliary toolbox services: - -- [`CommandStack`](https://github.com/bpmn-io/diagram-js/blob/master/lib/command/CommandStack.js): Responsible for redo and undo during modeling. -- [`ContextPad`](https://github.com/bpmn-io/diagram-js/blob/master/lib/features/context-pad/ContextPad.js): Provides context operations around elements. -- [`Overlays`](https://github.com/bpmn-io/diagram-js/blob/master/lib/features/overlays/Overlays.js): Provides an API for attaching additional information to chart elements. -- [`Modeling`](https://github.com/bpm - -n-io/diagram-js/blob/master/lib/features/modeling/Modeling.js): Provides an API for updating elements on the canvas (moving, deleting). -- [`Palette`](https://github.com/bpmn-io/diagram-js/blob/master/lib/features/palette/Palette.js) -- ... - -## In-Depth Analysis of Saga Designer - -### Code Entry - -#### Editor.js - -In this file, a class named `Editor` is defined, which inherits from the `Diagram` class of diagram-js. - -First, the required modules for `Editor` are defined. These modules can be categorized into two types: customized modules and built-in modules of diagram-js. - -```js -Editor.prototype.modules = [ - // Customized modules - Layout, - Modeling, - Providers, - Render, - - // Built-in modules - AlignElementsModule, - AutoScrollModule, - BendpointsModule, - // ... -]; -``` - -It's worth noting two methods of `Editor`: - -**`Editor#import`** - -Used to import a state machine defined in JSON into the `Editor`. The internal logic involves clearing all current elements in the diagram first and then calling the `import` method of the `sagaImporter` module. The `sagaImporter` is a submodule in the customized module `Modeling`, which will be introduced later. - -```js -Editor.prototype.import = function (definitions) { - this.clear(); - this.get('sagaImporter') - .import(definitions); -}; -``` - -**`Editor#export`** - -Used to export the current elements in the `Editor` to a JSON file. It calls the `export` method of the `sagaExporter` module. The `sagaExporter` is also a submodule in the customized module `Modeling`, which will be introduced later. - -```js -Editor.prototype.export = function () { - return this.get('sagaExporter') - .export(); -}; -``` - -In addition to these, `Editor` provides a series of utility methods for clearing all elements in the diagram (`clear`), detaching from the container (`detach`), and more. - -#### index.js - -Create a new `Editor` object and mount it to the `canvas` block. - -```js -const editor = new Editor({ - container: document.querySelector('#canvas'), - keyboard: { bindTo: document }, - propertiesPanel: { parent: '#properties' }, - // Add properties panel as additional modules - additionalModules: [ - PropertiesPanel, - PropertiesProvider, - ], -}); -``` - -It's worth noting that `PropertiesPanel` and `PropertiesProvider` are added as additional modules to `Editor` rather than directly in `Editor.prototype.modules`. This is done considering that the property panel is a pluggable module. If the designer is intended to be published as an npm package in the future, users can use `Editor` without bundling the property panel. - -After creating the `Editor` object, the following code: - -```js -control(editor); -``` - -is used to create control buttons on the canvas, allowing control over the import and export of files in the `Editor`. - -![control](assets/control.png) - -### Providers - -The providers folder is used to provide corresponding entries for the diagram-js toolbox (see the [Auxiliary Services (Toolbox)](#auxiliary-services-toolbox) section). - -#### providers/ContextPadProvider.js - -![ContextPad](assets/context-pad.png) - -ContextPad is a built-in auxiliary module in diagram-js, and providers can be defined to populate entries for it. The core implementation is in the `ContextPadProvider.prototype.getContextPadEntries` method. In the current designer, entries for connecting and deleting are provided for shapes, while only the delete entry is provided for edges (connecting edges to edges is not logical). - -#### providers/PaletteProvider.js - -palette - -Palette is a built-in left-side panel in diagram-js. The core implementation is in the `PaletteProvider.prototype.getPaletteEntries` method. Currently, it only implements entries for various states (ServiceTask, Fail, Success, three types of states, and a start node; more state types may be added later). In addition to various states, a lasso tool is provided at the top for batch selection of states for operations such as deletion or movement. - -### Spec - -The spec folder contains all the definitions for states, mainly specifying the default attributes when creating each state. It also defines some conversion logic for import and export using `importJson` and `exportJson`. The code files here are not expanded for discussion, and understanding can be gained by comparing the code with the class diagram below. - -```mermaid ---- -title: Spec Class Diagram ---- -classDiagram - BaseSpec <|-- StateMachine - - BaseSpec <|-- NodeStyle - BaseSpec <|-- Node - - Node <|-- StartState - Node <|-- State - - State <|-- TaskState - TaskState <|-- ServiceTask - TaskState <|-- ScriptTask - - BaseSpec <|-- EdgeStyle - BaseSpec <|-- Edge - - note for Transition "All edges' base class" - Edge <|-- Transition - Transition <|-- ChoiceEntry - Transition <|-- CatchEntry - - Node *-- NodeStyle - Edge *-- EdgeStyle - - BaseSpec : String Type - - class StateMachine { - String Name - String Comment - String Version - } - - NodeStyle : Object bounds - - class Node{ - NodeStyle style - } - - class EdgeStyle { - Object source - Object target - List waypoints - } - - class Edge{ - EdgeStyle style - } - - class State { - String Name - String Comment - } - - class TaskState { - List[Object] Input - Object Output - Object Status - List Retry - } - - class ServiceTask { - String ServiceName - String ServiceMethod - } -``` - -According to the diagram above, you can understand the class diagram related to the Spec classes, which has similarities with the Saga Java code definitions. The difference from Java code is that, since the designer needs to present the state machine as a graph to the user, states and connections need to be recorded through the `style` attribute. - -### Modeling Module Deep Dive - -The `modeling` module is the core logic of the Saga state machine designer, and it tightly integrates with the Saga specification. Let's explore each code file in this module. - -#### modeling/Modeling.js - -This file defines the `Modeling` class, which extends diagram-js's `BaseModeling`. The main functionalities include: - -1. Creating connections based on the `rules` module to determine if a connection is allowed. - - ```js - if (!attrs) { - attrs = rules.canConnect(source, target); - } - - return this.createConnection(source, target, attrs, rootElement, hints); - ``` - -2. Defining utility method `Modeling#updateProperties` for updating element properties. It implements the logic for property updates and undoing the updates, located in `UpdatePropertiesHandler#execute` and `UpdatePropertiesHandler#revert`, respectively. - -#### modeling/SagaFactory.js - -The `SagaFactory` acts as the factory class for Saga specifications. Its main method is: - -```js -SagaFactory.prototype.create = function (type) { - const Spec = this.typeToSpec.get(type); - return new Spec(); -}; -``` - -Given a string representing the element type, the `SagaFactory` retrieves the corresponding `Spec` and creates a new object. - -#### modeling/ElementFactory.js - -`ElementFactory` is an extension of the core module provided by diagram-js. It overrides the `ElementFactory#create` method, using `SagaFactory` to create a business object and save it in the element's `businessObject` field. - -```js -ElementFactory.prototype.create = function (elementType, attrs) { - const { sagaFactory } = this; - - attrs = attrs || {}; - - let { businessObject } = attrs; - - if (!businessObject) { - if (!attrs.type) { - throw new Error('no shape type specified'); - } - - businessObject = sagaFactory.create(attrs.type); - } - - const size = sagaFactory.getDefaultSize(businessObject); - - attrs = assign({ businessObject }, size, attrs); - - return this.baseCreate(elementType, attrs); -}; -``` - -#### modeling/SagaRules.js - -`SagaRules` extends diagram-js's `RuleProvider` class and aims to provide validation rules for drawing. For instance, in Saga state machines, a transition cannot connect to the same state (as it would create a deadlock). This is implemented in the `SagaRules#canConnect` method. - -#### modeling/SagaImporter.js - -The `SagaImporter` focuses on importing JSON state machine definitions into the designer. The core logic is in the `SagaImporter#import` method. The code logic involves creating the root element, creating a pseudo-state element, iterating over the states, and creating edges. - -#### modeling/SagaExporter.js - -`SagaExporter` and `SagaImporter` are counterparts, where `SagaExporter` exports the current state machine into a JSON file. It's essential to note that their implementations can be compared as inverse operations of each other. - -### render Module - -The `render` module is responsible for the core rendering of the state machine in SVG format. - -#### render/Renderer.js - -The `Renderer` serves as the entry point for drawing all elements. For different element types, it uses handlers defined in the `handlers` variable for rendering. - -```js -Transition(p, element) { - const fill = getFillColor(element, defaultFillColor); - const stroke = getStrokeColor(element, defaultStrokeColor); - const attrs = { - stroke, - strokeWidth: 1, - strokeLinecap: 'round', - strokeLinejoin: 'round', - markerEnd: marker('connection-end', fill, stroke), - }; - - return drawLine(p, element.waypoints, attrs); -}, -``` - -#### render/TextRenderer.js - -A utility class specifically abstracted for rendering text. It is not likely to require modifications in the future. - -#### render/PathMap.js - -This file defines a `pathMap` used to record SVG paths for different drawing elements. For the Saga state machine designer, almost all drawing elements can be referenced from the design elements in the BPMN specification. Therefore, you can directly use bpmn-js's [PathMap.js](https://github.com/bpmn-io/bpmn-js/blob/develop/lib/draw/PathMap.js) file. - -### layout Module - -The `layout` module focuses on layout changes. - -#### layout/Layouter.js - -`Layouter` extends diagram-js's `BaseLayouter` and, on top of that, implements the `layoutConnection` method to introduce bends in the connection lines based on the direction of the arrow. - -![waypoint](assets/waypoint.png) - -#### layout/behaviour/*.js - -In the `layout/behaviour` folder, a series of behaviors are defined to automatically adjust the layout and logic adaptation of the layout when layout changes occur (such as adding new elements, connections, or re-layouting the existing diagram). - -##### layout/behaviour/LayoutConnectionBehaviour.js - -`LayoutConnectionBehaviour` is used to reposition the connection points for edges when the layout changes. If this submodule is not added, connections look like this: - -![no-layout-connection](assets/no-layout-connection.png) - -After adding this submodule, regardless of where the edge points during creation or movement, the final edge will point to the middle of the element, making the layout clearer: - -![layout-connection](assets/layout-connection.png) - -The implementation logic for this part is relatively complex and not directly related to business relationships, mainly implemented in the constructor of `LayoutConnectionBehaviour`, accompanied by code comments. - -##### layout/behaviour/ReplaceConnectionBehavior.js - -`ReplaceConnectionBehaviour` works in conjunction with the [rules](#modeling/SagaRules.js) module to validate whether a connection can be made when changing connection points (`source` or `target`). - -##### layout/behaviour/LayoutUpdateBehavior.js - -`LayoutUpdateBehavior` is used to logically adapt the business object `businessObject` when the layout changes. Currently, it is mainly used to update the `businessObject.style` attribute when the layout changes. - -### properties-panel - -The development of the `properties-panel` component is based on the `@bpmn-io/properties-panel` package, similar to `diagram-js`, and is also developed by the bpmn-io organization. It is a set of basic components for property panels. - -The property panel currently resembles the implementation of the old version of the designer, requiring users to fill in JSON to update the state. - -![properties-panel](assets/properties-panel.png) - -The several code files in the root directory of `properties-panel` are mainly used to define the styles of the property panel. They are not likely to require much maintenance in the future. Here is a brief introduction: - -- `PropertiesPanelRenderer` is the root element of the property panel, used to render a property panel on the page. - -- `PropertiesPanel` is a component based on `PropertiesPanel` from diagram-js, and it is a customized component. Its functionality includes registering a series of handlers on the event bus, such as changing the target element of the property panel when the selection changes. - -- `PropertiesPanelContext` is a React Context used to provide a method for data transmission between components in the component tree. - -- `PanelHeaderProvider` is used to define the content displayed in the header of the property panel. - - ![header](assets/header.png) - -- `PanelPlaceHolderProvider` is used to define the content displayed when no element is selected. - - ![placeholder](assets/placeholder.png) - -#### properties-panel/provider - -The `properties-panel` module defines the property panel, and the `properties-panel/provider` module defines how properties are provided for states. - -![provider](assets/provider.png) - -##### properties-panel/provider/PropertiesProvider.js - -`PropertiesProvider` defines how different elements (states or connections) should display property editors. - -##### properties-panel/provider/properties - -Currently supported property editors can be found in the `properties-panel/provider/properties` folder. The General group provides support for `Name`, `Comment`, and `Version`. The JSON Props group provides editing for JSON properties and displays for the `style` attribute. - -For example, if you want to adjust the editing logic for the `Name` property, you should make changes in the `properties-panel/provider/properties/NameProps.js` file. - -## Build - -The project is built using webpack, and the webpack configuration file `webpack.config.js` is located in the root directory. The scripts defined in the `package.json` can be used to perform build, run, and other operations. - -```bash -npm install -``` - -Bundle the editor contained in `src` and output it to `dist`: - -```bash -npm run build -``` - -Start the development setup, opening the app, and rebuilding on changes: - -```bash -npm run start -``` diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/context-pad.png b/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/context-pad.png deleted file mode 100644 index 7d0b9870f5500ae14ef8c529f6a12c6bccbafc49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47316 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%0A*r6nyfbap29Pz@i>UEEsYOngM}Nvpcv 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 M!@CC6dJYl)0-KIWq5uE@ diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/header.png b/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/header.png deleted file mode 100644 index 424064852d70eeb98356d5186b4dbd9fe3cb9f2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20968 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

;?L!%HIPtx1E~xNrQI3Kj=?W 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 QM?rp+kbtgE#ys?Y0QHw|Hvj+t diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/no-layout-connection.png b/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/no-layout-connection.png deleted file mode 100644 index b8dd9b1709ba774970df181b3278e42e298d1187..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46879 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

RVo1Wzs%lns&y_J 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 VEhliQ+7kx)K;1E9>ZQy={s%xB_<;Zb diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/palette.png b/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/palette.png deleted file mode 100644 index d645b77c0ad3cc21fd1ebf3a03c8d63e4b86555f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42422 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 W!3t3X)iH@)a& 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 diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/properties-panel.png b/laokou-cloud/laokou-seata-saga-statemachine-designer/assets/properties-panel.png deleted file mode 100644 index 2012b8fc652e7601725c9e9581dae78221837238..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 290167 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�E&>A%^o-c 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 @moamFhTDRbCQQ&I$P?gV!a-(=H^#5A}eMV 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
Q0Q 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%0ADyY0aAlu>}Id3zA>mXFm_NWj_{4 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�@X2DLTL!6dq+K(ksm}V(I7}|+3H7yGc)zMEEcud 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

  • LhrXnYodG{rpVDP01^h-$OaARBUPgwGM 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�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 diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/package-lock.json b/laokou-cloud/laokou-seata-saga-statemachine-designer/package-lock.json deleted file mode 100644 index 662ec8998f..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/package-lock.json +++ /dev/null @@ -1,17651 +0,0 @@ -{ - "name": "seata-saga-statemachine-designer", - "version": "3.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "seata-saga-statemachine-designer", - "version": "3.0.0", - "license": "Apache-2.0", - "dependencies": { - "@bpmn-io/properties-panel": "^3.8.0", - "bpmn-font": "^0.12.1", - "diagram-js": "^14.0.0", - "diagram-js-grid": "^1.0.0", - "inherits-browser": "^0.1.0", - "min-dash": "^4.1.1", - "min-dom": "^5.0.0", - "tiny-svg": "^4.0.0" - }, - "devDependencies": { - "@babel/core": "^7.23.0", - "@babel/eslint-parser": "^7.22.15", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-react-jsx": "^7.22.15", - "@babel/plugin-transform-runtime": "^7.22.15", - "@babel/preset-env": "^7.22.20", - "@babel/preset-react": "^7.22.15", - "babel-loader": "^9.1.3", - "babel-plugin-module-resolver": "^5.0.0", - "copy-webpack-plugin": "^12.0.0", - "css-loader": "^7.0.0", - "eslint": "^9.0.0", - "eslint-config-airbnb": "^19.0.4", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "html-webpack-plugin": "^5.5.3", - "mini-css-extract-plugin": "^2.7.6", - "npm-run-all2": "^6.0.0", - "webpack": "^5.1.0", - "webpack-cli": "^5.0.0", - "webpack-dev-server": "^5.0.0" - }, - "peerDependencies": { - "react": "^16.3.0 || ^18.0.0" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.24.2", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/eslint-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz", - "integrity": "sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==", - "dev": true, - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", - "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz", - "integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", - "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", - "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", - "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", - "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", - "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz", - "integrity": "sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", - "integrity": "sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz", - "integrity": "sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.24.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz", - "integrity": "sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", - "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz", - "integrity": "sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", - "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", - "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", - "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", - "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz", - "integrity": "sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", - "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", - "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.4", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", - "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-split-export-declaration": "^7.22.6", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", - "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/template": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", - "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz", - "integrity": "sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz", - "integrity": "sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz", - "integrity": "sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", - "integrity": "sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==", - "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz", - "integrity": "sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", - "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", - "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz", - "integrity": "sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", - "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz", - "integrity": "sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", - "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz", - "integrity": "sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", - "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-simple-access": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz", - "integrity": "sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==", - "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz", - "integrity": "sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz", - "integrity": "sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", - "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz", - "integrity": "sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz", - "integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", - "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-replace-supers": "^7.24.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz", - "integrity": "sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz", - "integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", - "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", - "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", - "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", - "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz", - "integrity": "sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", - "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/types": "^7.23.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", - "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", - "dev": true, - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz", - "integrity": "sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz", - "integrity": "sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz", - "integrity": "sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", - "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-plugin-utils": "^7.24.0", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.1", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", - "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", - "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz", - "integrity": "sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", - "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz", - "integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz", - "integrity": "sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz", - "integrity": "sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz", - "integrity": "sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz", - "integrity": "sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.4.tgz", - "integrity": "sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.4", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.1", - "@babel/plugin-syntax-import-attributes": "^7.24.1", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.1", - "@babel/plugin-transform-async-generator-functions": "^7.24.3", - "@babel/plugin-transform-async-to-generator": "^7.24.1", - "@babel/plugin-transform-block-scoped-functions": "^7.24.1", - "@babel/plugin-transform-block-scoping": "^7.24.4", - "@babel/plugin-transform-class-properties": "^7.24.1", - "@babel/plugin-transform-class-static-block": "^7.24.4", - "@babel/plugin-transform-classes": "^7.24.1", - "@babel/plugin-transform-computed-properties": "^7.24.1", - "@babel/plugin-transform-destructuring": "^7.24.1", - "@babel/plugin-transform-dotall-regex": "^7.24.1", - "@babel/plugin-transform-duplicate-keys": "^7.24.1", - "@babel/plugin-transform-dynamic-import": "^7.24.1", - "@babel/plugin-transform-exponentiation-operator": "^7.24.1", - "@babel/plugin-transform-export-namespace-from": "^7.24.1", - "@babel/plugin-transform-for-of": "^7.24.1", - "@babel/plugin-transform-function-name": "^7.24.1", - "@babel/plugin-transform-json-strings": "^7.24.1", - "@babel/plugin-transform-literals": "^7.24.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", - "@babel/plugin-transform-member-expression-literals": "^7.24.1", - "@babel/plugin-transform-modules-amd": "^7.24.1", - "@babel/plugin-transform-modules-commonjs": "^7.24.1", - "@babel/plugin-transform-modules-systemjs": "^7.24.1", - "@babel/plugin-transform-modules-umd": "^7.24.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.24.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", - "@babel/plugin-transform-numeric-separator": "^7.24.1", - "@babel/plugin-transform-object-rest-spread": "^7.24.1", - "@babel/plugin-transform-object-super": "^7.24.1", - "@babel/plugin-transform-optional-catch-binding": "^7.24.1", - "@babel/plugin-transform-optional-chaining": "^7.24.1", - "@babel/plugin-transform-parameters": "^7.24.1", - "@babel/plugin-transform-private-methods": "^7.24.1", - "@babel/plugin-transform-private-property-in-object": "^7.24.1", - "@babel/plugin-transform-property-literals": "^7.24.1", - "@babel/plugin-transform-regenerator": "^7.24.1", - "@babel/plugin-transform-reserved-words": "^7.24.1", - "@babel/plugin-transform-shorthand-properties": "^7.24.1", - "@babel/plugin-transform-spread": "^7.24.1", - "@babel/plugin-transform-sticky-regex": "^7.24.1", - "@babel/plugin-transform-template-literals": "^7.24.1", - "@babel/plugin-transform-typeof-symbol": "^7.24.1", - "@babel/plugin-transform-unicode-escapes": "^7.24.1", - "@babel/plugin-transform-unicode-property-regex": "^7.24.1", - "@babel/plugin-transform-unicode-regex": "^7.24.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.31.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-react": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.1.tgz", - "integrity": "sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-transform-react-display-name": "^7.24.1", - "@babel/plugin-transform-react-jsx": "^7.23.4", - "@babel/plugin-transform-react-jsx-development": "^7.22.5", - "@babel/plugin-transform-react-pure-annotations": "^7.24.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "node_modules/@babel/runtime": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", - "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bpmn-io/cm-theme": { - "version": "0.1.0-alpha.2", - "resolved": "https://registry.npmjs.org/@bpmn-io/cm-theme/-/cm-theme-0.1.0-alpha.2.tgz", - "integrity": "sha512-ZILgiYzxk3KMvxplUXmdRFQo45/JehDPg5k9tWfehmzUOSE13ssyLPil8uCloMQnb3yyzyOWTjb/wzKXTHlFQw==", - "dependencies": { - "@codemirror/language": "^6.3.1", - "@codemirror/view": "^6.5.1", - "@lezer/highlight": "^1.1.4" - }, - "workspaces": { - "packages": [ - "preview-themes" - ] - } - }, - "node_modules/@bpmn-io/diagram-js-ui": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bpmn-io/diagram-js-ui/-/diagram-js-ui-0.2.3.tgz", - "integrity": "sha512-OGyjZKvGK8tHSZ0l7RfeKhilGoOGtFDcoqSGYkX0uhFlo99OVZ9Jn1K7TJGzcE9BdKwvA5Y5kGqHEhdTxHvFfw==", - "dependencies": { - "htm": "^3.1.1", - "preact": "^10.11.2" - } - }, - "node_modules/@bpmn-io/feel-editor": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@bpmn-io/feel-editor/-/feel-editor-1.2.0.tgz", - "integrity": "sha512-402yrNL+a58d9AiNE48IScTiWDGmB+8Fpiq9eqg/sKCzhdHahl5fZyl+cksfcyJjzJF1byUOhYy3UxL3/tbLmQ==", - "dependencies": { - "@bpmn-io/feel-lint": "^1.2.0", - "@codemirror/autocomplete": "^6.12.0", - "@codemirror/commands": "^6.3.3", - "@codemirror/language": "^6.10.0", - "@codemirror/lint": "^6.4.2", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.23.0", - "@lezer/highlight": "^1.2.0", - "lang-feel": "^2.0.0", - "min-dom": "^4.1.0" - }, - "engines": { - "node": ">= 16" - } - }, - "node_modules/@bpmn-io/feel-editor/node_modules/min-dom": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.1.0.tgz", - "integrity": "sha512-1lj1EyoSwY/UmTeT/hhPiZTsq+vK9D+8FAJ/53iK5jT1otkG9rJTixSKdjmTieEvdfES+sKbbTptzaQJhnacjA==", - "dependencies": { - "component-event": "^0.2.1", - "domify": "^1.4.1", - "min-dash": "^4.0.0" - } - }, - "node_modules/@bpmn-io/feel-lint": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@bpmn-io/feel-lint/-/feel-lint-1.2.0.tgz", - "integrity": "sha512-nsvAYxiSbWyjpd3gNnJd+60aTWrZvngYnZfe+GpmkM/pQoOgtF17GhD/p4fgaeAd/uUP3q9sO6EWRX+OU/p9dw==", - "dependencies": { - "@codemirror/language": "^6.8.0", - "lezer-feel": "^1.2.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@bpmn-io/properties-panel": { - "version": "3.18.1", - "resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-3.18.1.tgz", - "integrity": "sha512-ygBhVH99IFG1VbMlbvInXQUeqHwQH4uaajFaUi3OsjELpM1WcmHQ72fXPd1tC/OtJJhZoQajHiTI8SdL38t9ug==", - "dependencies": { - "@bpmn-io/feel-editor": "^1.2.0", - "@codemirror/view": "^6.14.0", - "classnames": "^2.3.1", - "feelers": "^1.3.0", - "focus-trap": "^7.5.2", - "min-dash": "^4.1.1", - "min-dom": "^4.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@bpmn-io/properties-panel/node_modules/min-dom": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.1.0.tgz", - "integrity": "sha512-1lj1EyoSwY/UmTeT/hhPiZTsq+vK9D+8FAJ/53iK5jT1otkG9rJTixSKdjmTieEvdfES+sKbbTptzaQJhnacjA==", - "dependencies": { - "component-event": "^0.2.1", - "domify": "^1.4.1", - "min-dash": "^4.0.0" - } - }, - "node_modules/@codemirror/autocomplete": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.12.0.tgz", - "integrity": "sha512-r4IjdYFthwbCQyvqnSlx0WBHRHi8nBvU+WjJxFUij81qsBfhNudf/XKKmmC2j3m0LaOYUQTf3qiEK1J8lO1sdg==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0" - }, - "peerDependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@codemirror/commands": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz", - "integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.1.0" - } - }, - "node_modules/@codemirror/language": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.0.tgz", - "integrity": "sha512-2vaNn9aPGCRFKWcHPFksctzJ8yS5p7YoaT+jHpc0UGKzNuAIx4qy6R5wiqbP+heEEdyaABA582mNqSHzSoYdmg==", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.23.0", - "@lezer/common": "^1.1.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0", - "style-mod": "^4.0.0" - } - }, - "node_modules/@codemirror/lint": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.4.2.tgz", - "integrity": "sha512-wzRkluWb1ptPKdzlsrbwwjYCPLgzU6N88YBAmlZi8WFyuiEduSd05MnJYNogzyc8rPK7pj6m95ptUApc8sHKVA==", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "node_modules/@codemirror/state": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.0.tgz", - "integrity": "sha512-hm8XshYj5Fo30Bb922QX9hXB/bxOAVH+qaqHBzw5TKa72vOeslyGwd4X8M0c1dJ9JqxlaMceOQ8RsL9tC7gU0A==" - }, - "node_modules/@codemirror/view": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.23.0.tgz", - "integrity": "sha512-/51px9N4uW8NpuWkyUX+iam5+PM6io2fm+QmRnzwqBy5v/pwGg9T0kILFtYeum8hjuvENtgsGNKluOfqIICmeQ==", - "dependencies": { - "@codemirror/state": "^6.4.0", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.0.2.tgz", - "integrity": "sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.0.0.tgz", - "integrity": "sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.12.3.tgz", - "integrity": "sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "node_modules/@lezer/common": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", - "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" - }, - "node_modules/@lezer/highlight": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", - "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/lr": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz", - "integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/markdown": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.2.0.tgz", - "integrity": "sha512-d7MwsfAukZJo1GpPrcPGa3MxaFFOqNp0gbqF+3F7pTeNDOgeJN1muXzx1XXDPt+Ac+/voCzsH7qXqnn+xReG/g==", - "dependencies": { - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, - "dependencies": { - "eslint-scope": "5.1.1" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dev": true, - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.56.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz", - "integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.41", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", - "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.14", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", - "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.11.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", - "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/qs": { - "version": "6.9.11", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", - "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.4.tgz", - "integrity": "sha512-BMtLxpV+8BD+6ZPFIWmnUBpQoy+A+ujcg4rhp2iwCRJYA7PEh2MS4NL3lz8EiDlLrJPp2hg9qWihr5pd//jcGw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", - "es-shim-unscopables": "^1.0.2" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true - }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/babel-loader": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", - "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", - "dev": true, - "dependencies": { - "find-cache-dir": "^4.0.0", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0", - "webpack": ">=5" - } - }, - "node_modules/babel-plugin-module-resolver": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz", - "integrity": "sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==", - "dev": true, - "dependencies": { - "find-babel-config": "^2.0.0", - "glob": "^8.0.3", - "pkg-up": "^3.1.0", - "reselect": "^4.1.7", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">= 16" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", - "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.1", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", - "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1", - "core-js-compat": "^3.36.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", - "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/bpmn-font": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/bpmn-font/-/bpmn-font-0.12.1.tgz", - "integrity": "sha512-quQ47cFuFSZw3y5ta4J2eg+g/UG38pN9Uk8QzR988RyjFP7agdgwmVXPErCGqaFm4UyTTNGtx9jCFdcxw990vg==" - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, - "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001599", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz", - "integrity": "sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/classnames": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" - }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true - }, - "node_modules/component-event": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/component-event/-/component-event-0.2.1.tgz", - "integrity": "sha512-wGA++isMqiDq1jPYeyv2as/Bt/u+3iLW0rEa+8NQ82jAv3TgqMiCM+B2SaBdn2DfLilLjjq736YcezihRYhfxw==" - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/copy-webpack-plugin": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz", - "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", - "dev": true, - "dependencies": { - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.1", - "globby": "^14.0.0", - "normalize-path": "^3.0.0", - "schema-utils": "^4.2.0", - "serialize-javascript": "^6.0.2" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/core-js-compat": { - "version": "3.36.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", - "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/crelt": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-loader": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.0.0.tgz", - "integrity": "sha512-WrO4FVoamxt5zY9CauZjoJgXRi/LZKIk+Ta7YvpSGr5r/eMYPNp5/T9ODlMe4/1rF5DYlycG1avhV4g3A/tiAw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.27.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/css-loader/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/css-loader/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/css-loader/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "node_modules/diagram-js": { - "version": "14.3.1", - "resolved": "https://registry.npmjs.org/diagram-js/-/diagram-js-14.3.1.tgz", - "integrity": "sha512-QXwH2kdlTP8cfWDCfYnnhvJ9PXX8UQ/M8TJaeLfcIjJPBOrfSEfLI/wuI7VNtAZZ9munlcGmCnh8hEBtcjB8kA==", - "dependencies": { - "@bpmn-io/diagram-js-ui": "^0.2.3", - "clsx": "^2.1.0", - "didi": "^10.2.2", - "inherits-browser": "^0.1.0", - "min-dash": "^4.1.0", - "min-dom": "^4.1.0", - "object-refs": "^0.4.0", - "path-intersection": "^3.0.0", - "tiny-svg": "^3.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/diagram-js-grid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/diagram-js-grid/-/diagram-js-grid-1.0.0.tgz", - "integrity": "sha512-h3fCeoRnjNXaa4DW2upsKZv4xZvrI29zdSQwYb//nngNpAl1BgxTTI3Wb++AFmDFi1RydVH+TzRmpWvVyl4u8Q==", - "dependencies": { - "min-dash": "^4.1.1", - "tiny-svg": "^3.0.1" - } - }, - "node_modules/diagram-js-grid/node_modules/tiny-svg": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tiny-svg/-/tiny-svg-3.0.1.tgz", - "integrity": "sha512-P8T4iwiW1t95vpHVHqrD36Brn7TqFYCPSHIWk9WLJtYK1X4aDd+5cgqcAADIWSjf1/i5idKnpCh9mim8hEdRBg==" - }, - "node_modules/diagram-js/node_modules/min-dom": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.1.0.tgz", - "integrity": "sha512-1lj1EyoSwY/UmTeT/hhPiZTsq+vK9D+8FAJ/53iK5jT1otkG9rJTixSKdjmTieEvdfES+sKbbTptzaQJhnacjA==", - "dependencies": { - "component-event": "^0.2.1", - "domify": "^1.4.1", - "min-dash": "^4.0.0" - } - }, - "node_modules/diagram-js/node_modules/tiny-svg": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tiny-svg/-/tiny-svg-3.0.1.tgz", - "integrity": "sha512-P8T4iwiW1t95vpHVHqrD36Brn7TqFYCPSHIWk9WLJtYK1X4aDd+5cgqcAADIWSjf1/i5idKnpCh9mim8hEdRBg==" - }, - "node_modules/didi": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/didi/-/didi-10.2.2.tgz", - "integrity": "sha512-l8NYkYFXV1izHI65EyT8EXOjUZtKmQkHLTT89cSP7HU5J/G7AOj0dXKtLc04EXYlga99PBY18IPjOeZ+c3DI4w==", - "engines": { - "node": ">= 16" - } - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/domify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/domify/-/domify-1.4.2.tgz", - "integrity": "sha512-m4yreHcUWHBncGVV7U+yQzc12vIlq0jMrtHZ5mW6dQMiL/7skSYNVX9wqKwOtyO9SGCgevrAFEgOCAHmamHTUA==" - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.710", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.710.tgz", - "integrity": "sha512-w+9yAVHoHhysCa+gln7AzbO9CdjFcL/wN/5dd+XW/Msl2d/4+WisEaCF1nty0xbAKaxdaJfgLB2296U7zZB7BA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", - "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - }, - "node_modules/envinfo": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", - "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/es-abstract": { - "version": "1.22.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", - "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.1", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", - "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", - "dev": true, - "dependencies": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.4", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", - "dev": true - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.0.0.tgz", - "integrity": "sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^3.0.2", - "@eslint/js": "9.0.0", - "@humanwhocodes/config-array": "^0.12.3", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.1", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-airbnb": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", - "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", - "dev": true, - "dependencies": { - "eslint-config-airbnb-base": "^15.0.0", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5" - }, - "engines": { - "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0" - } - }, - "node_modules/eslint-config-airbnb/node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", - "dev": true, - "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", - "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmmirror.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", - "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/feelers": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/feelers/-/feelers-1.3.0.tgz", - "integrity": "sha512-aldR3ybeQlXs1T+PqhKTLyaBJ1NP4bovDrQZzBZ9UUnN4HdEObQpWl9hsgyb8HKwojzRtBoq1BzmGIf07vuRCg==", - "dependencies": { - "@bpmn-io/cm-theme": "^0.1.0-alpha.2", - "@bpmn-io/feel-lint": "^1.2.0", - "@codemirror/autocomplete": "^6.10.1", - "@codemirror/commands": "^6.3.0", - "@codemirror/language": "^6.9.1", - "@codemirror/lint": "^6.4.2", - "@codemirror/state": "^6.3.0", - "@codemirror/view": "^6.21.3", - "@lezer/common": "^1.1.0", - "@lezer/highlight": "^1.1.6", - "@lezer/lr": "^1.3.13", - "@lezer/markdown": "^1.1.0", - "feelin": "^3.0.0", - "lezer-feel": "^1.2.4", - "min-dom": "^4.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/feelers/node_modules/min-dom": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.1.0.tgz", - "integrity": "sha512-1lj1EyoSwY/UmTeT/hhPiZTsq+vK9D+8FAJ/53iK5jT1otkG9rJTixSKdjmTieEvdfES+sKbbTptzaQJhnacjA==", - "dependencies": { - "component-event": "^0.2.1", - "domify": "^1.4.1", - "min-dash": "^4.0.0" - } - }, - "node_modules/feelin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/feelin/-/feelin-3.0.1.tgz", - "integrity": "sha512-aYXH3UYkM2eopg3scgNRNEo/ecwizKH6qTqkEu5nSLMMlMgfhLDhWrLl7ChG5iHspO9o4Q2YSP1o4wW8q0L2Qw==", - "dependencies": { - "@lezer/lr": "^1.3.9", - "lezer-feel": "^1.2.5", - "luxon": "^3.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/find-babel-config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.0.0.tgz", - "integrity": "sha512-dOKT7jvF3hGzlW60Gc3ONox/0rRZ/tz7WCil0bqA1In/3I8f1BctpXahRnEKDySZqci7u+dqq93sZST9fOJpFw==", - "dev": true, - "dependencies": { - "json5": "^2.1.1", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/find-babel-config/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-cache-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", - "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", - "dev": true, - "dependencies": { - "common-path-prefix": "^3.0.0", - "pkg-dir": "^7.0.0" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/focus-trap": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", - "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", - "dependencies": { - "tabbable": "^6.2.0" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/globby": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", - "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/htm": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz", - "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==" - }, - "node_modules/html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", - "dev": true - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.20.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/import-local/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/inherits-browser": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/inherits-browser/-/inherits-browser-0.1.0.tgz", - "integrity": "sha512-CJHHvW3jQ6q7lzsXPpapLdMx5hDpSF3FSh45pwsj6bKxJJ8Nl8v43i5yXnr3BdfOimGHKyniewQtnAIp3vyJJw==" - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-network-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.0.1.tgz", - "integrity": "sha512-OwQXkwBJeESyhFw+OumbJVD58BFBJJI5OM5S1+eyrDKlgDZPX2XNT5gXS56GSD3NPbbwUuMlR1Q71SRp5SobuQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lang-feel": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lang-feel/-/lang-feel-2.0.0.tgz", - "integrity": "sha512-cMD6EIhb7vyXLs4kXmaphfZZNr5SkbRxmkfsZUjUJzOV5YxyKBF73VI/8fC3GDUifzs0lVo2DruVszk5igrddg==", - "dependencies": { - "@codemirror/autocomplete": "^6.9.1", - "@codemirror/language": "^6.9.1", - "@codemirror/state": "^6.2.1", - "@codemirror/view": "^6.21.0", - "@lezer/common": "^1.1.2", - "lezer-feel": "^1.2.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/launch-editor": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", - "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", - "dev": true, - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lezer-feel": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/lezer-feel/-/lezer-feel-1.2.6.tgz", - "integrity": "sha512-SkTqHThCVZYWhVXy6xh79ULDYPLcWMw0XNcY4ZIr+b5jXTsGDIMxNFZe7oNXNBBZizH045jG3vgfM6t/59pvcw==", - "dependencies": { - "@lezer/highlight": "^1.2.0", - "@lezer/lr": "^1.4.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/luxon": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", - "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.7.7.tgz", - "integrity": "sha512-x9qc6k88J/VVwnfTkJV8pRRswJ2156Rc4w5rciRqKceFDZ0y1MqsNL9pkg5sE0GOcDzZYbonreALhaHzg1siFw==", - "dev": true, - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">= 4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/min-dash": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.2.1.tgz", - "integrity": "sha512-to+unsToePnm7cUeR9TrMzFlETHd/UXmU+ELTRfWZj5XGT41KF6X3L233o3E/GdEs3sk2Tbw/lOLD1avmWkg8A==" - }, - "node_modules/min-dom": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-5.0.0.tgz", - "integrity": "sha512-eqZlSlxmCje0Q1B4sR2RUuh5DOE8FyYLPo35xuJabHBrlzEcG/DFg09TT2tIWRVB3w/6ZgCBkVIPpcOiD66BxQ==", - "dependencies": { - "domify": "^2.0.0", - "min-dash": "^4.2.1" - } - }, - "node_modules/min-dom/node_modules/domify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/domify/-/domify-2.0.0.tgz", - "integrity": "sha512-rmvrrmWQPD/X1A/nPBfIVg4r05792QdG9Z4Prk6oQG0F9zBMDkr0GKAdds1wjb2dq1rTz/ywc4ZxpZbgz0tttg==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz", - "integrity": "sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA==", - "dev": true, - "dependencies": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true - }, - "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-run-all2": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-6.1.2.tgz", - "integrity": "sha512-WwwnS8Ft+RpXve6T2EIEVpFLSqN+ORHRvgNk3H9N62SZXjmzKoRhMFg3I17TK3oMaAEr+XFbRirWS2Fn3BCPSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "cross-spawn": "^7.0.3", - "memorystream": "^0.3.1", - "minimatch": "^9.0.0", - "pidtree": "^0.6.0", - "read-package-json-fast": "^3.0.2", - "shell-quote": "^1.7.3" - }, - "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "npm-run-all2": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0", - "npm": ">= 8" - } - }, - "node_modules/npm-run-all2/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm-run-all2/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-refs": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-refs/-/object-refs-0.4.0.tgz", - "integrity": "sha512-6kJqKWryKZmtte6QYvouas0/EIJKPI1/MMIuRsiBlNuhIMfqYTggzX2F1AJ2+cDs288xyi9GL7FyasHINR98BQ==", - "engines": { - "node": "*" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/object.hasown": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", - "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/open": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/open/-/open-10.0.4.tgz", - "integrity": "sha512-oujJ/FFr7ra6/7gJuQ4ZJJ8Gf2VHM0J3J/W7IvH++zaqEzacWVxzK++NiVY5NLHTTj7u/jNH5H3Ei9biL31Lng==", - "dev": true, - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/p-retry": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", - "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", - "dev": true, - "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/path-intersection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-intersection/-/path-intersection-3.0.0.tgz", - "integrity": "sha512-Rdnfb33F9+qadWe3ZyzDpw3KSXQhsK1MByL44QzSDIQtMAujd0zFx9f+kt4SaQp1JOoXl5pl5K28EoEuAEgarA==", - "engines": { - "node": ">= 14.20" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", - "dev": true, - "dependencies": { - "find-up": "^6.3.0" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", - "dev": true, - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.15", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", - "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/preact": { - "version": "10.19.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.3.tgz", - "integrity": "sha512-nHHTeFVBTHRGxJXKkKu5hT8C/YWBkPso4/Gad6xuj5dbptt9iF9NZr9pHbPhBrnT2klheu7mHTxTZ/LjwJiEiQ==" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", - "dev": true, - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/reselect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.2", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-mod": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", - "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==" - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", - "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/tiny-svg": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tiny-svg/-/tiny-svg-4.0.0.tgz", - "integrity": "sha512-r5fvsVXJ6BvLzEmAVF3gJusimBveGJJ25rtwTxW9FqgGsEP/gYgiKzEEqekmm27gkW6BEp4rfruvhz9n+3CVSw==", - "engines": { - "node": ">= 16" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", - "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" - }, - "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/webpack": { - "version": "5.91.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", - "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.16.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", - "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", - "colorette": "^2.0.14", - "commander": "^10.0.1", - "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/webpack-dev-middleware": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.1.1.tgz", - "integrity": "sha512-NmRVq4AvRQs66dFWyDR4GsFDJggtSi2Yn38MXLk0nffgF9n/AIP4TFBg2TQKYaRAN4sHuKOTiz9BnNCENDLEVA==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^4.6.0", - "mime-types": "^2.1.31", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", - "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.13", - "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", - "@types/serve-index": "^1.9.4", - "@types/serve-static": "^1.15.5", - "@types/sockjs": "^0.3.36", - "@types/ws": "^8.5.10", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.2.1", - "chokidar": "^3.6.0", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.4.0", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", - "open": "^10.0.3", - "p-retry": "^6.2.0", - "rimraf": "^5.0.5", - "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.1.0", - "ws": "^8.16.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, - "engines": { - "node": ">=12.20" - } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", - "dev": true, - "requires": { - "@babel/highlight": "^7.24.2", - "picocolors": "^1.0.0" - } - }, - "@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", - "dev": true - }, - "@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - } - }, - "@babel/eslint-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz", - "integrity": "sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==", - "dev": true, - "requires": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - } - }, - "@babel/generator": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", - "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", - "dev": true, - "requires": { - "@babel/types": "^7.24.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.15" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz", - "integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "semver": "^6.3.1" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", - "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", - "dev": true, - "requires": { - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", - "dev": true, - "requires": { - "@babel/types": "^7.24.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" - } - }, - "@babel/helper-replace-supers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", - "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5" - } - }, - "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" - } - }, - "@babel/helpers": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", - "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", - "dev": true, - "requires": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" - } - }, - "@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - } - }, - "@babel/parser": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", - "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", - "dev": true - }, - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz", - "integrity": "sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", - "integrity": "sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz", - "integrity": "sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.24.1" - } - }, - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz", - "integrity": "sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "requires": {} - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-import-assertions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", - "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-syntax-import-attributes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz", - "integrity": "sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", - "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-async-generator-functions": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", - "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", - "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", - "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz", - "integrity": "sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-class-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", - "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-class-static-block": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", - "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.24.4", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", - "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-split-export-declaration": "^7.22.6", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", - "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/template": "^7.24.0" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", - "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz", - "integrity": "sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz", - "integrity": "sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-dynamic-import": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz", - "integrity": "sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", - "integrity": "sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-export-namespace-from": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz", - "integrity": "sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", - "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", - "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-json-strings": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz", - "integrity": "sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", - "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz", - "integrity": "sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", - "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz", - "integrity": "sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", - "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-simple-access": "^7.22.5" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz", - "integrity": "sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-identifier": "^7.22.20" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz", - "integrity": "sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz", - "integrity": "sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", - "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-transform-numeric-separator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz", - "integrity": "sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-transform-object-rest-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz", - "integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.1" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", - "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-replace-supers": "^7.24.1" - } - }, - "@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz", - "integrity": "sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-transform-optional-chaining": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz", - "integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", - "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-private-methods": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", - "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-private-property-in-object": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", - "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", - "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-react-display-name": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz", - "integrity": "sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-react-jsx": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", - "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/types": "^7.23.4" - } - }, - "@babel/plugin-transform-react-jsx-development": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", - "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", - "dev": true, - "requires": { - "@babel/plugin-transform-react-jsx": "^7.22.5" - } - }, - "@babel/plugin-transform-react-pure-annotations": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz", - "integrity": "sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz", - "integrity": "sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "regenerator-transform": "^0.15.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz", - "integrity": "sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", - "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-plugin-utils": "^7.24.0", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.1", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", - "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", - "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz", - "integrity": "sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", - "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz", - "integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz", - "integrity": "sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz", - "integrity": "sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz", - "integrity": "sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz", - "integrity": "sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/preset-env": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.4.tgz", - "integrity": "sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.4", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.1", - "@babel/plugin-syntax-import-attributes": "^7.24.1", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.1", - "@babel/plugin-transform-async-generator-functions": "^7.24.3", - "@babel/plugin-transform-async-to-generator": "^7.24.1", - "@babel/plugin-transform-block-scoped-functions": "^7.24.1", - "@babel/plugin-transform-block-scoping": "^7.24.4", - "@babel/plugin-transform-class-properties": "^7.24.1", - "@babel/plugin-transform-class-static-block": "^7.24.4", - "@babel/plugin-transform-classes": "^7.24.1", - "@babel/plugin-transform-computed-properties": "^7.24.1", - "@babel/plugin-transform-destructuring": "^7.24.1", - "@babel/plugin-transform-dotall-regex": "^7.24.1", - "@babel/plugin-transform-duplicate-keys": "^7.24.1", - "@babel/plugin-transform-dynamic-import": "^7.24.1", - "@babel/plugin-transform-exponentiation-operator": "^7.24.1", - "@babel/plugin-transform-export-namespace-from": "^7.24.1", - "@babel/plugin-transform-for-of": "^7.24.1", - "@babel/plugin-transform-function-name": "^7.24.1", - "@babel/plugin-transform-json-strings": "^7.24.1", - "@babel/plugin-transform-literals": "^7.24.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", - "@babel/plugin-transform-member-expression-literals": "^7.24.1", - "@babel/plugin-transform-modules-amd": "^7.24.1", - "@babel/plugin-transform-modules-commonjs": "^7.24.1", - "@babel/plugin-transform-modules-systemjs": "^7.24.1", - "@babel/plugin-transform-modules-umd": "^7.24.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.24.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", - "@babel/plugin-transform-numeric-separator": "^7.24.1", - "@babel/plugin-transform-object-rest-spread": "^7.24.1", - "@babel/plugin-transform-object-super": "^7.24.1", - "@babel/plugin-transform-optional-catch-binding": "^7.24.1", - "@babel/plugin-transform-optional-chaining": "^7.24.1", - "@babel/plugin-transform-parameters": "^7.24.1", - "@babel/plugin-transform-private-methods": "^7.24.1", - "@babel/plugin-transform-private-property-in-object": "^7.24.1", - "@babel/plugin-transform-property-literals": "^7.24.1", - "@babel/plugin-transform-regenerator": "^7.24.1", - "@babel/plugin-transform-reserved-words": "^7.24.1", - "@babel/plugin-transform-shorthand-properties": "^7.24.1", - "@babel/plugin-transform-spread": "^7.24.1", - "@babel/plugin-transform-sticky-regex": "^7.24.1", - "@babel/plugin-transform-template-literals": "^7.24.1", - "@babel/plugin-transform-typeof-symbol": "^7.24.1", - "@babel/plugin-transform-unicode-escapes": "^7.24.1", - "@babel/plugin-transform-unicode-property-regex": "^7.24.1", - "@babel/plugin-transform-unicode-regex": "^7.24.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.31.0", - "semver": "^6.3.1" - } - }, - "@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/preset-react": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.1.tgz", - "integrity": "sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-transform-react-display-name": "^7.24.1", - "@babel/plugin-transform-react-jsx": "^7.23.4", - "@babel/plugin-transform-react-jsx-development": "^7.22.5", - "@babel/plugin-transform-react-pure-annotations": "^7.24.1" - } - }, - "@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "@babel/runtime": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", - "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.14.0" - } - }, - "@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" - } - }, - "@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - }, - "@bpmn-io/cm-theme": { - "version": "0.1.0-alpha.2", - "resolved": "https://registry.npmjs.org/@bpmn-io/cm-theme/-/cm-theme-0.1.0-alpha.2.tgz", - "integrity": "sha512-ZILgiYzxk3KMvxplUXmdRFQo45/JehDPg5k9tWfehmzUOSE13ssyLPil8uCloMQnb3yyzyOWTjb/wzKXTHlFQw==", - "requires": { - "@codemirror/language": "^6.3.1", - "@codemirror/view": "^6.5.1", - "@lezer/highlight": "^1.1.4" - } - }, - "@bpmn-io/diagram-js-ui": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bpmn-io/diagram-js-ui/-/diagram-js-ui-0.2.3.tgz", - "integrity": "sha512-OGyjZKvGK8tHSZ0l7RfeKhilGoOGtFDcoqSGYkX0uhFlo99OVZ9Jn1K7TJGzcE9BdKwvA5Y5kGqHEhdTxHvFfw==", - "requires": { - "htm": "^3.1.1", - "preact": "^10.11.2" - } - }, - "@bpmn-io/feel-editor": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@bpmn-io/feel-editor/-/feel-editor-1.2.0.tgz", - "integrity": "sha512-402yrNL+a58d9AiNE48IScTiWDGmB+8Fpiq9eqg/sKCzhdHahl5fZyl+cksfcyJjzJF1byUOhYy3UxL3/tbLmQ==", - "requires": { - "@bpmn-io/feel-lint": "^1.2.0", - "@codemirror/autocomplete": "^6.12.0", - "@codemirror/commands": "^6.3.3", - "@codemirror/language": "^6.10.0", - "@codemirror/lint": "^6.4.2", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.23.0", - "@lezer/highlight": "^1.2.0", - "lang-feel": "^2.0.0", - "min-dom": "^4.1.0" - }, - "dependencies": { - "min-dom": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.1.0.tgz", - "integrity": "sha512-1lj1EyoSwY/UmTeT/hhPiZTsq+vK9D+8FAJ/53iK5jT1otkG9rJTixSKdjmTieEvdfES+sKbbTptzaQJhnacjA==", - "requires": { - "component-event": "^0.2.1", - "domify": "^1.4.1", - "min-dash": "^4.0.0" - } - } - } - }, - "@bpmn-io/feel-lint": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@bpmn-io/feel-lint/-/feel-lint-1.2.0.tgz", - "integrity": "sha512-nsvAYxiSbWyjpd3gNnJd+60aTWrZvngYnZfe+GpmkM/pQoOgtF17GhD/p4fgaeAd/uUP3q9sO6EWRX+OU/p9dw==", - "requires": { - "@codemirror/language": "^6.8.0", - "lezer-feel": "^1.2.3" - } - }, - "@bpmn-io/properties-panel": { - "version": "3.18.1", - "resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-3.18.1.tgz", - "integrity": "sha512-ygBhVH99IFG1VbMlbvInXQUeqHwQH4uaajFaUi3OsjELpM1WcmHQ72fXPd1tC/OtJJhZoQajHiTI8SdL38t9ug==", - "requires": { - "@bpmn-io/feel-editor": "^1.2.0", - "@codemirror/view": "^6.14.0", - "classnames": "^2.3.1", - "feelers": "^1.3.0", - "focus-trap": "^7.5.2", - "min-dash": "^4.1.1", - "min-dom": "^4.0.3" - }, - "dependencies": { - "min-dom": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.1.0.tgz", - "integrity": "sha512-1lj1EyoSwY/UmTeT/hhPiZTsq+vK9D+8FAJ/53iK5jT1otkG9rJTixSKdjmTieEvdfES+sKbbTptzaQJhnacjA==", - "requires": { - "component-event": "^0.2.1", - "domify": "^1.4.1", - "min-dash": "^4.0.0" - } - } - } - }, - "@codemirror/autocomplete": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.12.0.tgz", - "integrity": "sha512-r4IjdYFthwbCQyvqnSlx0WBHRHi8nBvU+WjJxFUij81qsBfhNudf/XKKmmC2j3m0LaOYUQTf3qiEK1J8lO1sdg==", - "requires": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0" - } - }, - "@codemirror/commands": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz", - "integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==", - "requires": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.1.0" - } - }, - "@codemirror/language": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.0.tgz", - "integrity": "sha512-2vaNn9aPGCRFKWcHPFksctzJ8yS5p7YoaT+jHpc0UGKzNuAIx4qy6R5wiqbP+heEEdyaABA582mNqSHzSoYdmg==", - "requires": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.23.0", - "@lezer/common": "^1.1.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0", - "style-mod": "^4.0.0" - } - }, - "@codemirror/lint": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.4.2.tgz", - "integrity": "sha512-wzRkluWb1ptPKdzlsrbwwjYCPLgzU6N88YBAmlZi8WFyuiEduSd05MnJYNogzyc8rPK7pj6m95ptUApc8sHKVA==", - "requires": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "@codemirror/state": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.0.tgz", - "integrity": "sha512-hm8XshYj5Fo30Bb922QX9hXB/bxOAVH+qaqHBzw5TKa72vOeslyGwd4X8M0c1dJ9JqxlaMceOQ8RsL9tC7gU0A==" - }, - "@codemirror/view": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.23.0.tgz", - "integrity": "sha512-/51px9N4uW8NpuWkyUX+iam5+PM6io2fm+QmRnzwqBy5v/pwGg9T0kILFtYeum8hjuvENtgsGNKluOfqIICmeQ==", - "requires": { - "@codemirror/state": "^6.4.0", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.0.2.tgz", - "integrity": "sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "@eslint/js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.0.0.tgz", - "integrity": "sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.12.3.tgz", - "integrity": "sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "@lezer/common": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", - "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" - }, - "@lezer/highlight": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", - "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", - "requires": { - "@lezer/common": "^1.0.0" - } - }, - "@lezer/lr": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz", - "integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==", - "requires": { - "@lezer/common": "^1.0.0" - } - }, - "@lezer/markdown": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.2.0.tgz", - "integrity": "sha512-d7MwsfAukZJo1GpPrcPGa3MxaFFOqNp0gbqF+3F7pTeNDOgeJN1muXzx1XXDPt+Ac+/voCzsH7qXqnn+xReG/g==", - "requires": { - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0" - } - }, - "@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, - "requires": { - "eslint-scope": "5.1.1" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true - }, - "@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true - }, - "@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "8.56.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz", - "integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.41", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", - "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "@types/http-proxy": { - "version": "1.17.14", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", - "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "@types/node": { - "version": "20.11.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", - "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", - "dev": true, - "requires": { - "undici-types": "~5.26.4" - } - }, - "@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/qs": { - "version": "6.9.11", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true - }, - "@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", - "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", - "dev": true, - "requires": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "requires": {} - }, - "@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, - "requires": {} - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "requires": { - "dequal": "^2.0.3" - } - }, - "array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - } - }, - "array.prototype.findlast": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.4.tgz", - "integrity": "sha512-BMtLxpV+8BD+6ZPFIWmnUBpQoy+A+ujcg4rhp2iwCRJYA7PEh2MS4NL3lz8EiDlLrJPp2hg9qWihr5pd//jcGw==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - } - }, - "array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - } - }, - "array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", - "es-shim-unscopables": "^1.0.2" - } - }, - "arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - } - }, - "ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true - }, - "asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.3" - } - }, - "available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "requires": { - "possible-typed-array-names": "^1.0.0" - } - }, - "axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", - "dev": true - }, - "axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "dev": true, - "requires": { - "dequal": "^2.0.3" - } - }, - "babel-loader": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", - "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", - "dev": true, - "requires": { - "find-cache-dir": "^4.0.0", - "schema-utils": "^4.0.0" - } - }, - "babel-plugin-module-resolver": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz", - "integrity": "sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==", - "dev": true, - "requires": { - "find-babel-config": "^2.0.0", - "glob": "^8.0.3", - "pkg-up": "^3.1.0", - "reselect": "^4.1.7", - "resolve": "^1.22.1" - } - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", - "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.1", - "semver": "^6.3.1" - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", - "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.1", - "core-js-compat": "^3.36.1" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", - "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.1" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "bpmn-font": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/bpmn-font/-/bpmn-font-0.12.1.tgz", - "integrity": "sha512-quQ47cFuFSZw3y5ta4J2eg+g/UG38pN9Uk8QzR988RyjFP7agdgwmVXPErCGqaFm4UyTTNGtx9jCFdcxw990vg==" - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, - "requires": { - "run-applescript": "^7.0.0" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true - }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "caniuse-lite": { - "version": "1.0.30001599", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz", - "integrity": "sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, - "classnames": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" - }, - "clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - } - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==" - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true - }, - "common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true - }, - "component-event": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/component-event/-/component-event-0.2.1.tgz", - "integrity": "sha512-wGA++isMqiDq1jPYeyv2as/Bt/u+3iLW0rEa+8NQ82jAv3TgqMiCM+B2SaBdn2DfLilLjjq736YcezihRYhfxw==" - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, - "connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "copy-webpack-plugin": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz", - "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", - "dev": true, - "requires": { - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.1", - "globby": "^14.0.0", - "normalize-path": "^3.0.0", - "schema-utils": "^4.2.0", - "serialize-javascript": "^6.0.2" - } - }, - "core-js-compat": { - "version": "3.36.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", - "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", - "dev": true, - "requires": { - "browserslist": "^4.23.0" - } - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "crelt": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "css-loader": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.0.0.tgz", - "integrity": "sha512-WrO4FVoamxt5zY9CauZjoJgXRi/LZKIk+Ta7YvpSGr5r/eMYPNp5/T9ODlMe4/1rF5DYlycG1avhV4g3A/tiAw==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, - "requires": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - } - }, - "default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true - }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - } - }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - } - }, - "define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true - }, - "define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "requires": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "diagram-js": { - "version": "14.3.1", - "resolved": "https://registry.npmjs.org/diagram-js/-/diagram-js-14.3.1.tgz", - "integrity": "sha512-QXwH2kdlTP8cfWDCfYnnhvJ9PXX8UQ/M8TJaeLfcIjJPBOrfSEfLI/wuI7VNtAZZ9munlcGmCnh8hEBtcjB8kA==", - "requires": { - "@bpmn-io/diagram-js-ui": "^0.2.3", - "clsx": "^2.1.0", - "didi": "^10.2.2", - "inherits-browser": "^0.1.0", - "min-dash": "^4.1.0", - "min-dom": "^4.1.0", - "object-refs": "^0.4.0", - "path-intersection": "^3.0.0", - "tiny-svg": "^3.0.1" - }, - "dependencies": { - "min-dom": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.1.0.tgz", - "integrity": "sha512-1lj1EyoSwY/UmTeT/hhPiZTsq+vK9D+8FAJ/53iK5jT1otkG9rJTixSKdjmTieEvdfES+sKbbTptzaQJhnacjA==", - "requires": { - "component-event": "^0.2.1", - "domify": "^1.4.1", - "min-dash": "^4.0.0" - } - }, - "tiny-svg": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tiny-svg/-/tiny-svg-3.0.1.tgz", - "integrity": "sha512-P8T4iwiW1t95vpHVHqrD36Brn7TqFYCPSHIWk9WLJtYK1X4aDd+5cgqcAADIWSjf1/i5idKnpCh9mim8hEdRBg==" - } - } - }, - "diagram-js-grid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/diagram-js-grid/-/diagram-js-grid-1.0.0.tgz", - "integrity": "sha512-h3fCeoRnjNXaa4DW2upsKZv4xZvrI29zdSQwYb//nngNpAl1BgxTTI3Wb++AFmDFi1RydVH+TzRmpWvVyl4u8Q==", - "requires": { - "min-dash": "^4.1.1", - "tiny-svg": "^3.0.1" - }, - "dependencies": { - "tiny-svg": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tiny-svg/-/tiny-svg-3.0.1.tgz", - "integrity": "sha512-P8T4iwiW1t95vpHVHqrD36Brn7TqFYCPSHIWk9WLJtYK1X4aDd+5cgqcAADIWSjf1/i5idKnpCh9mim8hEdRBg==" - } - } - }, - "didi": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/didi/-/didi-10.2.2.tgz", - "integrity": "sha512-l8NYkYFXV1izHI65EyT8EXOjUZtKmQkHLTT89cSP7HU5J/G7AOj0dXKtLc04EXYlga99PBY18IPjOeZ+c3DI4w==" - }, - "dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" - } - }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "requires": { - "utila": "~0.4" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/domify/-/domify-1.4.2.tgz", - "integrity": "sha512-m4yreHcUWHBncGVV7U+yQzc12vIlq0jMrtHZ5mW6dQMiL/7skSYNVX9wqKwOtyO9SGCgevrAFEgOCAHmamHTUA==" - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.710", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.710.tgz", - "integrity": "sha512-w+9yAVHoHhysCa+gln7AzbO9CdjFcL/wN/5dd+XW/Msl2d/4+WisEaCF1nty0xbAKaxdaJfgLB2296U7zZB7BA==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true - }, - "enhanced-resolve": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", - "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - }, - "envinfo": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", - "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", - "dev": true - }, - "es-abstract": { - "version": "1.22.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", - "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.1", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" - } - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.4" - } - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true - }, - "es-iterator-helpers": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", - "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", - "dev": true, - "requires": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.4", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" - } - }, - "es-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", - "dev": true - }, - "es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - } - }, - "es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "requires": { - "hasown": "^2.0.0" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "eslint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.0.0.tgz", - "integrity": "sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^3.0.2", - "@eslint/js": "9.0.0", - "@humanwhocodes/config-array": "^0.12.3", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.1", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-scope": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", - "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } - }, - "eslint-config-airbnb": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", - "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", - "dev": true, - "requires": { - "eslint-config-airbnb-base": "^15.0.0", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5" - }, - "dependencies": { - "eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", - "dev": true, - "requires": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - } - } - } - }, - "eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "requires": { - "debug": "^3.2.7" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "dev": true, - "requires": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "eslint-plugin-react": { - "version": "7.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", - "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", - "dev": true, - "requires": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - } - } - }, - "eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmmirror.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "dev": true, - "peer": true, - "requires": {} - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "espree": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", - "dev": true, - "requires": { - "acorn": "^8.11.3", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true - } - } - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true - }, - "fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "feelers": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/feelers/-/feelers-1.3.0.tgz", - "integrity": "sha512-aldR3ybeQlXs1T+PqhKTLyaBJ1NP4bovDrQZzBZ9UUnN4HdEObQpWl9hsgyb8HKwojzRtBoq1BzmGIf07vuRCg==", - "requires": { - "@bpmn-io/cm-theme": "^0.1.0-alpha.2", - "@bpmn-io/feel-lint": "^1.2.0", - "@codemirror/autocomplete": "^6.10.1", - "@codemirror/commands": "^6.3.0", - "@codemirror/language": "^6.9.1", - "@codemirror/lint": "^6.4.2", - "@codemirror/state": "^6.3.0", - "@codemirror/view": "^6.21.3", - "@lezer/common": "^1.1.0", - "@lezer/highlight": "^1.1.6", - "@lezer/lr": "^1.3.13", - "@lezer/markdown": "^1.1.0", - "feelin": "^3.0.0", - "lezer-feel": "^1.2.4", - "min-dom": "^4.1.0" - }, - "dependencies": { - "min-dom": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.1.0.tgz", - "integrity": "sha512-1lj1EyoSwY/UmTeT/hhPiZTsq+vK9D+8FAJ/53iK5jT1otkG9rJTixSKdjmTieEvdfES+sKbbTptzaQJhnacjA==", - "requires": { - "component-event": "^0.2.1", - "domify": "^1.4.1", - "min-dash": "^4.0.0" - } - } - } - }, - "feelin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/feelin/-/feelin-3.0.1.tgz", - "integrity": "sha512-aYXH3UYkM2eopg3scgNRNEo/ecwizKH6qTqkEu5nSLMMlMgfhLDhWrLl7ChG5iHspO9o4Q2YSP1o4wW8q0L2Qw==", - "requires": { - "@lezer/lr": "^1.3.9", - "lezer-feel": "^1.2.5", - "luxon": "^3.1.0" - } - }, - "file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "requires": { - "flat-cache": "^4.0.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "find-babel-config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.0.0.tgz", - "integrity": "sha512-dOKT7jvF3hGzlW60Gc3ONox/0rRZ/tz7WCil0bqA1In/3I8f1BctpXahRnEKDySZqci7u+dqq93sZST9fOJpFw==", - "dev": true, - "requires": { - "json5": "^2.1.1", - "path-exists": "^4.0.0" - }, - "dependencies": { - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", - "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", - "dev": true, - "requires": { - "common-path-prefix": "^3.0.0", - "pkg-dir": "^7.0.0" - } - }, - "find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "requires": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - } - }, - "flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "focus-trap": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", - "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", - "requires": { - "tabbable": "^6.2.0" - } - }, - "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "requires": { - "is-callable": "^1.1.3" - } - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - } - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true - }, - "function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - } - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "globby": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", - "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", - "dev": true, - "requires": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "requires": { - "es-define-property": "^1.0.0" - } - }, - "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.3" - } - }, - "hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "dev": true, - "requires": { - "function-bind": "^1.1.2" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "htm": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz", - "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==" - }, - "html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", - "dev": true - }, - "html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "requires": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - } - }, - "html-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", - "dev": true, - "requires": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "inherits-browser": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/inherits-browser/-/inherits-browser-0.1.0.tgz", - "integrity": "sha512-CJHHvW3jQ6q7lzsXPpapLdMx5hDpSF3FSh45pwsj6bKxJJ8Nl8v43i5yXnr3BdfOimGHKyniewQtnAIp3vyJJw==" - }, - "internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "requires": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - } - }, - "interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true - }, - "ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", - "dev": true - }, - "is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - } - }, - "is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true - }, - "is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "requires": { - "hasown": "^2.0.0" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "requires": { - "is-docker": "^3.0.0" - } - }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true - }, - "is-network-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.0.1.tgz", - "integrity": "sha512-OwQXkwBJeESyhFw+OumbJVD58BFBJJI5OM5S1+eyrDKlgDZPX2XNT5gXS56GSD3NPbbwUuMlR1Q71SRp5SobuQ==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "requires": { - "call-bind": "^1.0.7" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "requires": { - "which-typed-array": "^1.1.14" - } - }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "requires": { - "is-inside-container": "^1.0.0" - } - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - }, - "iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "requires": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "requires": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - } - }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "lang-feel": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lang-feel/-/lang-feel-2.0.0.tgz", - "integrity": "sha512-cMD6EIhb7vyXLs4kXmaphfZZNr5SkbRxmkfsZUjUJzOV5YxyKBF73VI/8fC3GDUifzs0lVo2DruVszk5igrddg==", - "requires": { - "@codemirror/autocomplete": "^6.9.1", - "@codemirror/language": "^6.9.1", - "@codemirror/state": "^6.2.1", - "@codemirror/view": "^6.21.0", - "@lezer/common": "^1.1.2", - "lezer-feel": "^1.2.0" - } - }, - "language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true - }, - "language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "requires": { - "language-subtag-registry": "^0.3.20" - } - }, - "launch-editor": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", - "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", - "dev": true, - "requires": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lezer-feel": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/lezer-feel/-/lezer-feel-1.2.6.tgz", - "integrity": "sha512-SkTqHThCVZYWhVXy6xh79ULDYPLcWMw0XNcY4ZIr+b5jXTsGDIMxNFZe7oNXNBBZizH045jG3vgfM6t/59pvcw==", - "requires": { - "@lezer/highlight": "^1.2.0", - "@lezer/lr": "^1.4.0" - } - }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true - }, - "locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "requires": { - "p-locate": "^6.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "luxon": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", - "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true - }, - "memfs": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.7.7.tgz", - "integrity": "sha512-x9qc6k88J/VVwnfTkJV8pRRswJ2156Rc4w5rciRqKceFDZ0y1MqsNL9pkg5sE0GOcDzZYbonreALhaHzg1siFw==", - "dev": true, - "requires": { - "tslib": "^2.0.0" - } - }, - "memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "min-dash": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.2.1.tgz", - "integrity": "sha512-to+unsToePnm7cUeR9TrMzFlETHd/UXmU+ELTRfWZj5XGT41KF6X3L233o3E/GdEs3sk2Tbw/lOLD1avmWkg8A==" - }, - "min-dom": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/min-dom/-/min-dom-5.0.0.tgz", - "integrity": "sha512-eqZlSlxmCje0Q1B4sR2RUuh5DOE8FyYLPo35xuJabHBrlzEcG/DFg09TT2tIWRVB3w/6ZgCBkVIPpcOiD66BxQ==", - "requires": { - "domify": "^2.0.0", - "min-dash": "^4.2.1" - }, - "dependencies": { - "domify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/domify/-/domify-2.0.0.tgz", - "integrity": "sha512-rmvrrmWQPD/X1A/nPBfIVg4r05792QdG9Z4Prk6oQG0F9zBMDkr0GKAdds1wjb2dq1rTz/ywc4ZxpZbgz0tttg==" - } - } - }, - "mini-css-extract-plugin": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz", - "integrity": "sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA==", - "dev": true, - "requires": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, - "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true - }, - "npm-run-all2": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-6.1.2.tgz", - "integrity": "sha512-WwwnS8Ft+RpXve6T2EIEVpFLSqN+ORHRvgNk3H9N62SZXjmzKoRhMFg3I17TK3oMaAEr+XFbRirWS2Fn3BCPSg==", - "dev": true, - "requires": { - "ansi-styles": "^6.2.1", - "cross-spawn": "^7.0.3", - "memorystream": "^0.3.1", - "minimatch": "^9.0.0", - "pidtree": "^0.6.0", - "read-package-json-fast": "^3.0.2", - "shell-quote": "^1.7.3" - }, - "dependencies": { - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true - }, - "object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-refs": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-refs/-/object-refs-0.4.0.tgz", - "integrity": "sha512-6kJqKWryKZmtte6QYvouas0/EIJKPI1/MMIuRsiBlNuhIMfqYTggzX2F1AJ2+cDs288xyi9GL7FyasHINR98BQ==" - }, - "object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" - } - }, - "object.hasown": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", - "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", - "dev": true, - "requires": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/open/-/open-10.0.4.tgz", - "integrity": "sha512-oujJ/FFr7ra6/7gJuQ4ZJJ8Gf2VHM0J3J/W7IvH++zaqEzacWVxzK++NiVY5NLHTTj7u/jNH5H3Ei9biL31Lng==", - "dev": true, - "requires": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "requires": { - "yocto-queue": "^1.0.0" - } - }, - "p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "requires": { - "p-limit": "^4.0.0" - } - }, - "p-retry": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", - "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", - "dev": true, - "requires": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true - }, - "path-intersection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-intersection/-/path-intersection-3.0.0.tgz", - "integrity": "sha512-Rdnfb33F9+qadWe3ZyzDpw3KSXQhsK1MByL44QzSDIQtMAujd0zFx9f+kt4SaQp1JOoXl5pl5K28EoEuAEgarA==" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", - "dev": true, - "requires": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true - } - } - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true - }, - "pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", - "dev": true, - "requires": { - "find-up": "^6.3.0" - } - }, - "pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true - } - } - }, - "possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true - }, - "postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", - "dev": true, - "requires": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-selector-parser": { - "version": "6.0.15", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", - "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "preact": { - "version": "10.19.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.3.tgz", - "integrity": "sha512-nHHTeFVBTHRGxJXKkKu5hT8C/YWBkPso4/Gad6xuj5dbptt9iF9NZr9pHbPhBrnT2klheu7mHTxTZ/LjwJiEiQ==" - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "requires": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - } - } - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - } - } - }, - "react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "dependencies": { - "json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "requires": { - "resolve": "^1.20.0" - } - }, - "reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - } - }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dev": true, - "requires": { - "regenerate": "^1.4.2" - } - }, - "regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, - "requires": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - } - }, - "regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, - "requires": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - } - }, - "regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true - } - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true - }, - "renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "reselect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", - "dev": true - }, - "resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dev": true, - "requires": { - "glob": "^10.3.7" - }, - "dependencies": { - "glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" - } - }, - "minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "dev": true - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "requires": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "requires": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dev": true, - "requires": { - "define-data-property": "^1.1.2", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" - } - }, - "set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "requires": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - } - } - }, - "string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" - } - }, - "string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "style-mod": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", - "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "terser": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", - "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "tiny-svg": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tiny-svg/-/tiny-svg-4.0.0.tgz", - "integrity": "sha512-r5fvsVXJ6BvLzEmAVF3gJusimBveGJJ25rtwTxW9FqgGsEP/gYgiKzEEqekmm27gkW6BEp4rfruvhz9n+3CVSw==" - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true - }, - "tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - } - }, - "typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - } - }, - "typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - } - }, - "typed-array-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", - "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - } - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true - }, - "unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true - }, - "w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" - }, - "watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "webpack": { - "version": "5.91.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", - "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.16.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "webpack-cli": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", - "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", - "colorette": "^2.0.14", - "commander": "^10.0.1", - "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true - } - } - }, - "webpack-dev-middleware": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.1.1.tgz", - "integrity": "sha512-NmRVq4AvRQs66dFWyDR4GsFDJggtSi2Yn38MXLk0nffgF9n/AIP4TFBg2TQKYaRAN4sHuKOTiz9BnNCENDLEVA==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^4.6.0", - "mime-types": "^2.1.31", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - } - }, - "webpack-dev-server": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", - "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.13", - "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", - "@types/serve-index": "^1.9.4", - "@types/serve-static": "^1.15.5", - "@types/sockjs": "^0.3.36", - "@types/ws": "^8.5.10", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.2.1", - "chokidar": "^3.6.0", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.4.0", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", - "open": "^10.0.3", - "p-retry": "^6.2.0", - "rimraf": "^5.0.5", - "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.1.0", - "ws": "^8.16.0" - } - }, - "webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "requires": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - } - }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" - } - }, - "wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "requires": {} - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true - } - } -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/package.json b/laokou-cloud/laokou-seata-saga-statemachine-designer/package.json deleted file mode 100644 index 57c902bfa5..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/package.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "name": "seata-saga-statemachine-designer", - "version": "3.0.0", - "description": "A visual graph designer for Seata Saga StateMachine", - "scripts": { - "start": "webpack-dev-server --open --mode development", - "build": "webpack --mode production" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/apache/incubator-seata.git" - }, - "keywords": [ - "seata", - "saga", - "diagram-js" - ], - "author": { - "name": "Seata Community", - "email": "dev@seata.apache.org" - }, - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/apache/incubator-seata/issues" - }, - "homepage": "https://seata.apache.org/", - "peerDependencies": { - "react": "^16.3.0 || ^18.0.0" - }, - "dependencies": { - "@bpmn-io/properties-panel": "^3.8.0", - "bpmn-font": "^0.12.1", - "diagram-js": "^14.0.0", - "diagram-js-grid": "^1.0.0", - "inherits-browser": "^0.1.0", - "min-dash": "^4.1.1", - "min-dom": "^5.0.0", - "tiny-svg": "^4.0.0" - }, - "devDependencies": { - "@babel/core": "^7.23.0", - "@babel/eslint-parser": "^7.22.15", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-react-jsx": "^7.22.15", - "@babel/plugin-transform-runtime": "^7.22.15", - "@babel/preset-env": "^7.22.20", - "@babel/preset-react": "^7.22.15", - "babel-loader": "^9.1.3", - "babel-plugin-module-resolver": "^5.0.0", - "copy-webpack-plugin": "^12.0.0", - "css-loader": "^7.0.0", - "eslint": "^9.0.0", - "eslint-config-airbnb": "^19.0.4", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "html-webpack-plugin": "^5.5.3", - "mini-css-extract-plugin": "^2.7.6", - "npm-run-all2": "^6.0.0", - "webpack": "^5.1.0", - "webpack-cli": "^5.0.0", - "webpack-dev-server": "^5.0.0" - } -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/public/banner.png b/laokou-cloud/laokou-seata-saga-statemachine-designer/public/banner.png deleted file mode 100644 index c0e4590641d9fb047314831e21d66bb5495ff595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21024 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 diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/public/favicon.ico b/laokou-cloud/laokou-seata-saga-statemachine-designer/public/favicon.ico deleted file mode 100644 index a11777cc471a4344702741ab1c8a588998b1311a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/public/logo.jpeg b/laokou-cloud/laokou-seata-saga-statemachine-designer/public/logo.jpeg deleted file mode 100644 index 2cdb3f9b97f96dc0c70c7191b1a3889941761d94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3692 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 diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/public/robots.txt b/laokou-cloud/laokou-seata-saga-statemachine-designer/public/robots.txt deleted file mode 100644 index e9e57dc4d4..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/public/test.json b/laokou-cloud/laokou-seata-saga-statemachine-designer/public/test.json deleted file mode 100644 index e5344c938e..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/public/test.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "Name": "StateMachine", - "Comment": "This state machine is modeled by designer tools.", - "Version": "0.0.1", - "StartState": "ServiceTask-nrzlrnz", - "style": { - "bounds": { - "x": 200, - "y": 200, - "width": 36, - "height": 36 - } - }, - "edge": { - "style": { - "waypoints": [ - { - "original": { - "x": 236, - "y": 218 - }, - "x": 236, - "y": 218 - }, - { - "x": 290, - "y": 218 - }, - { - "original": { - "x": 310, - "y": 218 - }, - "x": 310, - "y": 218 - } - ], - "target": "ServiceTask-nrzlrnz" - }, - "type": "Transition" - }, - "States": { - "ServiceTask-nrzlrnz": { - "Type": "ServiceTask", - "Name": "ServiceTask-nrzlrnz", - "Input": [ - "$.[a]" - ], - "Output": { - "fooResult": "$.#root" - }, - "ServiceName": "DemoService", - "ServiceMethod": "foo", - "Next": "Succeed-pevcj3r", - "style": { - "bounds": { - "x": 310, - "y": 178, - "width": 100, - "height": 80 - } - }, - "edge": { - "Succeed-pevcj3r": { - "style": { - "waypoints": [ - { - "original": { - "x": 410, - "y": 218 - }, - "x": 410, - "y": 218 - }, - { - "x": 462, - "y": 218 - }, - { - "original": { - "x": 482, - "y": 218 - }, - "x": 482, - "y": 218 - } - ], - "source": "ServiceTask-nrzlrnz", - "target": "Succeed-pevcj3r" - }, - "type": "Transition" - } - } - }, - "Succeed-pevcj3r": { - "Type": "Succeed", - "Name": "Succeed-pevcj3r", - "style": { - "bounds": { - "x": 482, - "y": 200, - "width": 36, - "height": 36 - } - } - } - } -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/Editor.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/Editor.js deleted file mode 100644 index 2f1d153c87..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/Editor.js +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import inherits from 'inherits-browser'; -import { domify, query } from 'min-dom'; -import { innerSVG } from 'tiny-svg'; -import Diagram from 'diagram-js'; - -import AlignElementsModule from 'diagram-js/lib/features/align-elements'; -import AttachSupport from 'diagram-js/lib/features/attach-support'; -import AutoScrollModule from 'diagram-js/lib/features/auto-scroll'; -import BendpointsModule from 'diagram-js/lib/features/bendpoints'; -import ConnectModule from 'diagram-js/lib/features/connect'; -import ContextPadModule from 'diagram-js/lib/features/context-pad'; -import ConnectPreviewModule from 'diagram-js/lib/features/connection-preview'; -import CreateModule from 'diagram-js/lib/features/create'; -import EditorActionsModule from 'diagram-js/lib/features/editor-actions'; -import GridSnappingModule from 'diagram-js/lib/features/grid-snapping'; -import KeyboardModule from 'diagram-js/lib/features/keyboard'; -import KeyboardMoveModule from 'diagram-js/lib/navigation/keyboard-move'; -import KeyboardMoveSelectionModule from 'diagram-js/lib/features/keyboard-move-selection'; -import LassoToolModule from 'diagram-js/lib/features/lasso-tool'; -import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'; -import MoveModule from 'diagram-js/lib/features/move'; -import OutlineModule from 'diagram-js/lib/features/outline'; -import PaletteModule from 'diagram-js/lib/features/palette'; -import ResizeModule from 'diagram-js/lib/features/resize'; -import RulesModule from 'diagram-js/lib/features/rules'; -import SelectionModule from 'diagram-js/lib/features/selection'; -import SnappingModule from 'diagram-js/lib/features/snapping'; -import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll'; - -import GridModule from 'diagram-js-grid'; - -import Layout from './layout'; -import Modeling from './modeling'; -import Providers from './providers'; -import Render from './render'; - -import 'diagram-js/assets/diagram-js.css'; -import '@bpmn-io/properties-panel/assets/properties-panel.css'; -import 'bpmn-font/dist/css/bpmn.css'; -import './index.css'; - -/** - * Seata Saga Designer editor constructor - * - * @param { { container: Element, additionalModules?: Array } } options - * - * @return {Diagram} - */ -export default function Editor(options) { - this.container = this.createContainer(); - this.init(this.container, options); -} - -// Make Editor inherit from diagram-js/Diagram -inherits(Editor, Diagram); - -// Add modules for the Editor -Editor.prototype.modules = [ - // Customized modules - Layout, - Modeling, - Providers, - Render, - - // Built-in modules - AlignElementsModule, - AttachSupport, - AutoScrollModule, - BendpointsModule, - ConnectModule, - ConnectPreviewModule, - ContextPadModule, - CreateModule, - GridModule, - GridSnappingModule, - EditorActionsModule, - KeyboardModule, - KeyboardMoveModule, - KeyboardMoveSelectionModule, - LassoToolModule, - MoveCanvasModule, - MoveModule, - OutlineModule, - PaletteModule, - ResizeModule, - RulesModule, - SelectionModule, - SnappingModule, - ZoomScrollModule, -]; - -/** - * Create a container to mount - * @returns {HTMLElement} - */ -Editor.prototype.createContainer = function () { - return domify( - '
    ', - ); -}; - -/** - * A utility function to expose the event bus - */ -Editor.prototype.emit = function (type, event) { - return this.get('eventBus').fire(type, event); -}; - -/** - * Detach the editor from the actual container - */ -Editor.prototype.detach = function () { - const { container } = this; - const { parentNode } = container; - - if (!parentNode) { - return; - } - - this.emit('detach', {}); - - parentNode.removeChild(container); -}; - -/** - * Attach the editor to a specific container - */ -Editor.prototype.attachTo = function (parentNode) { - if (!parentNode) { - throw new Error('parentNode required'); - } - - // ensure we detach from the - // previous, old parent - this.detach(); - - parentNode.appendChild(this.container); - - this.emit('attach', {}); - - this.get('canvas').resized(); -}; - -/** - * Initialize the editor - */ -Editor.prototype.init = function (container, options) { - const { - additionalModules, - canvas, - ...additionalOptions - } = options; - - const baseModules = options.modules || this.modules; - - const modules = [ - ...baseModules, - ...(additionalModules || []), - ]; - - const diagramOptions = { - ...additionalOptions, - canvas: { - ...canvas, - container, - }, - modules, - }; - - // invoke diagram constructor - Diagram.call(this, diagramOptions); - - if (options && options.container) { - this.attachTo(options.container); - } - - this.get('eventBus').fire('editor.attached'); -}; - -/** - * Clear the editor, removing all contents. - */ -Editor.prototype.clear = function () { - Diagram.prototype.clear.call(this); -}; - -/** - * Import diagram from JSON definitions. - */ -Editor.prototype.import = function (definitions) { - this.clear(); - this.get('sagaImporter').import(definitions); -}; - -/** - * Export diagram to JSON definitions - */ -Editor.prototype.export = function () { - return this.get('sagaExporter').export(); -}; - -/** - * Export diagram to a SVG figure - */ -Editor.prototype.exportSvg = function () { - const eventBus = this.get('eventBus'); - eventBus.fire('saveSVG.start'); - - let svg; - let - err; - - try { - const canvas = this.get('canvas'); - - const contentNode = canvas.getActiveLayer(); - // eslint-disable-next-line no-underscore-dangle - const defsNode = query('defs', canvas._svg); - - const contents = innerSVG(contentNode); - const defs = defsNode ? `${innerSVG(defsNode)}` : ''; - - const bbox = contentNode.getBBox(); - - svg = '\n' - + '\n' - + '\n' - + '${ - defs}${contents - }`; - } catch (e) { - err = e; - } - - eventBus.fire('saveSVG.done', { - error: err, - svg, - }); - - if (err) { - throw err; - } - - return svg; -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/ExportControl.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/ExportControl.js deleted file mode 100644 index 25e2218665..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/ExportControl.js +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React from '@bpmn-io/properties-panel/preact/compat'; - -export default function ExportControl(props) { - const { editor } = props; - - function download(data, name, type) { - const a = document.createElement('a'); - - a.setAttribute( - 'href', - `data:text/${type};charset=UTF-8,${encodeURIComponent(data)}`, - ); - a.setAttribute('target', '_blank'); - a.setAttribute('dataTrack', `diagram:download-${type}`); - a.setAttribute('download', `${name}.${type}`); - - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - } - - return ( -
      -
    • - -
    • -
    • -
    • - -
    • -
    - ); -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/ImportControl.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/ImportControl.js deleted file mode 100644 index 650b48ddae..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/ImportControl.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React from '@bpmn-io/properties-panel/preact/compat'; - -export default function ImportControl(props) { - const { editor } = props; - const inputRef = React.useRef(null); - - function onOpenFileChange(e) { - const localFile = e.target.files[0]; - if (localFile) { - const reader = new FileReader(); - let data = ''; - reader.readAsText(localFile); - reader.onload = (event) => { - data = JSON.parse(event.target.result); - editor.import(data); - }; - } - } - - return ( -
      -
    • - - -
    • -
    - ); -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/index.js deleted file mode 100644 index 160326434a..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/control/index.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { domify } from 'min-dom'; -import React from '@bpmn-io/properties-panel/preact/compat'; -import ImportControl from './ImportControl'; -import ExportControl from './ExportControl'; - -export default function (editor) { - const container = domify('
    '); - const canvas = editor.get('canvas'); - canvas._container.appendChild(container); - - React.render( -
    - - -
    , - container, - ); -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.css b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.css deleted file mode 100644 index d77041ef7d..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.css +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -body { - margin: 0 auto; -} - -.palette-icon-lasso-tool { - background: url('data:image/svg+xml,%3Csvg%0A%20%20%20%20%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20%0A%20%20%20%20%20fill%3D%22none%22%0A%20%20%20%20%20stroke%3D%22%23000%22%0A%20%20%20%20%20stroke-width%3D%221.5%22%0A%20%20%20%20%20width%3D%2246%22%0A%20%20%20%20%20height%3D%2246%22%3E%0A%20%20%3Crect%20x%3D%2210%22%20y%3D%2210%22%20width%3D%2216%22%20height%3D%2216%22%20stroke-dasharray%3D%225%2C%205%22%20%2F%3E%0A%20%20%3Cline%20x1%3D%2216%22%20y1%3D%2226%22%20x2%3D%2236%22%20y2%3D%2226%22%20stroke%3D%22black%22%20%2F%3E%0A%20%20%3Cline%20x1%3D%2226%22%20y1%3D%2216%22%20x2%3D%2226%22%20y2%3D%2236%22%20stroke%3D%22black%22%20%2F%3E%0A%3C%2Fsvg%3E'); -} - -.palette-icon-create-shape { - background: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%20width%3D%2246%22%20height%3D%2246%22%3E%3Crect%20x%3D%2210%22%20y%3D%2213%22%20width%3D%2226%22%20height%3D%2220%22%2F%3E%3C%2Fsvg%3E'); -} - -.palette-icon-create-frame { - background: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%20stroke-dasharray%3D%224%22%20width%3D%2246%22%20height%3D%2246%22%3E%3Crect%20x%3D%2210%22%20y%3D%2213%22%20width%3D%2226%22%20height%3D%2220%22%2F%3E%3C%2Fsvg%3E'); -} - -.context-pad-icon-remove { - background: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%20width%3D%2246%22%20height%3D%2246%22%3E%3Cline%20x1%3D%225%22%20y1%3D%225%22%20x2%3D%2215%22%20y2%3D%2215%22%2F%3E%3Cline%20x1%3D%2215%22%20y1%3D%225%22%20x2%3D%225%22%20y2%3D%2215%22%2F%3E%3C%2Fsvg%3E') !important; -} - -.context-pad-icon-connect { - background: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%20width%3D%2246%22%20height%3D%2246%22%3E%3Cline%20x1%3D%2215%22%20y1%3D%225%22%20x2%3D%225%22%20y2%3D%2215%22%2F%3E%3C%2Fsvg%3E') !important; -} - -.io-control { - background: #FAFAFA; - border-radius: 2px; - border: solid 1px #E0E0E0; - padding: 5px; -} - -.io-control-list { - display: inline-block; - list-style: none; - padding: 5px; - margin: 0 10px 0 0; -} - -.io-control-list li { - display: inline-block; -} - -.io-control-list li + li { - margin-left: 10px; -} - -.io-control-list button { - padding: 0; - outline: none; - cursor: pointer; - font-size: 22px; - line-height: 26px; - color: #555555; - background: none; - border: none; -} - -.io-control .vr { - height: 15px; - border-right: solid 1px #DDD; -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.html b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.html deleted file mode 100644 index c6808cdd5d..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - Seata Saga Designer - - - -
    -
    - -
    -
    -
    - - - diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.js deleted file mode 100644 index 8bd1cefeb4..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/index.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import PropertiesPanel from './properties-panel'; -import PropertiesProvider from './properties-panel/provider'; -import Editor from './Editor'; -import control from './control'; -import { randomString } from './utils'; - -const editor = new Editor({ - container: document.querySelector('#canvas'), - keyboard: { bindTo: document }, - propertiesPanel: { parent: '#properties' }, - // Add properties panel as additional modules - additionalModules: [ - PropertiesPanel, - PropertiesProvider, - ], -}); - -control(editor); - -editor.import({ - Name: `StateMachine-${randomString()}`, - Comment: 'This state machine is modeled by designer tools.', - Version: '0.0.1', - style: { - bounds: { - x: 200, - y: 200, - width: 36, - height: 36, - }, - }, -}); diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/Layouter.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/Layouter.js deleted file mode 100644 index 1691d64086..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/Layouter.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import inherits from 'inherits-browser'; - -import BaseLayouter from 'diagram-js/lib/layout/BaseLayouter'; - -import { - getMid, getOrientation, -} from 'diagram-js/lib/layout/LayoutUtil'; - -import { assign } from 'min-dash'; - -const ADDITIONAL_WAYPOINT_DISTANCE = 20; - -export default function Layouter(connectionDocking) { - this.connectionDocking = connectionDocking; -} - -inherits(Layouter, BaseLayouter); - -Layouter.$inject = ['connectionDocking']; - -function getConnectionDocking(point, shape) { - return point ? (point.original || point) : getMid(shape); -} - -Layouter.prototype.layoutConnection = function (connection, hints) { - const { connectionDocking } = this; - - if (!hints) { - hints = {}; - } - - const source = hints.source || connection.source; - const target = hints.target || connection.target; - let waypoints = hints.waypoints || connection.waypoints || []; - let { connectionStart } = hints; - let { connectionEnd } = hints; - const orientation = getOrientation(source, target); - - if (!connectionStart) { - connectionStart = getConnectionDocking(waypoints[0], source); - } - - if (!connectionEnd) { - connectionEnd = getConnectionDocking(waypoints[waypoints.length - 1], target); - } - waypoints = [connectionStart, connectionEnd]; - - const croppedWaypoints = connectionDocking.getCroppedWaypoints( - assign({}, connection, { - waypoints, - }), - source, - target, - ); - - connectionEnd = croppedWaypoints.pop(); - - const additionalWaypoint = { - x: connectionEnd.x, - y: connectionEnd.y, - }; - - if (orientation.includes('bottom')) { - additionalWaypoint.y += ADDITIONAL_WAYPOINT_DISTANCE; - } else if (orientation.includes('top')) { - additionalWaypoint.y -= ADDITIONAL_WAYPOINT_DISTANCE; - } else if (orientation.includes('right')) { - additionalWaypoint.x += ADDITIONAL_WAYPOINT_DISTANCE; - } else { - additionalWaypoint.x -= ADDITIONAL_WAYPOINT_DISTANCE; - } - - waypoints = croppedWaypoints.concat([additionalWaypoint, connectionEnd]); - - return waypoints; -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/AttachCatchBehavior.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/AttachCatchBehavior.js deleted file mode 100644 index 4d28b44b22..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/AttachCatchBehavior.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import inherits from 'inherits-browser'; - -import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; -import { is } from '../../utils'; - -const LOW_PRIORITY = 500; - -function shouldUpdate(shape, host) { - return is(shape, 'Catch') && host; -} - -export default function AttachEventBehavior(injector) { - injector.invoke(CommandInterceptor, this); - this.postExecuted('element.updateAttachment', LOW_PRIORITY, ({ context }) => { - const { shape, oldHost, newHost } = context; - - if (shouldUpdate(shape, newHost)) { - delete oldHost?.businessObject.Catch; - newHost.businessObject.Catch = shape.businessObject; - } - }); -} - -inherits(AttachEventBehavior, CommandInterceptor); - -AttachEventBehavior.$inject = ['injector']; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/LayoutConnectionBehavior.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/LayoutConnectionBehavior.js deleted file mode 100644 index c792491411..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/LayoutConnectionBehavior.js +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import inherits from 'inherits-browser'; - -import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; - -import { - asTRBL, - getMid, - getOrientation, -} from 'diagram-js/lib/layout/LayoutUtil'; - -import { - assign, - forEach, -} from 'min-dash'; - -const LOW_PRIORITY = 500; - -// helpers ////////// - -function getConnectionHints(source, target, orientation) { - const connectionStart = getMid(source); - const connectionEnd = getMid(target); - - if (orientation.includes('bottom')) { - connectionStart.y = source.y; - connectionEnd.y = target.y + target.height; - } else if (orientation.includes('top')) { - connectionStart.y = source.y + source.height; - connectionEnd.y = target.y; - } else if (orientation.includes('right')) { - connectionStart.x = source.x; - connectionEnd.x = target.x + target.width; - } else { - connectionStart.x = source.x + source.width; - connectionEnd.x = target.x; - } - - return { - connectionStart, - connectionEnd, - }; -} - -/** - * Get connections start and end based on number of connections and - * orientation. - * - * @param {Array} connections - * @param {djs.model.Shape} target - * @param {string} orientation - * - * @returns {Array} - */ -function getConnectionsStartEnd(connections, target, orientation) { - return connections.map( - (connection, index) => { - const { source } = connection; - const sourceMid = getMid(source); - const sourceTrbl = asTRBL(source); - const targetTrbl = asTRBL(target); - - const { length } = connections; - - if (orientation.includes('bottom')) { - return { - start: { - x: sourceMid.x, - y: sourceTrbl.top, - }, - end: { - x: targetTrbl.left + (target.width / (length + 1)) * (index + 1), - y: targetTrbl.bottom, - }, - }; - } if (orientation.includes('top')) { - return { - start: { - x: sourceMid.x, - y: sourceTrbl.bottom, - }, - end: { - x: targetTrbl.left + (target.width / (length + 1)) * (index + 1), - y: targetTrbl.top, - }, - }; - } if (orientation.includes('right')) { - return { - start: { - x: sourceTrbl.left, - y: sourceMid.y, - }, - end: { - x: targetTrbl.right, - y: targetTrbl.top + (target.height / (length + 1)) * (index + 1), - }, - }; - } - return { - start: { - x: sourceTrbl.right, - y: sourceMid.y, - }, - end: { - x: targetTrbl.left, - y: targetTrbl.top + (target.height / (length + 1)) * (index + 1), - }, - }; - }, - ); -} - -/** - * Get connections by orientation. - * - * @param {djs.model.shape} target - * @param {Array} connections - * - * @returns {Object} - */ -function getConnectionByOrientation(target, connections) { - const incomingConnectionsByOrientation = {}; - - connections.forEach((incoming) => { - const orientation = getOrientation(incoming.source, target).split('-').shift(); - - if (!incomingConnectionsByOrientation[orientation]) { - incomingConnectionsByOrientation[orientation] = []; - } - - incomingConnectionsByOrientation[orientation].push(incoming); - }); - - return incomingConnectionsByOrientation; -} - -function isSameOrientation(orientationA, orientationB) { - return orientationA - && orientationB - && orientationA.split('-').shift() === orientationB.split('-').shift(); -} - -function sortConnections(connections, orientation) { - let axis; - - if (orientation.includes('top') || orientation.includes('bottom')) { - axis = 'x'; - } else { - axis = 'y'; - } - - return connections.sort((a, b) => { - return getMid(a.source)[axis] - getMid(b.source)[axis]; - }); -} - -export default function LayoutConnectionBehavior(injector, layouter, modeling) { - injector.invoke(CommandInterceptor, this); - - // specify connection start and end on connection create - this.preExecute([ - 'connection.create', - 'connection.reconnect', - ], (context) => { - const source = context.newSource || context.source; - const target = context.newTarget || context.target; - - const orientation = getOrientation(source, target); - - if (!context.hints) { - context.hints = {}; - } - - assign(context.hints, getConnectionHints(source, target, orientation)); - }, true); - - /** - * Update incoming connections. - * - * @param {djs.model.Shape} target - * @param {Array} [connection] - * @param {string} [orientation] - */ - function updateConnections(target, connection, orientation) { - // (1) get connection - if (!connection) { - connection = target.incoming; - } - - let incomingConnectionsByOrientation = {}; - - // (2) get connections per orientation - if (orientation) { - incomingConnectionsByOrientation[orientation] = connection; - } else { - incomingConnectionsByOrientation = getConnectionByOrientation(target, connection); - } - - // (3) update connections per orientation - forEach( - incomingConnectionsByOrientation, - (connections, ot) => { - // (3.1) sort connections - connections = sortConnections(connections, ot); - - // (3.2) get new connection start and end - const connectionStartEnd = getConnectionsStartEnd(connections, target, ot); - - // (3.3) update connections - connections.forEach((conn, index) => { - const connectionStart = connectionStartEnd[index].start; - const connectionEnd = connectionStartEnd[index].end; - - const waypoints = layouter.layoutConnection(conn, { - connectionStart, - connectionEnd, - }); - - modeling.updateWaypoints(conn, waypoints); - }); - }, - ); - } - - // update connections on connection create and delete - // update connections of new target on connection reconnect - this.postExecuted([ - 'connection.create', - 'connection.delete', - 'connection.reconnect', - ], (context) => { - const { connection } = context; - const source = connection.source || context.source; - const target = connection.target || context.target; - - const orientation = getOrientation(source, target); - - // update all connections with same orientation - const connections = target.incoming.filter((incoming) => { - const incomingOrientation = getOrientation(incoming.source, incoming.target); - - return isSameOrientation(incomingOrientation, orientation); - }); - - if (!connections.length) { - return; - } - - updateConnections(target, connections, orientation); - }, true); - - // update connections of old target on connection reconnect - this.preExecute('connection.reconnect', (context) => { - const { connection } = context; - const { source } = connection; - const { target } = connection; - - const orientation = getOrientation(source, target); - - // update all connections with same orientation except reconnected - const connections = target.incoming.filter((incoming) => { - const incomingOrientation = getOrientation(incoming.source, incoming.target); - - return incoming !== connection - && isSameOrientation(incomingOrientation, orientation); - }); - - if (!connections.length) { - return; - } - - updateConnections(target, connections, orientation); - }, true); - - // update connections on elements move - this.postExecuted('elements.move', LOW_PRIORITY, (context) => { - const { shapes } = context; - const { closure } = context; - const { enclosedConnections } = closure; - - shapes.forEach((shape) => { - // (1) update incoming connections - const incomingConnections = shape.incoming.filter((incoming) => { - return !enclosedConnections[incoming.id]; - }); - - if (incomingConnections.length) { - updateConnections(shape, incomingConnections); - } - - // (2) update outgoing connections - shape.outgoing.forEach((outgoing) => { - if (enclosedConnections[outgoing.id]) { - return; - } - - updateConnections(outgoing.target); - }); - }); - }, true); -} - -LayoutConnectionBehavior.$inject = [ - 'injector', - 'layouter', - 'modeling', - 'rules', -]; - -inherits(LayoutConnectionBehavior, CommandInterceptor); diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/LayoutUpdateBehavior.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/LayoutUpdateBehavior.js deleted file mode 100644 index 223decd7ca..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/LayoutUpdateBehavior.js +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { assign } from 'min-dash'; - -import inherits from 'inherits-browser'; - -import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; - -export default function LayoutUpdateBehavior(injector) { - injector.invoke(CommandInterceptor, this); - const self = this; - - function updateBounds(context) { - const { shape } = context; - self.updateBounds(shape); - } - - this.executed(['shape.create', 'shape.move', 'shape.resize'], updateBounds, true); - this.reverted(['shape.create', 'shape.move', 'shape.resize'], updateBounds, true); - - function updateConnectionWaypoints(context) { - self.updateConnectionWaypoints(context); - } - - this.executed([ - 'connection.create', - 'connection.layout', - 'connection.move', - 'connection.updateWaypoints', - ], updateConnectionWaypoints, true); - - this.reverted([ - 'connection.create', - 'connection.layout', - 'connection.move', - 'connection.updateWaypoints', - ], updateConnectionWaypoints, true); - - function updateConnectionSourceTarget(context) { - self.updateConnectionSourceTarget(context); - } - - this.executed(['connection.create', 'connection.reconnect'], updateConnectionSourceTarget, true); - this.reverted(['connection.create', 'connection.reconnect'], updateConnectionSourceTarget, true); -} - -inherits(LayoutUpdateBehavior, CommandInterceptor); - -LayoutUpdateBehavior.$inject = ['injector']; - -LayoutUpdateBehavior.prototype.updateBounds = function (shape) { - const { businessObject } = shape; - const { bounds } = businessObject.style; - - // update bounds - assign(bounds, { - x: shape.x, - y: shape.y, - width: shape.width, - height: shape.height, - }); -}; - -LayoutUpdateBehavior.prototype.updateConnectionWaypoints = function (context) { - const { connection } = context; - const { businessObject } = connection; - const { waypoints } = businessObject.style; - - assign(waypoints, connection.waypoints); -}; - -LayoutUpdateBehavior.prototype.updateConnectionSourceTarget = function (context) { - const { connection } = context; - const { businessObject } = connection; - const { source, newSource, target, newTarget } = context; - - businessObject.style.source = newSource || source; - businessObject.style.target = newTarget || target; -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/ReplaceConnectionBehavior.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/ReplaceConnectionBehavior.js deleted file mode 100644 index 2a6fbce50d..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/ReplaceConnectionBehavior.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import inherits from 'inherits-browser'; - -import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; - -export default function ReplaceConnectionBehavior(injector, modeling, rules) { - injector.invoke(CommandInterceptor, this); - - this.preExecute('connection.reconnect', (context) => { - const { connection } = context; - const source = context.newSource || connection.source; - const target = context.newTarget || connection.target; - const waypoints = connection.waypoints.slice(); - - const allowed = rules.allowed('connection.reconnect', { - connection, - source, - target, - }); - - if (!allowed || allowed.type === connection.type) { - return; - } - - context.connection = modeling.connect(source, target, { - type: allowed.type, - waypoints, - }); - - modeling.removeConnection(connection); - }, true); -} - -inherits(ReplaceConnectionBehavior, CommandInterceptor); - -ReplaceConnectionBehavior.$inject = [ - 'injector', - 'modeling', - 'rules', -]; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/index.js deleted file mode 100644 index 1da9796d2e..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/behavior/index.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import AttachCatchBehavior from './AttachCatchBehavior'; -import LayoutConnectionBehavior from './LayoutConnectionBehavior'; -import ReplaceConnectionBehavior from './ReplaceConnectionBehavior'; -import LayoutUpdateBehavior from './LayoutUpdateBehavior'; - -export default { - __init__: [ - 'attachCatchBehavior', - 'layoutConnectionBehavior', - 'replaceConnectionBehavior', - 'layoutUpdateBehavior', - ], - attachCatchBehavior: ['type', AttachCatchBehavior], - layoutConnectionBehavior: ['type', LayoutConnectionBehavior], - replaceConnectionBehavior: ['type', ReplaceConnectionBehavior], - layoutUpdateBehavior: ['type', LayoutUpdateBehavior], -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/index.js deleted file mode 100644 index 479e172c2f..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/layout/index.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import CroppingConnectionDocking from 'diagram-js/lib/layout/CroppingConnectionDocking'; -import Layouter from './Layouter'; -import Behavior from './behavior'; - -export default { - __depends__: [Behavior], - layouter: ['type', Layouter], - connectionDocking: ['type', CroppingConnectionDocking], -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/ElementFactory.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/ElementFactory.js deleted file mode 100644 index 584cfcaa33..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/ElementFactory.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { assign } from 'min-dash'; - -import inherits from 'inherits-browser'; - -import BaseElementFactory from 'diagram-js/lib/core/ElementFactory'; - -/** - * A drd-aware factory for diagram-js shapes - */ -export default function ElementFactory(sagaFactory) { - BaseElementFactory.call(this); - - this.sagaFactory = sagaFactory; -} - -inherits(ElementFactory, BaseElementFactory); - -ElementFactory.$inject = ['sagaFactory']; - -ElementFactory.prototype.baseCreate = BaseElementFactory.prototype.create; - -ElementFactory.prototype.create = function (elementType, attrs) { - const { sagaFactory } = this; - - attrs = attrs || {}; - - let { businessObject } = attrs; - - if (!businessObject) { - if (!attrs.type) { - throw new Error('no shape type specified'); - } - - businessObject = sagaFactory.create(attrs.type); - } - - const size = sagaFactory.getDefaultSize(businessObject); - - attrs = assign({ businessObject }, size, attrs); - - return this.baseCreate(elementType, attrs); -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/Modeling.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/Modeling.js deleted file mode 100644 index aacb0e6b67..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/Modeling.js +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import inherits from 'inherits-browser'; - -import { keys } from 'min-dash'; -import BaseModeling from 'diagram-js/lib/features/modeling/Modeling'; -import { getProperties, setProperties } from '../utils'; - -function UpdatePropertiesHandler() { -} - -/** - * @param {Object} context - * @param {djs.model.Base} context.element the element to update - * @param {Object} context.properties a list of properties to set on the element's businessObject. - * - * @return {Array} the updated element - */ -UpdatePropertiesHandler.prototype.execute = function (context) { - const { element } = context; - const changed = [element]; - - if (!element) { - throw new Error('element required'); - } - - const { businessObject } = element; - const { properties } = context; - const oldProperties = context.oldProperties || getProperties(businessObject, keys(properties)); - - const { override } = context; - // update properties - setProperties(businessObject, properties, override); - - // store old values - context.oldProperties = oldProperties; - context.changed = changed; - - // indicate changed on objects affected by the update - return changed; -}; - -/** - * @param {Object} context - * - * @return {djs.model.Base} the updated element - */ -UpdatePropertiesHandler.prototype.revert = function (context) { - const { element } = context; - const { oldProperties } = context; - const { businessObject } = element; - - // update properties - setProperties(businessObject, oldProperties); - return context.changed; -}; - -export default function Modeling( - canvas, - commandStack, - rules, - injector, -) { - this.canvas = canvas; - this.commandStack = commandStack; - this.rules = rules; - - injector.invoke(BaseModeling, this); -} - -inherits(Modeling, BaseModeling); - -Modeling.$inject = [ - 'canvas', - 'commandStack', - 'rules', - 'injector', -]; - -Modeling.prototype.connect = function (source, target, attrs, hints) { - const { rules } = this; - const rootElement = this.canvas.getRootElement(); - - if (!attrs) { - attrs = rules.canConnect(source, target); - } - - return this.createConnection(source, target, attrs, rootElement, hints); -}; - -Modeling.prototype.getHandlers = function () { - const handlers = BaseModeling.prototype.getHandlers.call(this); - - handlers['element.updateProperties'] = UpdatePropertiesHandler; - - return handlers; -}; - -Modeling.prototype.updateProperties = function (element, properties, override) { - this.commandStack.execute('element.updateProperties', { - element, - properties, - override, - }); -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaExporter.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaExporter.js deleted file mode 100644 index 6cd0ec838a..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaExporter.js +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { assign } from 'min-dash'; -import StateMachine from '../spec/StateMachine'; -import StartState from '../spec/StartState'; -import State from '../spec/State'; -import Edge from '../spec/style/Edge'; - -export default function SagaExporter(elementRegistry) { - this.elementRegistry = elementRegistry; -} -SagaExporter.$inject = ['elementRegistry']; - -SagaExporter.prototype.parseRoot = function (definitions, root) { - const { businessObject } = root; - assign(definitions, businessObject.exportJson()); -}; - -SagaExporter.prototype.parseState = function (definitions, node) { - const { businessObject } = node; - const elementJson = businessObject.exportJson(); - - const { Name } = businessObject; - definitions.States[Name] = elementJson; -}; - -SagaExporter.prototype.parseEdge = function (definitions, edge) { - const { businessObject } = edge; - const elementJson = businessObject.exportJson(); - const { source, target } = elementJson.style; - if (!source) { - if (definitions.StartState) { - throw new Error(`Two or more start states, ${target} and ${definitions.StartState}`); - } else { - definitions.StartState = target; - if (definitions.edge === undefined) { - definitions.edge = {}; - } - assign(definitions.edge, elementJson); - } - } else { - const stateRef = definitions.States[source]; - switch (businessObject.Type) { - case 'ChoiceEntry': - if (!stateRef.Choices) { - stateRef.Choices = []; - } - stateRef.Choices.push({ - Expression: businessObject.Expression, - Next: target, - }); - if (businessObject.Default) { - stateRef.Default = target; - } - stateRef.edge = assign(stateRef.edge || {}, { [target]: elementJson }); - break; - case 'ExceptionMatch': - stateRef.Catch.push({ - Exceptions: businessObject.Exceptions, - Next: target, - }); - stateRef.catch = assign(stateRef.catch || {}, { edge: { [target]: elementJson } }); - break; - case 'Compensation': - stateRef.CompensateState = target; - stateRef.edge = assign(stateRef.edge || {}, { [target]: elementJson }); - break; - case 'Transition': - default: - stateRef.Next = target; - stateRef.edge = assign(stateRef.edge || {}, { [target]: elementJson }); - } - } -}; - -SagaExporter.prototype.export = function () { - const definitions = {}; - - const elements = this.elementRegistry.getAll(); - const root = elements.filter(({ businessObject }) => businessObject instanceof StateMachine)[0]; - const start = elements.filter(({ businessObject }) => businessObject instanceof StartState)[0]; - const states = elements.filter(({ businessObject }) => businessObject instanceof State); - const edges = elements.filter(({ businessObject }) => businessObject instanceof Edge); - - this.parseRoot(definitions, root); - this.parseRoot(definitions, start); - assign(definitions, { States: {} }); - states.forEach((state) => this.parseState(definitions, state)); - edges.forEach((edge) => this.parseEdge(definitions, edge)); - - return definitions; -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaFactory.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaFactory.js deleted file mode 100644 index 7db11c7cc6..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaFactory.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import Transition from '../spec/Transition'; -import StateMachine from '../spec/StateMachine'; -import ServiceTask from '../spec/ServiceTask'; -import StartState from '../spec/StartState'; -import ScriptTask from '../spec/ScriptTask'; -import Choice from '../spec/Choice'; -import ChoiceEntry from '../spec/ChoiceEntry'; -import Succeed from '../spec/Succeed'; -import Fail from '../spec/Fail'; -import Catch from '../spec/Catch'; -import ExceptionMatch from '../spec/ExceptionMatch'; -import CompensationTrigger from '../spec/CompensationTrigger'; -import SubStateMachine from '../spec/SubStateMachine'; -import Compensation from '../spec/Compensation'; - -export default function SagaFactory() { - const typeToSpec = new Map(); - typeToSpec.set('Transition', Transition); - typeToSpec.set('StartState', StartState); - typeToSpec.set('StateMachine', StateMachine); - typeToSpec.set('ServiceTask', ServiceTask); - typeToSpec.set('ScriptTask', ScriptTask); - typeToSpec.set('Choice', Choice); - typeToSpec.set('ChoiceEntry', ChoiceEntry); - typeToSpec.set('Succeed', Succeed); - typeToSpec.set('Fail', Fail); - typeToSpec.set('Catch', Catch); - typeToSpec.set('ExceptionMatch', ExceptionMatch); - typeToSpec.set('CompensationTrigger', CompensationTrigger); - typeToSpec.set('SubStateMachine', SubStateMachine); - typeToSpec.set('Compensation', Compensation); - this.typeToSpec = typeToSpec; -} - -SagaFactory.prototype.create = function (type) { - const Spec = this.typeToSpec.get(type); - return new Spec(); -}; - -SagaFactory.prototype.getDefaultSize = function (semantic) { - if (semantic.DEFAULT_SIZE) { - return semantic.DEFAULT_SIZE; - } - - return { - width: 100, - height: 80, - }; -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaImporter.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaImporter.js deleted file mode 100644 index 4234136edf..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaImporter.js +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - assign, forEach, - map, -} from 'min-dash'; - -// helper ///// -function elementData(semantic, attrs) { - return assign({ - type: semantic.Type, - businessObject: semantic, - }, attrs); -} - -function collectWaypoints(edge) { - const { waypoints } = edge; - - if (waypoints) { - return map(waypoints, (waypoint) => { - const position = { x: waypoint.x, y: waypoint.y }; - - return assign({ original: position }, position); - }); - } - return null; -} - -export default function SagaImporter( - sagaFactory, - eventBus, - canvas, - elementFactory, - elementRegistry, - modeling, -) { - this.sagaFactory = sagaFactory; - this.eventBus = eventBus; - this.canvas = canvas; - this.elementRegistry = elementRegistry; - this.elementFactory = elementFactory; - this.modeling = modeling; -} - -SagaImporter.$inject = [ - 'sagaFactory', - 'eventBus', - 'canvas', - 'elementFactory', - 'elementRegistry', - 'modeling', -]; - -SagaImporter.prototype.import = function (definitions) { - let error = []; - const warnings = []; - - this.eventBus.fire('import.start', { definitions }); - - try { - const root = this.sagaFactory.create('StateMachine'); - root.importJson(definitions); - this.root(root); - - // Add start state - let start = this.sagaFactory.create('StartState'); - start.importJson(definitions); - start = this.add(start); - - const edges = []; - const catches = []; - forEach(definitions.States, (semantic) => { - const state = this.sagaFactory.create(semantic.Type); - state.importJson(semantic); - const host = this.add(state); - if (semantic.edge) { - edges.push(...Object.values(semantic.edge)); - } - if (semantic.catch) { - const node = this.sagaFactory.create('Catch'); - node.importJson(semantic.catch); - const source = this.add(node); - if (semantic.catch.edge) { - semantic.Catch.forEach((exceptionMatch) => { - if (semantic.catch.edge[exceptionMatch.Next]) { - semantic.catch.edge[exceptionMatch.Next].Exceptions = exceptionMatch.Exceptions; - } - }); - } - this.modeling.updateAttachment(source, host); - catches.push({ source, edges: Object.values(semantic.catch.edge) }); - } - }); - - // Add start edge - if (definitions.edge) { - const startEdge = this.sagaFactory.create('Transition'); - startEdge.importJson(definitions.edge); - this.add(startEdge, { source: start }); - } - - forEach(edges, (semantic) => { - const transition = this.sagaFactory.create(semantic.Type); - transition.importJson(semantic); - this.add(transition); - }); - - forEach(catches, (oneCatch) => { - const { source, edges: exceptionMatches } = oneCatch; - forEach(exceptionMatches, (semantic) => { - const exceptionMatch = this.sagaFactory.create(semantic.Type); - exceptionMatch.importJson(semantic); - this.add(exceptionMatch, { source }); - }); - }); - } catch (e) { - error = e; - console.error(error); - } - - this.eventBus.fire('import.done', { error, warnings }); -}; - -SagaImporter.prototype.root = function (semantic) { - const element = this.elementFactory.createRoot(elementData(semantic)); - - this.canvas.setRootElement(element); - - return element; -}; - -/** - * Add drd element (semantic) to the canvas. - */ -SagaImporter.prototype.add = function (semantic, attrs = {}) { - const { elementFactory } = this; - const { canvas } = this; - const { style } = semantic; - - let element; let waypoints; let source; let target; let elementDefinition; let - bounds; - - if (style.Type === 'Node') { - bounds = style.bounds; - - elementDefinition = elementData(semantic, { - x: Math.round(bounds.x), - y: Math.round(bounds.y), - width: Math.round(bounds.width), - height: Math.round(bounds.height), - }); - element = elementFactory.createShape(elementDefinition); - - canvas.addShape(element); - } else if (style.Type === 'Edge') { - waypoints = collectWaypoints(style); - - source = attrs.source || this.getSource(semantic); - target = this.getTarget(semantic); - semantic.style.source = source; - semantic.style.target = target; - - if (source && target) { - elementDefinition = elementData(semantic, { - source, - target, - waypoints, - }); - // console.log(elementDefinition); - - element = elementFactory.createConnection(elementDefinition); - - canvas.addConnection(element); - } - } else { - throw new Error(`unknown di for element ${semantic.id}`); - } - - return element; -}; - -SagaImporter.prototype.getSource = function (semantic) { - return this.getShape(semantic.style.source); -}; - -SagaImporter.prototype.getTarget = function (semantic) { - return this.getShape(semantic.style.target); -}; - -SagaImporter.prototype.getShape = function (name) { - return this.elementRegistry.find((element) => element.businessObject.Name === name); -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaRules.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaRules.js deleted file mode 100644 index 53f00a15ce..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/SagaRules.js +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import inherits from 'inherits-browser'; - -import RuleProvider from 'diagram-js/lib/features/rules/RuleProvider'; -import { getOrientation } from 'diagram-js/lib/layout/LayoutUtil'; -import { is } from '../utils'; - -export default function SagaRules(injector) { - injector.invoke(RuleProvider, this); -} - -inherits(SagaRules, RuleProvider); - -SagaRules.$inject = ['injector']; - -function canConnect(source, target) { - if (!source || !target) { - return null; - } - - if (target.parent !== source.parent || source === target) { - return false; - } - - if (is(source, 'Task') && is(target, 'Task') && target.businessObject.IsForCompensation) { - return { type: 'Compensation' }; - } - - if (is(source, 'Choice')) { - return { type: 'ChoiceEntry' }; - } - - if (is(source, 'Catch')) { - return { type: 'ExceptionMatch' }; - } - - return { type: 'Transition' }; -} - -function canCreate(shapes, target) { - let shapeList = shapes; - if (!Array.isArray(shapes)) { - shapeList = [shapes]; - } - - const invalid = shapeList.map((shape) => { - if (is(shape, 'Catch')) { - return false; - } - - if (!target) { - return true; - } - - return target.parent === shape.target; - }).filter((valid) => !valid).length; - - return !invalid; -} - -function canAttach(shapes, target, position) { - if (Array.isArray(shapes)) { - if (shapes.length > 1) { - return false; - } - } - const shape = shapes[0] || shapes; - - if (is(shape, 'Catch')) { - if (position && getOrientation(position, target, -15) === 'intersect') { - return false; - } - - if (is(target, 'Task')) { - return 'attach'; - } - } - - return false; -} - -function canMove(shapes, target, position) { - const shapeSet = new Set(shapes); - // Exclude all catches with parents included - const filtered = shapes.filter((shape) => !(is(shape, 'Catch') && shapeSet.has(shape.parent))); - return !target || canAttach(filtered, target, position) || canCreate(filtered, target); -} - -SagaRules.prototype.init = function () { - this.addRule('shape.create', (context) => { - const { target } = context; - const { shape } = context; - - return canCreate(shape, target); - }); - - this.addRule('shape.attach', (context) => { - const { shape, target, position } = context; - - return canAttach(shape, target, position); - }); - - this.addRule('elements.move', (context) => { - const { shapes, target, position } = context; - - return canMove(shapes, target, position); - }); - - this.addRule('connection.create', (context) => { - const { source } = context; - const { target } = context; - - return canConnect(source, target); - }); - - this.addRule('connection.reconnect', (context) => { - const { source } = context; - const { target } = context; - - return canConnect(source, target); - }); -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/index.js deleted file mode 100644 index f733a5ffc9..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/modeling/index.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import DiagramCommand from 'diagram-js/lib/command'; -import DiagramChangeSupport from 'diagram-js/lib/features/change-support'; -import DiagramRulesModule from 'diagram-js/lib/features/rules'; -import DiagramSelection from 'diagram-js/lib/features/selection'; - -import ElementFactory from './ElementFactory'; -import Modeling from './Modeling'; -import SagaFactory from './SagaFactory'; -import SagaRules from './SagaRules'; -import SagaExporter from './SagaExporter'; -import SagaImporter from './SagaImporter'; - -export default { - __init__: [ - 'modeling', - 'sagaImporter', - 'sagaExporter', - 'sagaFactory', - 'sagaRules', - ], - __depends__: [ - DiagramCommand, - DiagramChangeSupport, - DiagramRulesModule, - DiagramSelection, - ], - elementFactory: ['type', ElementFactory], - modeling: ['type', Modeling], - sagaImporter: ['type', SagaImporter], - sagaExporter: ['type', SagaExporter], - sagaFactory: ['type', SagaFactory], - sagaRules: ['type', SagaRules], -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PanelHeaderProvider.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PanelHeaderProvider.js deleted file mode 100644 index 8c888df452..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PanelHeaderProvider.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export default { - - getElementLabel: (element) => { - return element.name; - }, - - getElementIcon: (element) => { - // eslint-disable-next-line react/react-in-jsx-scope - return () => ; - }, - - getTypeLabel: (element) => { - return element?.type?.replace(/(\B[A-Z])/g, ' $1').replace(/(\bNon Interrupting)/g, '($1)'); - }, -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PanelPlaceholderProvider.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PanelPlaceholderProvider.js deleted file mode 100644 index eaaf2d8412..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PanelPlaceholderProvider.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export default { - - getEmpty: () => { - return { - text: 'Select an element to edit its properties.', - - icon: null, - }; - }, - - getMultiple: () => { - return { - text: 'Multiple elements are selected. Select a single element to edit its properties.', - - icon: null, - }; - }, -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanel.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanel.js deleted file mode 100644 index aaf0e578a5..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanel.js +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - useState, - useMemo, - useEffect, -} from '@bpmn-io/properties-panel/preact/hooks'; - -import { - find, - isArray, - reduce, -} from 'min-dash'; - -import { PropertiesPanel as BasePropertiesPanel } from '@bpmn-io/properties-panel'; - -import PropertiesPanelContext from './PropertiesPanelContext'; - -import PanelHeaderProvider from './PanelHeaderProvider'; -import PanelPlaceholderProvider from './PanelPlaceholderProvider'; - -// helpers ////////////////////////// - -function isImplicitRoot(element) { - // Backwards compatibility for diagram-js<7.4.0, see https://github.com/bpmn-io/bpmn-properties-panel/pull/102 - return element && (element.isImplicit || element.id === '__implicitroot'); -} - -function findElement(elements, element) { - return find(elements, (e) => e === element); -} - -function elementExists(element, elementRegistry) { - return element && elementRegistry.get(element.id); -} - -/** - * @param {Object} props - * @param {djs.model.Base|Array} [props.element] - * @param {Injector} props.injector - * @param { (djs.model.BaseSpec) => Array } props.getProviders - * @param {Object} props.layoutConfig - * @param {Object} props.descriptionConfig - */ -export default function PropertiesPanel(props) { - const { - element, - injector, - getProviders, - layoutConfig, - descriptionConfig, - } = props; - - const canvas = injector.get('canvas'); - const elementRegistry = injector.get('elementRegistry'); - const eventBus = injector.get('eventBus'); - - const [state, setState] = useState({ - selectedElement: element, - }); - - const { selectedElement } = state; - - /** - * @param {djs.model.Base | Array} e - */ - const update = (e) => { - if (!e) { - return; - } - - const newSelectedElement = e; - - setState({ - ...state, - selectedElement: newSelectedElement, - }); - - // notify interested parties on property panel updates - eventBus.fire('propertiesPanel.updated', { - element: newSelectedElement, - }); - }; - - // (2) react on element changes - - // (2a) selection changed - useEffect(() => { - const onSelectionChanged = (e) => { - const { newSelection = [] } = e; - - if (newSelection.length > 1) { - return update(newSelection); - } - - const newElement = newSelection[0]; - - const rootElement = canvas.getRootElement(); - - if (isImplicitRoot(rootElement)) { - // TODO - } - - update(newElement || rootElement); - return null; - }; - - eventBus.on('selection.changed', onSelectionChanged); - - return () => { - eventBus.off('selection.changed', onSelectionChanged); - }; - }, []); - - // (2b) selected element changed - useEffect(() => { - const onElementsChanged = (e) => { - const { elements } = e; - - const updatedElement = findElement(elements, selectedElement); - - if (updatedElement && elementExists(updatedElement, elementRegistry)) { - update(updatedElement); - } - }; - - eventBus.on('elements.changed', onElementsChanged); - - return () => { - eventBus.off('elements.changed', onElementsChanged); - }; - }, [selectedElement]); - - // (2c) root element changed - useEffect(() => { - const onRootAdded = (e) => { - const { element: root } = e; - - if (isImplicitRoot(root)) { - return; - } - - update(root); - }; - - eventBus.on('root.added', onRootAdded); - - return () => { - eventBus.off('root.added', onRootAdded); - }; - }, [selectedElement]); - - // (2d) provided entries changed - useEffect(() => { - const onProvidersChanged = () => { - update(selectedElement); - }; - - eventBus.on('propertiesPanel.providersChanged', onProvidersChanged); - - return () => { - eventBus.off('propertiesPanel.providersChanged', onProvidersChanged); - }; - }, [selectedElement]); - - // (3) create properties panel context - const propertiesPanelContext = useMemo(() => ({ - selectedElement, - injector, - getService(type, strict) { return injector.get(type, strict); }, - }), [selectedElement, injector]); - - // (4) retrieve groups for selected element - const providers = getProviders(selectedElement); - - const groups = useMemo(() => { - return reduce(providers, (g, provider) => { - // do not collect groups for multi element state - if (isArray(selectedElement)) { - return []; - } - const updater = provider.getGroups(selectedElement); - - return updater(g); - }, []); - }, [providers, selectedElement]); - - // (5) notify layout changes - const onLayoutChanged = (layout) => { - eventBus.fire('propertiesPanel.layoutChanged', { - layout, - }); - }; - - // (6) notify description changes - const onDescriptionLoaded = (description) => { - eventBus.fire('propertiesPanel.descriptionLoaded', { - description, - }); - }; - - return ( - - - - ); -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanelContext.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanelContext.js deleted file mode 100644 index e423b355f2..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanelContext.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - createContext, -} from '@bpmn-io/properties-panel/preact'; - -const PropertiesPanelContext = createContext({ - selectedElement: null, - injector: null, - getService: () => null, -}); - -export default PropertiesPanelContext; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanelRenderer.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanelRenderer.js deleted file mode 100644 index 9174e3d69f..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/PropertiesPanelRenderer.js +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - isUndo, - isRedo, -} from 'diagram-js/lib/features/keyboard/KeyboardUtil'; - -import { - render, -} from '@bpmn-io/properties-panel/preact'; - -import { - domify, - query as domQuery, - event as domEvent, -} from 'min-dom'; -import PropertiesPanel from './PropertiesPanel'; - -// helpers /////////////////////// - -function isImplicitRoot(element) { - // Backwards compatibility for diagram-js<7.4.0, see https://github.com/bpmn-io/bpmn-properties-panel/pull/102 - return element && (element.isImplicit || element.id === '__implicitroot'); -} - -/** - * Setup keyboard bindings (undo, redo) on the given container. - * - * @param {Element} container - * @param {EventBus} eventBus - * @param {CommandStack} commandStack - */ -function setupKeyboard(container, eventBus, commandStack) { - function cancel(event) { - event.preventDefault(); - event.stopPropagation(); - } - - function handleKeys(event) { - if (isUndo(event)) { - commandStack.undo(); - - return cancel(event); - } - - if (isRedo(event)) { - commandStack.redo(); - - return cancel(event); - } - - return null; - } - - eventBus.on('keyboard.bind', () => { - domEvent.bind(container, 'keydown', handleKeys); - }); - - eventBus.on('keyboard.unbind', () => { - domEvent.unbind(container, 'keydown', handleKeys); - }); -} - -const DEFAULT_PRIORITY = 1000; - -export default class PropertiesPanelRenderer { - constructor(config, injector, eventBus) { - const { - parent, - layout: layoutConfig, - description: descriptionConfig, - } = config || {}; - - this.eventBus = eventBus; - this.injector = injector; - this.layoutConfig = layoutConfig; - this.descriptionConfig = descriptionConfig; - - this.container = domify( - '
    ', - ); - - const commandStack = injector.get('commandStack', false); - - if (commandStack) { - setupKeyboard(this.container, eventBus, commandStack); - } - eventBus.on('diagram.destroy', () => { - this.detach(); - }); - - eventBus.on('import.done', (event) => { - const { element } = event; - - if (parent) { - this.attachTo(parent); - } - this.render(element); - }); - - eventBus.on('detach', () => { - this.detach(); - }); - } - - /** - * Attach the properties panel to a parent node. - * - * @param {HTMLElement} container - */ - attachTo(container) { - if (!container) { - throw new Error('container required'); - } - - // unwrap jQuery if provided - if (container.get && container.constructor.prototype.jquery) { - container = container.get(0); - } - - if (typeof container === 'string') { - container = domQuery(container); - } - - // (1) detach from old parent - this.detach(); - - // (2) append to parent container - container.appendChild(this.container); - - // (3) notify interested parties - this.eventBus.fire('propertiesPanel.attach'); - } - - /** - * Detach the properties panel from its parent node. - */ - detach() { - const { parentNode } = this.container; - - if (parentNode) { - parentNode.removeChild(this.container); - - this.eventBus.fire('propertiesPanel.detach'); - } - } - - /** - * Register a new properties provider to the properties panel. - * - * @param {Number} [priority] - * @param {PropertiesProvider} provider - */ - registerProvider(priority, provider) { - if (!provider) { - provider = priority; - priority = DEFAULT_PRIORITY; - } - - if (typeof provider.getGroups !== 'function') { - console.error( - 'Properties provider does not implement #getGroups(element) API', - ); - - return; - } - - this.eventBus.on('propertiesPanel.getProviders', priority, (event) => { - event.providers.push(provider); - }); - - this.eventBus.fire('propertiesPanel.providersChanged'); - } - - getProviders() { - const event = this.eventBus.createEvent({ - type: 'propertiesPanel.getProviders', - providers: [], - }); - - this.eventBus.fire(event); - - return event.providers; - } - - render(element) { - const canvas = this.injector.get('canvas'); - - if (!element) { - element = canvas.getRootElement(); - } - - if (isImplicitRoot(element)) { - return; - } - - render( - , - this.container, - ); - - this.eventBus.fire('propertiesPanel.rendered'); - } - - destroy() { - if (this.container) { - render(null, this.container); - - this.eventBus.fire('propertiesPanel.destroyed'); - } - } -} - -PropertiesPanelRenderer.$inject = ['config.propertiesPanel', 'injector', 'eventBus']; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/index.js deleted file mode 100644 index 60d9bf789a..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/index.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { DebounceInputModule, FeelPopupModule } from '@bpmn-io/properties-panel'; -import PropertiesPanelRenderer from './PropertiesPanelRenderer'; - -export default { - __depends__: [ - DebounceInputModule, - FeelPopupModule, - ], - __init__: ['propertiesPanel'], - propertiesPanel: ['type', PropertiesPanelRenderer], -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/PropertiesProvider.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/PropertiesProvider.js deleted file mode 100644 index aa0471c0b7..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/PropertiesProvider.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Group } from '@bpmn-io/properties-panel'; - -import NameProps from './properties/NameProps'; -import CommentProps from './properties/CommentProps'; -import VersionProps from './properties/VersionProps'; -import StateProps from './properties/StateProps'; -import StyleProps from './properties/StyleProps'; -import { is } from '../../utils'; - -function GeneralGroup(element) { - const entries = [ - ...NameProps({ element }), - ...CommentProps({ element }), - ]; - - if (is(element, 'StateMachine')) { - entries.push(...VersionProps({ element })); - } - - if (is(element, 'Connection') || is(element, 'StartState') || is(element, 'Catch')) { - return null; - } - - return { - id: 'general', - label: 'General', - entries, - component: Group, - }; -} - -function JsonGroup(element) { - const entries = [ - ...StateProps({ element }), - ...StyleProps({ element }), - ]; - - if (is(element, 'Transition') || is(element, 'Compensation') || is(element, 'StartState') || is(element, 'Catch')) { - entries.splice(0, 1); - } - - return { - id: 'json', - label: 'Json Props', - entries, - shouldOpen: true, - component: Group, - }; -} - -function getGroups(element) { - const groups = [ - GeneralGroup(element), - JsonGroup(element), - ]; - - // contract: if a group returns null, it should not be displayed at all - return groups.filter((group) => group !== null); -} - -export default class PropertiesProvider { - constructor(propertiesPanel) { - propertiesPanel.registerProvider(this); - } - - getGroups(element) { - return (groups) => { - return [ - ...groups, - ...getGroups(element), - ]; - }; - } -} - -PropertiesProvider.$inject = ['propertiesPanel']; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/index.js deleted file mode 100644 index cc1f209765..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/index.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import PropertiesProvider from './PropertiesProvider'; - -export default { - __init__: ['propertiesProvider'], - propertiesProvider: ['type', PropertiesProvider], -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/BaseText.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/BaseText.js deleted file mode 100644 index a746a77365..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/BaseText.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - TextFieldEntry, -} from '@bpmn-io/properties-panel'; - -import { useService } from '../../../utils'; - -export default function BaseText(props) { - const { - element, - id, - label, - parameterKey, - ...additionalProps - } = props; - - const debounce = useService('debounceInput'); - const modeling = useService('modeling'); - - const options = { - element, - id, - label, - ...additionalProps, - debounce, - getValue: (e) => { - if (e.businessObject) { - return e.businessObject[parameterKey]; - } - return null; - }, - setValue: (value) => { - modeling.updateProperties(element, { [parameterKey]: value }); - }, - }; - - return TextFieldEntry(options); -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/BaseTextArea.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/BaseTextArea.js deleted file mode 100644 index 57b7e3606c..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/BaseTextArea.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - TextAreaEntry, -} from '@bpmn-io/properties-panel'; - -import { useService } from '../../../utils'; - -export default function BaseTextArea(props) { - const { - element, - id, - label, - parameterKey, - ...additionalProps - } = props; - - const debounce = useService('debounceInput'); - const modeling = useService('modeling'); - - const options = { - element, - id, - label, - ...additionalProps, - debounce, - getValue: (e) => { - if (e.businessObject) { - return e.businessObject[parameterKey]; - } - return null; - }, - setValue: (value) => { - modeling.updateProperties(element, { [parameterKey]: value }); - }, - }; - - return TextAreaEntry(options); -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/CommentProps.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/CommentProps.js deleted file mode 100644 index a806aa1718..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/CommentProps.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - isTextFieldEntryEdited, -} from '@bpmn-io/properties-panel'; -import BaseTextArea from './BaseTextArea'; - -export default function CommentProps(props) { - const { - element, - } = props; - - return [ - { - id: 'comment', - label: 'Comment', - parameterKey: 'Comment', - component: BaseTextArea, - element, - isEdited: isTextFieldEntryEdited, - }, - ]; -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/NameProps.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/NameProps.js deleted file mode 100644 index 3660834f7b..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/NameProps.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - isTextFieldEntryEdited, -} from '@bpmn-io/properties-panel'; - -import BaseText from './BaseText'; - -export default function NameProps(props) { - const { - element, - } = props; - - return [ - { - id: 'name', - label: 'Name', - parameterKey: 'Name', - component: BaseText, - element, - isEdited: isTextFieldEntryEdited, - }, - ]; -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/StateProps.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/StateProps.js deleted file mode 100644 index cf09035501..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/StateProps.js +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - TextAreaEntry, - isTextFieldEntryEdited, CollapsibleEntry, -} from '@bpmn-io/properties-panel'; - -import { assign } from 'min-dash'; -import { useService } from '../../../utils'; - -function State(props) { - const { element } = props; - - const debounce = useService('debounceInput'); - const modeling = useService('modeling'); - - const options = { - component: TextAreaEntry, - element, - id: 'props', - // label: 'Props', - debounce, - autoResize: true, - getValue: (e) => { - const value = assign({}, e.businessObject); - // Exclude style - delete value.style; - // Exclude Catch for Task - delete value.Catch; - return JSON.stringify(value, null, 2); - }, - validate: (value) => { - try { - JSON.parse(value); - } catch (e) { - return e.message; - } - - return null; - }, - setValue: (value, newValidationError) => { - try { - JSON.parse(value); - } catch (e) { - newValidationError = e; - } - if (newValidationError) { - return; - } - const businessObject = JSON.parse(value); - modeling.updateProperties(element, businessObject, true); - }, - }; - - return CollapsibleEntry({ - id: 'collapsible-props', - label: 'Props', - element, - entries: [options], - open: true, - }); -} - -export default function StateProps(props) { - const { - element, - } = props; - - return [ - { - component: State, - element, - isEdited: isTextFieldEntryEdited, - }, - ]; -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/StyleProps.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/StyleProps.js deleted file mode 100644 index d6522e83d9..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/StyleProps.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - TextAreaEntry, - isTextFieldEntryEdited, CollapsibleEntry, -} from '@bpmn-io/properties-panel'; - -import { useService } from '../../../utils'; - -function Style(props) { - const { element } = props; - - const debounce = useService('debounceInput'); - - const options = { - component: TextAreaEntry, - element, - id: 'style', - debounce, - autoResize: true, - disabled: true, - getValue: (e) => { - return JSON.stringify(e.businessObject.style, null, 2); - }, - }; - - return CollapsibleEntry({ - id: 'collapsible-props', - label: 'Style', - element, - entries: [options], - }); -} - -export default function StateProps(props) { - const { - element, - } = props; - - return [ - { - component: Style, - element, - isEdited: isTextFieldEntryEdited, - }, - ]; -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/VersionProps.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/VersionProps.js deleted file mode 100644 index f41a870ca9..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/properties-panel/provider/properties/VersionProps.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; - -import BaseText from './BaseText'; - -export default function VersionProps(props) { - const { - element, - } = props; - - return [ - { - id: 'version', - label: 'Version', - parameterKey: 'Version', - component: BaseText, - element, - isEdited: isTextFieldEntryEdited, - }, - ]; -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/ContextPadProvider.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/ContextPadProvider.js deleted file mode 100644 index 4e8ab26afc..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/ContextPadProvider.js +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - assign, -} from 'min-dash'; - -import { - hasPrimaryModifier, -} from 'diagram-js/lib/util/Mouse'; -import { is } from '../utils'; - -/** - * A provider for DMN elements context pad - */ -export default function ContextPadProvider( - eventBus, - contextPad, - modeling, - elementFactory, - connect, - create, - canvas, - config, - injector, -) { - config = config || {}; - - contextPad.registerProvider(this); - - this.contextPad = contextPad; - this.modeling = modeling; - this.elementFactory = elementFactory; - this.connect = connect; - this.canvas = canvas; - - if (config.autoPlace !== false) { - this.autoPlace = injector.get('autoPlace', false); - } - - eventBus.on('create.end', 250, (event) => { - const { shape } = event.context; - - if (!hasPrimaryModifier(event)) { - return; - } - - const entries = contextPad.getEntries(shape); - - if (entries.replace) { - entries.replace.action.click(event, shape); - } - }); -} - -ContextPadProvider.$inject = [ - 'eventBus', - 'contextPad', - 'modeling', - 'elementFactory', - 'connect', - 'create', - 'canvas', - 'config.contextPad', - 'injector', -]; - -ContextPadProvider.prototype.getContextPadEntries = function (element) { - const { modeling } = this; - const { connect } = this; - - const actions = {}; - - if (element.type === 'label') { - return actions; - } - - const { businessObject } = element; - const { type } = businessObject; - - function startConnect(event, e, autoActivate) { - connect.start(event, e, autoActivate); - } - - function removeElement() { - modeling.removeElements([element]); - } - - assign(actions, { - delete: { - group: 'edit', - className: 'bpmn-icon-trash', - title: 'Remove', - action: { - click: removeElement, - }, - }, - }); - - if (!is(type, 'Connection')) { - assign(actions, { - connect: { - group: 'edit', - className: 'bpmn-icon-connection-multi', - title: 'Connect', - action: { - click: startConnect, - dragstart: startConnect, - }, - }, - }); - } - - return actions; -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/PaletteProvider.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/PaletteProvider.js deleted file mode 100644 index 9558b68c93..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/PaletteProvider.js +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { assign } from 'min-dash'; -import ServiceTask from '../spec/ServiceTask'; -import StartState from '../spec/StartState'; -import ScriptTask from '../spec/ScriptTask'; -import Choice from '../spec/Choice'; -import Succeed from '../spec/Succeed'; -import Fail from '../spec/Fail'; -import Catch from '../spec/Catch'; -import CompensationTrigger from '../spec/CompensationTrigger'; -import SubStateMachine from '../spec/SubStateMachine'; - -const SPEC_LIST = [StartState, ServiceTask, ScriptTask, SubStateMachine, Choice, Succeed, Fail, - Catch, CompensationTrigger]; - -/** - * A palette provider. - */ -export default function PaletteProvider(create, elementFactory, lassoTool, palette) { - this.create = create; - this.elementFactory = elementFactory; - this.lassoTool = lassoTool; - this.palette = palette; - - palette.registerProvider(this); -} - -PaletteProvider.$inject = [ - 'create', - 'elementFactory', - 'lassoTool', - 'palette', -]; - -PaletteProvider.prototype.getPaletteEntries = function () { - const { create } = this; - const { elementFactory } = this; - const { lassoTool } = this; - - function createAction(type, group, className, title, options) { - function createListener(event) { - const shape = elementFactory.createShape(assign({ type }, options)); - create.start(event, shape); - } - - return { - group, - className, - title, - action: { - dragstart: createListener, - click: createListener, - }, - }; - } - - const entries = { - 'lasso-tool': { - group: 'tools', - className: 'palette-icon-lasso-tool', - title: 'Activate Lasso Tool', - action: { - click(event) { - lassoTool.activateSelection(event); - }, - }, - }, - 'tool-separator': { - group: 'tools', - separator: true, - }, - }; - SPEC_LIST.forEach((Spec) => { - const type = Spec.prototype.Type; - entries[`create-${type}`] = createAction(type, 'state', Spec.prototype.THUMBNAIL_CLASS, `Create ${type}`); - }); - return entries; -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/index.js deleted file mode 100644 index eb108aee27..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/providers/index.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import ContextPadProvider from './ContextPadProvider'; -import PaletteProvider from './PaletteProvider'; - -export default { - __init__: [ - 'contextPadProvider', - 'paletteProvider', - ], - contextPadProvider: ['type', ContextPadProvider], - paletteProvider: ['type', PaletteProvider], -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/PathMap.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/PathMap.js deleted file mode 100644 index 36ab8a13c2..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/PathMap.js +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* eslint-disable max-len */ - -// helpers ////////////////////// - -// copied and adjusted from https://github.com/adobe-webplatform/Snap.svg/blob/master/src/svg.js -const tokenRegex = /\{([^{}]+)\}/g; -const objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g; // matches .xxxxx or ["xxxxx"] to run over object properties - -function replacer(all, key, obj) { - let res = obj; - key.replace(objNotationRegex, (_, name, quote, quotedName, isFunc) => { - name = name || quotedName; - if (res) { - if (name in res) { - res = res[name]; - } - if (typeof res === 'function' && isFunc) { - res = res(); - } - } - }); - res = `${res == null || res === obj ? all : res}`; - - return res; -} - -function format(str, obj) { - return String(str).replace(tokenRegex, (all, key) => { - return replacer(all, key, obj); - }); -} - -/** - * Map containing SVG paths needed by BpmnRenderer. - */ -export default function PathMap() { - /** - * Contains a map of path elements - * - *

    Path definition

    - * A parameterized path is defined like this: - *
    -   * 'GATEWAY_PARALLEL': {
    -   *   d: 'm {mx},{my} {e.x0},0 0,{e.x1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
    -          '-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
    -   *   height: 17.5,
    -   *   width:  17.5,
    -   *   heightElements: [2.5, 7.5],
    -   *   widthElements: [2.5, 7.5]
    -   * }
    -   * 
    - *

    It's important to specify a correct height and width for the path as the scaling - * is based on the ratio between the specified height and width in this object and the - * height and width that is set as scale target (Note x,y coordinates will be scaled with - * individual ratios).

    - *

    The 'heightElements' and 'widthElements' array must contain the values that will be scaled. - * The scaling is based on the computed ratios. - * Coordinates on the y axis should be in the heightElement's array, they will be scaled using - * the computed ratio coefficient. - * In the parameterized path the scaled values can be accessed through the 'e' object in {} brackets. - *

      - *
    • The values for the y axis can be accessed in the path string using {e.y0}, {e.y1}, ....
    • - *
    • The values for the x axis can be accessed in the path string using {e.x0}, {e.x1}, ....
    • - *
    - * The numbers x0, x1 respectively y0, y1, ... map to the corresponding array index. - *

    - m1,1 - l 0,55.3 - c 29.8,19.7 48.4,-4.2 67.2,-6.7 - c 12.2,-2.3 19.8,1.6 30.8,6.2 - l 0,-54.6 - z - */ - this.pathMap = { - TASK_TYPE_SERVICE: { - d: 'm {mx},{my} v -1.71335 c 0.352326,-0.0705 0.703932,-0.17838 1.047628,-0.32133 ' - + '0.344416,-0.14465 0.665822,-0.32133 0.966377,-0.52145 l 1.19431,1.18005 1.567487,-1.57688 ' - + '-1.195028,-1.18014 c 0.403376,-0.61394 0.683079,-1.29908 0.825447,-2.01824 l 1.622133,-0.01 ' - + 'v -2.2196 l -1.636514,0.01 c -0.07333,-0.35153 -0.178319,-0.70024 -0.323564,-1.04372 ' - + '-0.145244,-0.34406 -0.321407,-0.6644 -0.522735,-0.96217 l 1.131035,-1.13631 -1.583305,-1.56293 ' - + '-1.129598,1.13589 c -0.614052,-0.40108 -1.302883,-0.68093 -2.022633,-0.82247 l 0.0093,-1.61852 ' - + 'h -2.241173 l 0.0042,1.63124 c -0.353763,0.0736 -0.705369,0.17977 -1.049785,0.32371 -0.344415,0.14437 ' - + '-0.665102,0.32092 -0.9635006,0.52046 l -1.1698628,-1.15823 -1.5667691,1.5792 1.1684265,1.15669 ' - + 'c -0.4026573,0.61283 -0.68308,1.29797 -0.8247287,2.01713 l -1.6588041,0.003 v 2.22174 ' - + 'l 1.6724648,-0.006 c 0.073327,0.35077 0.1797598,0.70243 0.3242851,1.04472 0.1452428,0.34448 ' - + '0.3214064,0.6644 0.5227339,0.96066 l -1.1993431,1.19723 1.5840256,1.56011 1.1964668,-1.19348 ' - + 'c 0.6140517,0.40346 1.3028827,0.68232 2.0233517,0.82331 l 7.19e-4,1.69892 h 2.226848 z ' - + 'm 0.221462,-3.9957 c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' - + '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' - + '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z', - }, - TASK_TYPE_SERVICE_FILL: { - d: 'm {mx},{my} c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' - + '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' - + '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z', - }, - MARKER_COMPENSATION: { - d: 'm {mx},{my} 7,-5 0,10 z m 7.1,-0.3 6.9,-4.7 0,10 -6.9,-4.7 z', - height: 10, - width: 21, - heightElements: [], - widthElements: [], - }, - MARKER_LOOP: { - d: 'm {mx},{my} c 3.526979,0 6.386161,-2.829858 6.386161,-6.320661 0,-3.490806 -2.859182,-6.320661 ' - + '-6.386161,-6.320661 -3.526978,0 -6.38616,2.829855 -6.38616,6.320661 0,1.745402 ' - + '0.714797,3.325567 1.870463,4.469381 0.577834,0.571908 1.265885,1.034728 2.029916,1.35457 ' - + 'l -0.718163,-3.909793 m 0.718163,3.909793 -3.885211,0.802902', - height: 13.9, - width: 13.7, - heightElements: [], - widthElements: [], - }, - MARKER_SUB_PROCESS: { - d: 'm{mx},{my} m 7,2 l 0,10 m -5,-5 l 10,0', - height: 10, - width: 10, - heightElements: [], - widthElements: [], - }, - TASK_TYPE_SCRIPT: { - d: 'm {mx},{my} c 9.966553,-6.27276 -8.000926,-7.91932 2.968968,-14.938 l -8.802728,0 ' - + 'c -10.969894,7.01868 6.997585,8.66524 -2.968967,14.938 z ' - + 'm -7,-12 l 5,0 ' - + 'm -4.5,3 l 4.5,0 ' - + 'm -3,3 l 5,0' - + 'm -4,3 l 5,0', - height: 15, - width: 12.6, - heightElements: [6, 14], - widthElements: [10.5, 21], - }, - GATEWAY_EXCLUSIVE: { - d: 'm {mx},{my} {e.x0},{e.y0} {e.x1},{e.y0} {e.x2},0 {e.x4},{e.y2} ' - + '{e.x4},{e.y1} {e.x2},0 {e.x1},{e.y3} {e.x0},{e.y3} ' - + '{e.x3},0 {e.x5},{e.y1} {e.x5},{e.y2} {e.x3},0 z', - height: 17.5, - width: 17.5, - heightElements: [8.5, 6.5312, -6.5312, -8.5], - widthElements: [6.5, -6.5, 3, -3, 5, -5], - }, - EVENT_ERROR: { - d: 'm {mx},{my} {e.x0},-{e.y0} {e.x1},-{e.y1} {e.x2},{e.y2} {e.x3},-{e.y3} -{e.x4},{e.y4} -{e.x5},-{e.y5} z', - height: 36, - width: 36, - heightElements: [0.023, 8.737, 8.151, 16.564, 10.591, 8.714], - widthElements: [0.085, 6.672, 6.97, 4.273, 5.337, 6.636], - }, - EVENT_COMPENSATION: { - d: 'm {mx},{my} {e.x0},-{e.y0} 0,{e.y1} z m {e.x1},-{e.y2} {e.x2},-{e.y3} 0,{e.y1} -{e.x2},-{e.y3} z', - height: 36, - width: 36, - heightElements: [6.5, 13, 0.4, 6.1], - widthElements: [9, 9.3, 8.7], - }, - }; - - this.getRawPath = function getRawPath(pathId) { - return this.pathMap[pathId].d; - }; - - /** - * Scales the path to the given height and width. - *

    Use case

    - *

    Use case is to scale the content of elements (event, gateways) based - * on the element bounding box's size. - *

    - *

    Why not transform

    - *

    Scaling a path with transform() will also scale the stroke and IE does not support - * the option 'non-scaling-stroke' to prevent this. - * Also there are use cases where only some parts of a path should be - * scaled.

    - * - * @param {string} pathId The ID of the path. - * @param {Object} param

    - * Example param object scales the path to 60% size of the container (data.width, data.height). - *

    -   *   {
    -   *     xScaleFactor: 0.6,
    -   *     yScaleFactor:0.6,
    -   *     containerWidth: data.width,
    -   *     containerHeight: data.height,
    -   *     position: {
    -   *       mx: 0.46,
    -   *       my: 0.2,
    -   *     }
    -   *   }
    -   *   
    - *
      - *
    • targetpathwidth = xScaleFactor * containerWidth
    • - *
    • targetpathheight = yScaleFactor * containerHeight
    • - *
    • Position is used to set the starting coordinate of the path. M is computed: - *
        - *
      • position.x * containerWidth
      • - *
      • position.y * containerHeight
      • - *
      - * Center of the container
       position: {
      -   *       mx: 0.5,
      -   *       my: 0.5,
      -   *     }
      - * Upper left corner of the container - *
       position: {
      -   *       mx: 0.0,
      -   *       my: 0.0,
      -   *     }
      - *
    • - *
    - *

    - * - */ - this.getScaledPath = function getScaledPath(pathId, param) { - const rawPath = this.pathMap[pathId]; - - // positioning - // compute the start point of the path - let mx; let - my; - - if (param.abspos) { - mx = param.abspos.x; - my = param.abspos.y; - } else { - mx = param.containerWidth * param.position.mx; - my = param.containerHeight * param.position.my; - } - - const coordinates = {}; // map for the scaled coordinates - if (param.position) { - // path - const heightRatio = (param.containerHeight / rawPath.height) * param.yScaleFactor; - const widthRatio = (param.containerWidth / rawPath.width) * param.xScaleFactor; - - // Apply height ratio - for (let heightIndex = 0; heightIndex < rawPath.heightElements.length; heightIndex++) { - coordinates[`y${heightIndex}`] = rawPath.heightElements[heightIndex] * heightRatio; - } - - // Apply width ratio - for (let widthIndex = 0; widthIndex < rawPath.widthElements.length; widthIndex++) { - coordinates[`x${widthIndex}`] = rawPath.widthElements[widthIndex] * widthRatio; - } - } - - // Apply value to raw path - const path = format(rawPath.d, { - mx, - my, - e: coordinates, - }); - return path; - }; -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/Renderer.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/Renderer.js deleted file mode 100644 index fcf6884ede..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/Renderer.js +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import inherits from 'inherits-browser'; - -import { assign, forEach, isObject } from 'min-dash'; - -import { attr as domAttr, query as domQuery } from 'min-dom'; - -import { append as svgAppend, attr as svgAttr, create as svgCreate } from 'tiny-svg'; - -import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer'; - -import { createLine } from 'diagram-js/lib/util/RenderUtil'; -import { translate } from 'diagram-js/lib/util/SvgTransformUtil'; - -const BLACK = 'hsl(225, 10%, 15%)'; -const TASK_BORDER_RADIUS = 10; -const DEFAULT_FILL_OPACITY = 0.95; - -// helper functions ////////////////////// - -function getSemantic(element) { - return element.businessObject; -} - -function colorEscape(str) { - // only allow characters and numbers - return str.replace(/[^0-9a-zA-z]+/g, '_'); -} - -function getStrokeColor(element, defaultColor) { - return defaultColor; -} - -function getFillColor(element, defaultColor) { - return defaultColor; -} - -function getLabelColor(element, defaultColor, defaultStrokeColor) { - return defaultColor || getStrokeColor(element, defaultStrokeColor); -} - -export default function Renderer(config, eventBus, pathMap, styles, textRenderer, canvas) { - BaseRenderer.call(this, eventBus); - - const { computeStyle } = styles; - - const markers = {}; - - const defaultFillColor = (config && config.defaultFillColor) || 'white'; - const defaultStrokeColor = (config && config.defaultStrokeColor) || BLACK; - const defaultLabelColor = (config && config.defaultLabelColor); - - function shapeStyle(attrs) { - return styles.computeStyle(attrs, { - strokeLinecap: 'round', - strokeLinejoin: 'round', - stroke: BLACK, - strokeWidth: 2, - fill: 'white', - }); - } - - function addMarker(id, options) { - const attrs = assign({ - strokeWidth: 1, - strokeLinecap: 'round', - strokeDasharray: 'none', - }, options.attrs); - - const ref = options.ref || { x: 0, y: 0 }; - - const scale = options.scale || 1; - - // fix for safari / chrome / firefox bug not correctly - // resetting stroke dash array - if (attrs.strokeDasharray === 'none') { - attrs.strokeDasharray = [10000, 1]; - } - - const markerElement = svgCreate('marker'); - - svgAttr(options.element, attrs); - - svgAppend(markerElement, options.element); - - svgAttr(markerElement, { - id, - viewBox: '0 0 20 20', - refX: ref.x, - refY: ref.y, - markerWidth: 20 * scale, - markerHeight: 20 * scale, - orient: 'auto', - }); - - // eslint-disable-next-line no-underscore-dangle - let defs = domQuery('defs', canvas._svg); - - if (!defs) { - defs = svgCreate('defs'); - - // eslint-disable-next-line no-underscore-dangle - svgAppend(canvas._svg, defs); - } - - svgAppend(defs, markerElement); - - markers[id] = markerElement; - } - - function createMarker(id, type, fill, stroke) { - const end = svgCreate('path'); - svgAttr(end, { d: 'M 1 5 L 11 10 L 1 15 Z' }); - - if (type === 'connection-end') { - addMarker(id, { - element: end, - attrs: { - fill: stroke, - stroke: 'none', - }, - ref: { x: 11, y: 10 }, - scale: 1, - }); - } - - if (type === 'default-choice-marker') { - const defaultChoiceMarker = svgCreate('path', { - d: 'M 6 4 L 10 16', - ...shapeStyle({ - stroke, - }), - }); - - addMarker(id, { - element: defaultChoiceMarker, - ref: { x: 0, y: 10 }, - scale: 1, - }); - } - } - - function marker(type, fill, stroke) { - const id = `${type}-${colorEscape(fill) - }-${colorEscape(stroke)}`; - - if (!markers[id]) { - createMarker(id, type, fill, stroke); - } - - return `url(#${id})`; - } - - function drawCircle(parentGfx, width, height, offset, attrs) { - if (isObject(offset)) { - attrs = offset; - offset = 0; - } - - offset = offset || 0; - - attrs = shapeStyle(attrs); - - if (attrs.fill === 'none') { - delete attrs.fillOpacity; - } - - const cx = width / 2; - const cy = height / 2; - - const circle = svgCreate('circle', { - cx, - cy, - r: Math.round((width + height) / 4 - offset), - ...attrs, - }); - - svgAppend(parentGfx, circle); - - return circle; - } - - function drawRect(p, width, height, r, offset, attrs) { - if (isObject(offset)) { - attrs = offset; - offset = 0; - } - - offset = offset || 0; - - attrs = computeStyle(attrs, { - stroke: BLACK, - strokeWidth: 2, - fill: 'white', - }); - - const rect = svgCreate('rect'); - svgAttr(rect, { - x: offset, - y: offset, - width: width - offset * 2, - height: height - offset * 2, - rx: r, - ry: r, - }); - svgAttr(rect, attrs); - - svgAppend(p, rect); - - return rect; - } - - function renderLabel(p, label, options) { - const text = textRenderer.createText(label || '', options); - - domAttr(text, 'class', 'djs-label'); - - svgAppend(p, text); - - return text; - } - - function renderEmbeddedLabel(p, element, align, options) { - const { Name } = element.businessObject; - - options = assign({ - box: element, - align, - padding: 5, - style: { - fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor), - }, - }, options); - - return renderLabel(p, Name, options); - } - - function drawPath(p, d, attrs) { - attrs = computeStyle(attrs, ['no-fill'], { - strokeWidth: 2, - stroke: BLACK, - }); - - const path = svgCreate('path'); - svgAttr(path, { d }); - svgAttr(path, attrs); - - svgAppend(p, path); - - return path; - } - - function drawDiamond(parentGfx, width, height, attrs) { - const x2 = width / 2; - const y2 = height / 2; - - const points = [ - { x: x2, y: 0 }, - { x: width, y: y2 }, - { x: x2, y: height }, - { x: 0, y: y2 }, - ]; - - const pointsString = points.map((point) => { - return `${point.x},${point.y}`; - }).join(' '); - - attrs = shapeStyle(attrs); - - const polygon = svgCreate('polygon', { - ...attrs, - points: pointsString, - }); - - svgAppend(parentGfx, polygon); - - return polygon; - } - - function drawLine(p, waypoints, attrs) { - attrs = computeStyle(attrs, ['no-fill'], { - stroke: BLACK, - strokeWidth: 2, - fill: 'none', - }); - - const line = createLine(waypoints, attrs); - - svgAppend(p, line); - - return line; - } - - function drawMarker(type, parentGfx, path, attrs) { - return drawPath(parentGfx, path, assign({ 'data-marker': type }, attrs)); - } - - let handlers; - - function renderer(type) { - return handlers[type]; - } - - function attachTaskMarkers(p, element, taskMarkers) { - const obj = getSemantic(element); - - const sub = taskMarkers && taskMarkers.indexOf('SubStateMachineMarker') !== -1; - let position; - - if (sub) { - position = { - seq: -21, - parallel: -22, - compensation: -42, - loop: -18, - }; - } else { - position = { - seq: -3, - parallel: -6, - compensation: -27, - loop: 0, - }; - } - - forEach(taskMarkers, (m) => { - renderer(m)(p, element, position); - }); - - if (obj.IsForCompensation) { - renderer('CompensationMarker')(p, element, position); - } - - const { Loop } = obj; - - if (Loop) { - renderer('LoopMarker')(p, element, position); - } - } - - handlers = { - Transition(p, element) { - const fill = getFillColor(element, defaultFillColor); - const stroke = getStrokeColor(element, defaultStrokeColor); - const attrs = { - stroke, - strokeWidth: 1, - strokeLinecap: 'round', - strokeLinejoin: 'round', - markerEnd: marker('connection-end', fill, stroke), - }; - - return drawLine(p, element.waypoints, attrs); - }, - ChoiceEntry(p, element) { - const fill = getFillColor(element, defaultFillColor); - const stroke = getStrokeColor(element, defaultStrokeColor); - const attrs = { - stroke, - strokeWidth: 1, - strokeLinecap: 'round', - strokeLinejoin: 'round', - markerEnd: marker('connection-end', fill, stroke), - }; - - const path = drawLine(p, element.waypoints, attrs); - - if (getSemantic(element).Default) { - svgAttr(path, { - markerStart: marker('default-choice-marker', fill, stroke), - }); - } - - return path; - }, - ExceptionMatch(p, element) { - return renderer('Transition')(p, element); - }, - Compensation(p, element) { - const stroke = getStrokeColor(element, defaultStrokeColor); - const attrs = { - stroke, - strokeWidth: 1, - strokeLinecap: 'round', - strokeLinejoin: 'round', - strokeDasharray: '10, 11', - }; - - return drawLine(p, element.waypoints, attrs); - }, - StartState(parentGfx, element) { - return drawCircle(parentGfx, element.width, element.height, { - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - }); - }, - Task(parentGfx, element, additionalMarkers) { - const attrs = { - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - fillOpacity: DEFAULT_FILL_OPACITY, - }; - - const rect = drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, attrs); - - renderEmbeddedLabel(parentGfx, element, 'center-middle'); - attachTaskMarkers(parentGfx, element, additionalMarkers); - - return rect; - }, - ServiceTask(parentGfx, element) { - const task = renderer('Task')(parentGfx, element); - const pathDataBG = pathMap.getScaledPath('TASK_TYPE_SERVICE', { - abspos: { - x: 12, - y: 18, - }, - }); - - /* service bg */ drawPath(parentGfx, pathDataBG, { - strokeWidth: 1, - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - }); - - const fillPathData = pathMap.getScaledPath('TASK_TYPE_SERVICE_FILL', { - abspos: { - x: 17.2, - y: 18, - }, - }); - - /* service fill */ drawPath(parentGfx, fillPathData, { - strokeWidth: 0, - fill: getFillColor(element, defaultFillColor), - }); - - const pathData = pathMap.getScaledPath('TASK_TYPE_SERVICE', { - abspos: { - x: 17, - y: 22, - }, - }); - - /* service */ drawPath(parentGfx, pathData, { - strokeWidth: 1, - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - }); - - return task; - }, - ScriptTask(parentGfx, element) { - const task = renderer('Task')(parentGfx, element); - const pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', { - abspos: { - x: 15, - y: 20, - }, - }); - - /* script path */ drawPath(parentGfx, pathData, { - strokeWidth: 1, - stroke: getStrokeColor(element, defaultStrokeColor), - }); - - return task; - }, - SubStateMachine(parentGfx, element) { - return renderer('Task')(parentGfx, element, ['SubStateMachineMarker']); - }, - SubStateMachineMarker(parentGfx, element) { - const markerRect = drawRect(parentGfx, 14, 14, 0, { - strokeWidth: 1, - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - }); - - translate(markerRect, element.width / 2 - 7.5, element.height - 20); - - const markerPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', { - xScaleFactor: 1.5, - yScaleFactor: 1.5, - containerWidth: element.width, - containerHeight: element.height, - position: { - mx: (element.width / 2 - 7.5) / element.width, - my: (element.height - 20) / element.height, - }, - }); - - drawMarker('sub-process', parentGfx, markerPath, { - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - }); - }, - LoopMarker(parentGfx, element, position) { - const markerPath = pathMap.getScaledPath('MARKER_LOOP', { - xScaleFactor: 1, - yScaleFactor: 1, - containerWidth: element.width, - containerHeight: element.height, - position: { - mx: ((element.width / 2 + position.loop) / element.width), - my: (element.height - 7) / element.height, - }, - }); - - drawMarker('loop', parentGfx, markerPath, { - strokeWidth: 1.5, - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - strokeMiterlimit: 0.5, - }); - }, - CompensationMarker(parentGfx, element, position) { - const markerMath = pathMap.getScaledPath('MARKER_COMPENSATION', { - xScaleFactor: 1, - yScaleFactor: 1, - containerWidth: element.width, - containerHeight: element.height, - position: { - mx: ((element.width / 2 + position.compensation) / element.width), - my: (element.height - 13) / element.height, - }, - }); - - drawMarker('compensation', parentGfx, markerMath, { - strokeWidth: 1, - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - }); - }, - Gateway(parentGfx, element) { - return drawDiamond(parentGfx, element.width, element.height, { - fill: getFillColor(element, defaultFillColor), - fillOpacity: DEFAULT_FILL_OPACITY, - stroke: getStrokeColor(element, defaultStrokeColor), - }); - }, - Choice(parentGfx, element) { - const diamond = renderer('Gateway')(parentGfx, element); - - const pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', { - xScaleFactor: 0.4, - yScaleFactor: 0.4, - containerWidth: element.width, - containerHeight: element.height, - position: { - mx: 0.32, - my: 0.3, - }, - }); - - drawPath(parentGfx, pathData, { - strokeWidth: 1, - fill: getStrokeColor(element, defaultStrokeColor), - stroke: getStrokeColor(element, defaultStrokeColor), - }); - - return diamond; - }, - Succeed(parentGfx, element) { - return drawCircle(parentGfx, element.width, element.height, { - strokeWidth: 4, - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - }); - }, - Error(parentGfx, element, fill) { - const pathData = pathMap.getScaledPath('EVENT_ERROR', { - xScaleFactor: 1.1, - yScaleFactor: 1.1, - containerWidth: element.width, - containerHeight: element.height, - position: { - mx: 0.2, - my: 0.722, - }, - }); - return drawPath(parentGfx, pathData, { - strokeWidth: 1, - fill: fill ? getStrokeColor(element, defaultStrokeColor) : 'none', - stroke: getStrokeColor(element, defaultStrokeColor), - }); - }, - Fail(parentGfx, element) { - const circle = handlers.Succeed(parentGfx, element); - renderer('Error')(parentGfx, element, true); - return circle; - }, - Event(parentGfx, element) { - const attrs = { - strokeWidth: 1.5, - fill: getFillColor(element, defaultFillColor), - stroke: getStrokeColor(element, defaultStrokeColor), - }; - - // apply fillOpacity - const outerAttrs = { - ...attrs, - fillOpacity: 1, - }; - - // apply no-fill - const innerAttrs = { - ...attrs, - fill: 'none', - }; - - const outer = drawCircle(parentGfx, element.width, element.height, outerAttrs); - drawCircle(parentGfx, element.width, element.height, 3, innerAttrs); - return outer; - }, - Catch(parentGfx, element) { - const outer = renderer('Event')(parentGfx, element); - renderer('Error')(parentGfx, element); - - return outer; - }, - CompensationTrigger(parentGfx, element) { - const outer = renderer('Event')(parentGfx, element); - const pathData = pathMap.getScaledPath('EVENT_COMPENSATION', { - xScaleFactor: 1, - yScaleFactor: 1, - containerWidth: element.width, - containerHeight: element.height, - position: { - mx: 0.22, - my: 0.5, - }, - }); - - const fill = 'none'; - - drawPath(parentGfx, pathData, { - strokeWidth: 1, - fill, - stroke: getStrokeColor(element, defaultStrokeColor), - }); - return outer; - }, - }; - function drawShape(parent, element) { - const h = handlers[element.type]; - - if (!h) { - return BaseRenderer.prototype.drawShape.apply(this, [parent, element]); - } - return h(parent, element); - } - - function drawConnection(parent, element) { - const { type } = element; - const h = handlers[type]; - - if (!h) { - return BaseRenderer.prototype.drawConnection.apply(this, [parent, element]); - } - return h(parent, element); - } - - // eslint-disable-next-line no-unused-vars - this.canRender = function (element) { - return true; - }; - - this.drawShape = drawShape; - this.drawConnection = drawConnection; -} - -inherits(Renderer, BaseRenderer); - -Renderer.$inject = [ - 'config.Renderer', - 'eventBus', - 'pathMap', - 'styles', - 'textRenderer', - 'canvas', -]; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/TextRenderer.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/TextRenderer.js deleted file mode 100644 index eec8cc3361..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/TextRenderer.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { assign } from 'min-dash'; - -import TextUtil from 'diagram-js/lib/util/Text'; - -const DEFAULT_FONT_SIZE = 12; -const LINE_HEIGHT_RATIO = 1.2; - -export default function TextRenderer(config) { - const defaultStyle = assign({ - fontFamily: 'Arial, sans-serif', - fontSize: DEFAULT_FONT_SIZE, - fontWeight: 'normal', - lineHeight: LINE_HEIGHT_RATIO, - }, (config && config.defaultStyle) || {}); - - const textUtil = new TextUtil({ - style: defaultStyle, - }); - - /** - * Create a layouted text element. - * - * @param {string} text - * @param {Object} [options] - * - * @return {SVGElement} rendered text - */ - this.createText = function (text, options) { - return textUtil.createText(text, options || {}); - }; - - /** - * Get default text style. - */ - this.getDefaultStyle = function () { - return defaultStyle; - }; -} - -TextRenderer.$inject = [ - 'config.textRenderer', -]; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/index.js deleted file mode 100644 index e0b3ec3f25..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/render/index.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import Renderer from './Renderer'; -import TextRenderer from './TextRenderer'; -import PathMap from './PathMap'; - -export default { - __init__: ['renderer'], - renderer: ['type', Renderer], - textRenderer: ['type', TextRenderer], - pathMap: ['type', PathMap], -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/BaseSpec.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/BaseSpec.js deleted file mode 100644 index e97efe7a9e..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/BaseSpec.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export default function BaseSpec() { -} - -BaseSpec.prototype.Type = 'Base'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Catch.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Catch.js deleted file mode 100644 index b18a33c89d..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Catch.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import Node from './style/Node'; - -export default class Catch extends Node { - -} - -Catch.prototype.Type = 'Catch'; - -Catch.prototype.THUMBNAIL_CLASS = 'bpmn-icon-intermediate-event-catch-error'; - -Catch.prototype.DEFAULT_SIZE = { - width: 36, - height: 36, -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Choice.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Choice.js deleted file mode 100644 index a7758ed3aa..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Choice.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import State from './State'; - -export default class Choice extends State { - importJson(json) { - super.importJson(json); - if (json.edge) { - this.Choices.forEach((choice) => { - if (json.edge[choice.Next]) { - json.edge[choice.Next].Expression = choice.Expression; - } - }); - if (json.edge[this.Default]) { - json.edge[this.Default].Default = true; - } - } - delete this.Choices; - delete this.Default; - } -} - -Choice.prototype.Type = 'Choice'; - -Choice.prototype.THUMBNAIL_CLASS = 'bpmn-icon-gateway-xor'; - -Choice.prototype.DEFAULT_SIZE = { - width: 50, - height: 50, -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ChoiceEntry.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ChoiceEntry.js deleted file mode 100644 index 43161baa14..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ChoiceEntry.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import Transition from './Transition'; - -export default class ChoiceEntry extends Transition { - constructor() { - super(); - this.Expression = ''; - this.Default = false; - } - - importJson(json) { - super.importJson(json); - this.Expression = json.Expression; - this.Default = json.Default; - } -} - -ChoiceEntry.prototype.Type = 'ChoiceEntry'; - -ChoiceEntry.prototype.THUMBNAIL_CLASS = 'bpmn-icon-connection'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Compensation.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Compensation.js deleted file mode 100644 index d1eb7eea62..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Compensation.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import Transition from './Transition'; - -export default class Compensation extends Transition { - -} - -Compensation.prototype.Type = 'Compensation'; - -Compensation.prototype.THUMBNAIL_CLASS = 'bpmn-icon-connection-multi'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/CompensationTrigger.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/CompensationTrigger.js deleted file mode 100644 index 416431df5f..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/CompensationTrigger.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import State from './State'; - -export default class CompensationTrigger extends State { - -} - -CompensationTrigger.prototype.Type = 'CompensationTrigger'; - -CompensationTrigger.prototype.THUMBNAIL_CLASS = 'bpmn-icon-intermediate-event-catch-compensation'; - -CompensationTrigger.prototype.DEFAULT_SIZE = { - width: 36, - height: 36, -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ExceptionMatch.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ExceptionMatch.js deleted file mode 100644 index d14e5b36fd..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ExceptionMatch.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import Transition from './Transition'; - -export default class ExceptionMatch extends Transition { - constructor() { - super(); - this.Exceptions = []; - } - - importJson(json) { - super.importJson(json); - this.Exceptions = json.Exceptions; - } - - exportJson() { - const json = super.exportJson(); - json.style.source = this.style.source.host.businessObject.Name; - return json; - } -} - -ExceptionMatch.prototype.Type = 'ExceptionMatch'; - -ExceptionMatch.prototype.THUMBNAIL_CLASS = 'bpmn-icon-connection'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Fail.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Fail.js deleted file mode 100644 index 42e4ce1388..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Fail.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import State from './State'; - -export default class Fail extends State { - constructor() { - super(); - this.ErrorCode = ''; - this.Message = ''; - } -} - -Fail.prototype.Type = 'Fail'; - -Fail.prototype.THUMBNAIL_CLASS = 'bpmn-icon-end-event-error'; - -Fail.prototype.DEFAULT_SIZE = { - width: 36, - height: 36, -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ScriptTask.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ScriptTask.js deleted file mode 100644 index 4eaea829f0..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ScriptTask.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import TaskState from './TaskState'; - -export default class ScriptTask extends TaskState { - constructor() { - super(); - this.ScriptType = 'groovy'; - this.ScriptContent = ''; - } -} - -ScriptTask.prototype.Type = 'ScriptTask'; - -ScriptTask.prototype.THUMBNAIL_CLASS = 'bpmn-icon-script-task'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ServiceTask.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ServiceTask.js deleted file mode 100644 index 1dfdd27f2d..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/ServiceTask.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import TaskState from './TaskState'; - -export default class ServiceTask extends TaskState { - constructor() { - super(); - this.ServiceName = ''; - this.ServiceMethod = ''; - } -} - -ServiceTask.prototype.Type = 'ServiceTask'; - -ServiceTask.prototype.THUMBNAIL_CLASS = 'bpmn-icon-service-task'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/StartState.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/StartState.js deleted file mode 100644 index d1531fa8d8..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/StartState.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import Node from './style/Node'; - -export default class StartState extends Node { - -} - -StartState.prototype.Type = 'StartState'; - -StartState.prototype.THUMBNAIL_CLASS = 'bpmn-icon-start-event-none'; - -StartState.prototype.DEFAULT_SIZE = { - width: 36, - height: 36, -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/State.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/State.js deleted file mode 100644 index 4f8e3ba8b8..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/State.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { assign } from 'min-dash'; -import { randomString } from '../utils'; -import Node from './style/Node'; - -export default class State extends Node { - constructor() { - super(); - this.Name = `${this.Type}-${randomString()}`; - } - - importJson(json) { - super.importJson(json); - const { style, edge, Type, Next, ...props } = json; - assign(this, props); - } - - exportJson() { - const json = super.exportJson(); - const { style, ...props } = this; - return assign(json, props, { Type: this.Type }); - } -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/StateMachine.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/StateMachine.js deleted file mode 100644 index 689f9a9a6d..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/StateMachine.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { assign } from 'min-dash'; -import { randomString } from '../utils'; -import BaseSpec from './BaseSpec'; - -export default class StateMachine extends BaseSpec { - constructor() { - super(); - this.Name = `${this.Type}-${randomString()}`; - } - - importJson(json) { - const { style, edge, StartState, States, ...props } = json; - assign(this, props); - } - - exportJson() { - return assign({}, this); - } -} - -StateMachine.prototype.THUMBNAIL_CLASS = 'bpmn-icon-transaction'; - -StateMachine.prototype.Type = 'StateMachine'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/SubStateMachine.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/SubStateMachine.js deleted file mode 100644 index 79a2a41e86..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/SubStateMachine.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import TaskState from './TaskState'; - -export default class SubStateMachine extends TaskState { - constructor() { - super(); - this.StateMachineName = ''; - } -} - -SubStateMachine.prototype.Type = 'SubStateMachine'; - -SubStateMachine.prototype.THUMBNAIL_CLASS = 'bpmn-icon-subprocess-collapsed'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Succeed.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Succeed.js deleted file mode 100644 index ad53a7b923..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Succeed.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import State from './State'; - -export default class Succeed extends State { -} - -Succeed.prototype.Type = 'Succeed'; - -Succeed.prototype.THUMBNAIL_CLASS = 'bpmn-icon-end-event-none'; - -Succeed.prototype.DEFAULT_SIZE = { - width: 36, - height: 36, -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/TaskState.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/TaskState.js deleted file mode 100644 index 566ab67e77..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/TaskState.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import State from './State'; - -export default class TaskState extends State { - constructor() { - super(); - this.IsForCompensation = false; - this.Input = [{}]; - this.Output = {}; - this.Status = {}; - this.Retry = []; - } - - importJson(json) { - super.importJson(json); - delete this.catch; - } - - exportJson() { - const json = super.exportJson(); - const { Catch } = json; - if (Catch) { - json.catch = json.Catch.exportJson(); - json.Catch = []; - } - - if (this.CompensateState) { - json.CompensateState = this.CompensateState.Name; - } - return json; - } -} - -TaskState.prototype.DEFAULT_SIZE = { - width: 100, - height: 80, -}; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Transition.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Transition.js deleted file mode 100644 index 2a16482792..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/Transition.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import Edge from './style/Edge'; - -export default class Transition extends Edge { - exportJson() { - const json = super.exportJson(); - json.Type = this.Type; - return json; - } -} - -Transition.prototype.THUMBNAIL_CLASS = 'bpmn-icon-connection'; - -Transition.prototype.Type = 'Transition'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/Edge.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/Edge.js deleted file mode 100644 index 7ff1391ba8..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/Edge.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { assign } from 'min-dash'; -import BaseSpec from '../BaseSpec'; -import EdgeStyle from './EdgeStyle'; - -export default class Edge extends BaseSpec { - style = new EdgeStyle(); - - importJson(json) { - this.style.source = json.style.source; - this.style.target = json.style.target; - assign(this.style.waypoints, json.style.waypoints); - } - - exportJson() { - const json = assign({ style: new EdgeStyle() }, { style: { waypoints: this.style.waypoints } }); - json.style.source = this.style.source.businessObject.Name; - json.style.target = this.style.target.businessObject.Name; - return json; - } -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/EdgeStyle.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/EdgeStyle.js deleted file mode 100644 index 4538a94a90..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/EdgeStyle.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import BaseSpec from '../BaseSpec'; - -export default class EdgeStyle extends BaseSpec { - /** - * @type {djs.model.Base} - */ - source; - - /** - * @type {djs.model.Base} - */ - target; - - /** - * @typedef {{original: WayPoint, x: number, y: number}} WayPoint - */ - /** - * @type {[WayPoint]} - */ - waypoints = []; -} - -EdgeStyle.prototype.Type = 'Edge'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/Node.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/Node.js deleted file mode 100644 index dc06861bb1..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/Node.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { assign } from 'min-dash'; -import BaseSpec from '../BaseSpec'; -import NodeStyle from './NodeStyle'; -// import THUMBNAIL from '../icons/bpmn-icon-service-task.svg'; - -export default class Node extends BaseSpec { - style = new NodeStyle(); - - importJson(json) { - assign(this.style.bounds, json.style.bounds); - } - - exportJson() { - return assign({}, { style: this.style }); - } -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/NodeStyle.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/NodeStyle.js deleted file mode 100644 index c26d2867bb..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/spec/style/NodeStyle.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import BaseSpec from '../BaseSpec'; - -export default class NodeStyle extends BaseSpec { - /** - * @typedef {{x: number, y: number, width: number, height: number}} Bounds - * @type {Bounds} - */ - bounds = {}; -} - -NodeStyle.prototype.Type = 'Node'; diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/utils/index.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/src/utils/index.js deleted file mode 100644 index 72054ca1c5..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/src/utils/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { forEach, reduce } from 'min-dash'; -import { useContext } from '@bpmn-io/properties-panel/preact/hooks'; -import PropertiesPanelContext from '../properties-panel/PropertiesPanelContext'; - -/** - * Returns a random generated string for initial decision definition id. - * @returns {string} - */ -export function randomString() { - // noinspection SpellCheckingInspection - const chars = 'abcdefghijklmnopqrstuvwxyz1234567890'; - const maxPos = chars.length; - let str = ''; - for (let i = 0; i < 7; i++) { - str += chars.charAt(Math.floor(Math.random() * maxPos)); - } - return str; -} - -export function useService(type, strict) { - const { getService } = useContext(PropertiesPanelContext); - - return getService(type, strict); -} - -export function getProperties(businessObject, propertyNames) { - return reduce(propertyNames, (result, key) => { - result[key] = businessObject[key]; - return result; - }, {}); -} - -export function setProperties(businessObject, properties, override) { - if (override) { - Object.keys(businessObject) - .filter((key) => key !== 'style') - .forEach((key) => delete businessObject[key]); - } - forEach(properties, (value, key) => { - businessObject[key] = value; - }); -} - -export function is(element, target) { - const type = element?.businessObject?.Type || element?.Type || element; - - if (target === 'Task') { - return type === 'ServiceTask' || type === 'ScriptTask' || type === 'SubStateMachine'; - } - - if (target === 'Connection') { - return type === 'Transition' || type === 'ChoiceEntry' || type === 'ExceptionMatch' || type === 'Compensation'; - } - - return type === target; -} diff --git a/laokou-cloud/laokou-seata-saga-statemachine-designer/webpack.config.js b/laokou-cloud/laokou-seata-saga-statemachine-designer/webpack.config.js deleted file mode 100644 index 04369f9497..0000000000 --- a/laokou-cloud/laokou-seata-saga-statemachine-designer/webpack.config.js +++ /dev/null @@ -1,46 +0,0 @@ -const CopyPlugin = require('copy-webpack-plugin'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -module.exports = (env, options) => { - return { - entry: { - bundle: './src/index.js', - }, - output: { - path: `${__dirname}/dist`, - filename: '[name].js', - }, - plugins: [ - new CopyPlugin({ - patterns: [ - { from: 'public' }, - ], - }), - new MiniCssExtractPlugin(), - new HtmlWebpackPlugin({ - template: 'src/index.html', - filename: 'index.html', - }), - ], - module: { - rules: [ - { - test: /\.m?js$/, - exclude: /(node_modules|bower_components)/, - use: { - loader: 'babel-loader', - options: { - babelrc: true, - }, - }, - }, - { - test: /\.css$/, - use: [MiniCssExtractPlugin.loader, 'css-loader'], - }, - ], - }, - devtool: options.mode === 'production' ? 'nosources-source-map' : 'source-map', - }; -}; diff --git a/laokou-cloud/laokou-seata/Dockerfile b/laokou-cloud/laokou-seata/Dockerfile deleted file mode 100644 index b34bc2eb66..0000000000 --- a/laokou-cloud/laokou-seata/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# /** -# * Copyright (c) 2022-2024 KCloud-Platform-IoT Author or Authors. All Rights Reserved. -# *

    -# * Licensed under the Apache License, Version 2.0 (the "License"); -# * you may not use this file except in compliance with the License. -# * You may obtain a copy of the License at -# *

    -# * http://www.apache.org/licenses/LICENSE-2.0 -# *

    -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# */ -# 基础镜像 -FROM docker.io/tabatad/jdk21 -# 信息 -LABEL maintainer="laokou" -LABEL description="laokou-seata" -# 复制文件 -COPY target/laokou-seata.jar app.jar -# 暴露端口 -EXPOSE 7091 -CMD java $JVM_OPTS -jar app.jar >/dev/null 2>&1 diff --git a/laokou-cloud/laokou-seata/pom.xml b/laokou-cloud/laokou-seata/pom.xml deleted file mode 100644 index 46038ecee3..0000000000 --- a/laokou-cloud/laokou-seata/pom.xml +++ /dev/null @@ -1,234 +0,0 @@ - - - - laokou-cloud - org.laokou - 3.3.2 - - 4.0.0 - laokou-seata - - - - 2.0.0 - - 2.7.18 - - 0.2.0-RC2 - - 3.10.0 - - 2.0.52 - - 7.4 - - 1.2.23 - - 1.82 - - 1.3.14 - - 4.1.112.Final - - - - - org.projectlombok - lombok - - - org.springframework.boot - spring-boot-starter-web - - - log4j-to-slf4j - org.apache.logging.log4j - - - org.springframework.boot - spring-boot-starter-tomcat - - - - - io.seata - seata-spring-autoconfigure-server - ${seata.version} - - - io.seata - seata-core - ${seata.version} - - - io.seata - seata-config-all - ${seata.version} - - - log4j - log4j - - - io.netty - netty-codec-http - - - - - io.netty - netty-all - ${netty.version} - - - io.seata - seata-discovery-all - ${seata.version} - - - io.seata - seata-serializer-all - ${seata.version} - - - io.seata - seata-compressor-all - ${seata.version} - - - io.seata - seata-metrics-all - ${seata.version} - - - io.seata - seata-console - ${seata.version} - - - com.alibaba - druid - ${druid.version} - - - org.apache.commons - commons-dbcp2 - - - com.zaxxer - HikariCP - - - com.github.ulisesbocchio - jasypt-spring-boot-starter - - - com.beust - jcommander - ${jcommander.version} - - - com.google.guava - guava - - - redis.clients - jedis - ${jedis.version} - - - com.alibaba - fastjson - ${fastjson.version} - - - net.logstash.logback - logstash-logback-encoder - ${logstash-logback-encoder.version} - - - com.github.danielwegener - logback-kafka-appender - ${kafka-appender.version} - - - com.alipay.sofa - jraft-core - ${jraft-core.version} - - - org.codehaus.janino - janino - - - org.springframework.boot - spring-boot-starter-undertow - provided - - - - - - - - org.springframework.boot - spring-boot-starter-parent - ${spring-boot.version} - pom - import - - - - - - ${project.artifactId} - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 21 - 21 - UTF-8 - - -Xlint:deprecation - -parameters - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot-maven-plugin.version} - - ${project.artifactId} - - io.seata.server.SeataApp - - - - - repackage - - - - - - io.fabric8 - docker-maven-plugin - ${docker-maven-plugin.version} - - - org.apache.maven.plugins - maven-checkstyle-plugin - ${maven-checkstyle-plugin.version} - - true - - - - - - diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/AbstractTCInboundHandler.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/AbstractTCInboundHandler.java deleted file mode 100644 index ecc15cf263..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/AbstractTCInboundHandler.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server; - -import io.seata.common.exception.StoreException; -import io.seata.core.exception.AbstractExceptionHandler; -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.model.GlobalStatus; -import io.seata.core.protocol.transaction.AbstractGlobalEndRequest; -import io.seata.core.protocol.transaction.AbstractGlobalEndResponse; -import io.seata.core.protocol.transaction.BranchRegisterRequest; -import io.seata.core.protocol.transaction.BranchRegisterResponse; -import io.seata.core.protocol.transaction.BranchReportRequest; -import io.seata.core.protocol.transaction.BranchReportResponse; -import io.seata.core.protocol.transaction.GlobalBeginRequest; -import io.seata.core.protocol.transaction.GlobalBeginResponse; -import io.seata.core.protocol.transaction.GlobalCommitRequest; -import io.seata.core.protocol.transaction.GlobalCommitResponse; -import io.seata.core.protocol.transaction.GlobalLockQueryRequest; -import io.seata.core.protocol.transaction.GlobalLockQueryResponse; -import io.seata.core.protocol.transaction.GlobalReportRequest; -import io.seata.core.protocol.transaction.GlobalReportResponse; -import io.seata.core.protocol.transaction.GlobalRollbackRequest; -import io.seata.core.protocol.transaction.GlobalRollbackResponse; -import io.seata.core.protocol.transaction.GlobalStatusRequest; -import io.seata.core.protocol.transaction.GlobalStatusResponse; -import io.seata.core.protocol.transaction.TCInboundHandler; -import io.seata.core.rpc.RpcContext; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The type Abstract tc inbound handler. - * - * @author sharajava - */ -public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler implements TCInboundHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractTCInboundHandler.class); - - @Override - public GlobalBeginResponse handle(GlobalBeginRequest request, final RpcContext rpcContext) { - GlobalBeginResponse response = new GlobalBeginResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalBeginRequest request, GlobalBeginResponse response) throws TransactionException { - try { - doGlobalBegin(request, response, rpcContext); - } - catch (StoreException e) { - throw new TransactionException(TransactionExceptionCode.FailedStore, String - .format("begin global request failed. xid=%s, msg=%s", response.getXid(), e.getMessage()), e); - } - } - }, request, response); - return response; - } - - /** - * Do global begin. - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public GlobalCommitResponse handle(GlobalCommitRequest request, final RpcContext rpcContext) { - GlobalCommitResponse response = new GlobalCommitResponse(); - response.setGlobalStatus(GlobalStatus.Committing); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalCommitRequest request, GlobalCommitResponse response) - throws TransactionException { - try { - doGlobalCommit(request, response, rpcContext); - } - catch (StoreException e) { - throw new TransactionException(TransactionExceptionCode.FailedStore, String - .format("global commit request failed. xid=%s, msg=%s", request.getXid(), e.getMessage()), e); - } - } - - @Override - public void onTransactionException(GlobalCommitRequest request, GlobalCommitResponse response, - TransactionException tex) { - super.onTransactionException(request, response, tex); - checkTransactionStatus(request, response); - } - - @Override - public void onException(GlobalCommitRequest request, GlobalCommitResponse response, Exception rex) { - super.onException(request, response, rex); - checkTransactionStatus(request, response); - } - - }, request, response); - return response; - } - - /** - * Do global commit. - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public GlobalRollbackResponse handle(GlobalRollbackRequest request, final RpcContext rpcContext) { - GlobalRollbackResponse response = new GlobalRollbackResponse(); - response.setGlobalStatus(GlobalStatus.Rollbacking); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalRollbackRequest request, GlobalRollbackResponse response) - throws TransactionException { - try { - doGlobalRollback(request, response, rpcContext); - } - catch (StoreException e) { - throw new TransactionException(TransactionExceptionCode.FailedStore, String - .format("global rollback request failed. xid=%s, msg=%s", request.getXid(), e.getMessage()), e); - } - } - - @Override - public void onTransactionException(GlobalRollbackRequest request, GlobalRollbackResponse response, - TransactionException tex) { - super.onTransactionException(request, response, tex); - // may be appears StoreException outer layer method catch - checkTransactionStatus(request, response); - } - - @Override - public void onException(GlobalRollbackRequest request, GlobalRollbackResponse response, Exception rex) { - super.onException(request, response, rex); - // may be appears StoreException outer layer method catch - checkTransactionStatus(request, response); - } - }, request, response); - return response; - } - - /** - * Do global rollback. - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public BranchRegisterResponse handle(BranchRegisterRequest request, final RpcContext rpcContext) { - BranchRegisterResponse response = new BranchRegisterResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(BranchRegisterRequest request, BranchRegisterResponse response) - throws TransactionException { - try { - doBranchRegister(request, response, rpcContext); - } - catch (StoreException e) { - throw new TransactionException(TransactionExceptionCode.FailedStore, String - .format("branch register request failed. xid=%s, msg=%s", request.getXid(), e.getMessage()), e); - } - } - }, request, response); - return response; - } - - /** - * Do branch register. - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public BranchReportResponse handle(BranchReportRequest request, final RpcContext rpcContext) { - BranchReportResponse response = new BranchReportResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(BranchReportRequest request, BranchReportResponse response) - throws TransactionException { - try { - doBranchReport(request, response, rpcContext); - } - catch (StoreException e) { - throw new TransactionException(TransactionExceptionCode.FailedStore, - String.format("branch report request failed. xid=%s, branchId=%s, msg=%s", request.getXid(), - request.getBranchId(), e.getMessage()), - e); - } - } - }, request, response); - return response; - } - - /** - * Do branch report. - * @param request the request - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doBranchReport(BranchReportRequest request, BranchReportResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public GlobalLockQueryResponse handle(GlobalLockQueryRequest request, final RpcContext rpcContext) { - GlobalLockQueryResponse response = new GlobalLockQueryResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalLockQueryRequest request, GlobalLockQueryResponse response) - throws TransactionException { - try { - doLockCheck(request, response, rpcContext); - } - catch (StoreException e) { - throw new TransactionException(TransactionExceptionCode.FailedStore, String.format( - "global lock query request failed. xid=%s, msg=%s", request.getXid(), e.getMessage()), e); - } - } - }, request, response); - return response; - } - - /** - * Do lock check. - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doLockCheck(GlobalLockQueryRequest request, GlobalLockQueryResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public GlobalStatusResponse handle(GlobalStatusRequest request, final RpcContext rpcContext) { - GlobalStatusResponse response = new GlobalStatusResponse(); - response.setGlobalStatus(GlobalStatus.UnKnown); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalStatusRequest request, GlobalStatusResponse response) - throws TransactionException { - try { - doGlobalStatus(request, response, rpcContext); - } - catch (StoreException e) { - throw new TransactionException(TransactionExceptionCode.FailedStore, String - .format("global status request failed. xid=%s, msg=%s", request.getXid(), e.getMessage()), e); - } - } - - @Override - public void onTransactionException(GlobalStatusRequest request, GlobalStatusResponse response, - TransactionException tex) { - super.onTransactionException(request, response, tex); - checkTransactionStatus(request, response); - } - - @Override - public void onException(GlobalStatusRequest request, GlobalStatusResponse response, Exception rex) { - super.onException(request, response, rex); - checkTransactionStatus(request, response); - } - }, request, response); - return response; - } - - /** - * Do global status. - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doGlobalStatus(GlobalStatusRequest request, GlobalStatusResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public GlobalReportResponse handle(GlobalReportRequest request, final RpcContext rpcContext) { - GlobalReportResponse response = new GlobalReportResponse(); - response.setGlobalStatus(request.getGlobalStatus()); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalReportRequest request, GlobalReportResponse response) - throws TransactionException { - doGlobalReport(request, response, rpcContext); - } - }, request, response); - return response; - } - - /** - * Do global report. - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doGlobalReport(GlobalReportRequest request, GlobalReportResponse response, - RpcContext rpcContext) throws TransactionException; - - private void checkTransactionStatus(AbstractGlobalEndRequest request, AbstractGlobalEndResponse response) { - try { - GlobalSession globalSession = SessionHolder.findGlobalSession(request.getXid(), false); - if (globalSession != null) { - response.setGlobalStatus(globalSession.getStatus()); - } - else { - response.setGlobalStatus(GlobalStatus.Finished); - } - } - catch (Exception exx) { - LOGGER.error("check transaction status error,{}]", exx.getMessage()); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/ParameterParser.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/ParameterParser.java deleted file mode 100644 index 32c0d4e6b5..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/ParameterParser.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server; - -import com.beust.jcommander.JCommander; -import com.beust.jcommander.Parameter; -import com.beust.jcommander.ParameterException; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.server.env.ContainerHelper; -import io.seata.server.store.StoreConfig; - -import static io.seata.config.ConfigurationFactory.ENV_PROPERTY_KEY; - -/** - * The type Parameter parser. - * - * @author xingfudeshi @gmail.com - */ -public class ParameterParser { - - private static final String PROGRAM_NAME = "sh seata-server.sh(for linux and mac) or cmd seata-server.bat(for windows)"; - - private static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - @Parameter(names = "--help", help = true) - private boolean help; - - @Parameter(names = { "--host", "-h" }, description = "The ip to register to registry center.", order = 1) - private String host; - - @Parameter(names = { "--port", "-p" }, description = "The port to listen.", order = 2) - private int port; - - @Parameter(names = { "--storeMode", "-m" }, description = "log store mode : file, db, redis", order = 3) - private String storeMode; - - @Parameter(names = { "--serverNode", "-n" }, - description = "server node id, such as 1, 2, 3.it will be generated according to the snowflake by default", - order = 4) - private Long serverNode; - - @Parameter(names = { "--seataEnv", "-e" }, description = "The name used for multi-configuration isolation.", - order = 5) - private String seataEnv; - - @Parameter(names = { "--sessionStoreMode", "-ssm" }, description = "session log store mode : file, db, redis", - order = 6) - private String sessionStoreMode; - - @Parameter(names = { "--lockStoreMode", "-lsm" }, description = "lock log store mode : file, db, redis", order = 7) - private String lockStoreMode; - - /** - * Instantiates a new Parameter parser. - * @param args the args - */ - public ParameterParser(String... args) { - this.init(args); - } - - /** - * startup args > docker env. - * @param args 参数 - */ - private void init(String[] args) { - try { - getCommandParameters(args); - getEnvParameters(); - if (StringUtils.isNotBlank(seataEnv)) { - System.setProperty(ENV_PROPERTY_KEY, seataEnv); - } - StoreConfig.setStartupParameter(storeMode, sessionStoreMode, lockStoreMode); - } - catch (ParameterException e) { - printError(e); - } - - } - - private void getCommandParameters(String[] args) { - JCommander jCommander = JCommander.newBuilder().addObject(this).build(); - jCommander.parse(args); - if (help) { - jCommander.setProgramName(PROGRAM_NAME); - jCommander.usage(); - System.exit(0); - } - } - - private void getEnvParameters() { - if (StringUtils.isBlank(seataEnv)) { - seataEnv = ContainerHelper.getEnv(); - } - if (StringUtils.isBlank(host)) { - host = ContainerHelper.getHost(); - } - if (port == 0) { - port = ContainerHelper.getPort(); - } - if (serverNode == null) { - serverNode = ContainerHelper.getServerNode(); - } - } - - private void printError(ParameterException e) { - System.err.println("Option error " + e.getMessage()); - e.getJCommander().setProgramName(PROGRAM_NAME); - e.usage(); - System.exit(0); - } - - /** - * Gets host. - * @return the host - */ - public String getHost() { - return host; - } - - /** - * Gets port. - * @return the port - */ - public int getPort() { - return port; - } - - /** - * Gets store mode. - * @return the store mode - */ - public String getStoreMode() { - return storeMode; - } - - /** - * Gets lock store mode. - * @return the store mode - */ - public String getLockStoreMode() { - return lockStoreMode; - } - - /** - * Gets session store mode. - * @return the store mode - */ - public String getSessionStoreMode() { - return sessionStoreMode; - } - - /** - * Is help boolean. - * @return the boolean - */ - public boolean isHelp() { - return help; - } - - /** - * Gets server node. - * @return the server node - */ - public Long getServerNode() { - return serverNode; - } - - /** - * Gets seata env。 - * @return the name used for multi-configuration isolation. - */ - public String getSeataEnv() { - return seataEnv; - } - - /** - * Clean up. - */ - public void cleanUp() { - if (null != System.getProperty(ENV_PROPERTY_KEY)) { - System.clearProperty(ENV_PROPERTY_KEY); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/SeataApp.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/SeataApp.java deleted file mode 100644 index 955fc39c2d..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/SeataApp.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server; - -import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author spilledyear@outlook.com - */ -@SpringBootApplication(scanBasePackages = { "io.seata" }) -@EnableEncryptableProperties -public class SeataApp { - - /** - * 启动项目. - */ - public static void main(String[] args) { - // @formatter:off - // -Dtls.enable=true -Dtls.client.authServer=true -Dtls.client.trustCertPath=d:\\nacos.crt - // @formatter:on - SpringApplication.run(SeataApp.class, args); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/Server.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/Server.java deleted file mode 100644 index d6c5e85f89..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/Server.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server; - -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import io.seata.common.XID; -import io.seata.common.holder.ObjectHolder; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.util.NetUtil; -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.core.rpc.netty.NettyRemotingServer; -import io.seata.core.rpc.netty.NettyServerConfig; -import io.seata.server.coordinator.DefaultCoordinator; -import io.seata.server.lock.LockerManagerFactory; -import io.seata.server.metrics.MetricsManager; -import io.seata.server.session.SessionHolder; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.web.context.support.GenericWebApplicationContext; - -import static io.seata.common.Constants.OBJECT_KEY_SPRING_APPLICATION_CONTEXT; -import static io.seata.spring.boot.autoconfigure.StarterConstants.REGEX_SPLIT_CHAR; -import static io.seata.spring.boot.autoconfigure.StarterConstants.REGISTRY_PREFERED_NETWORKS; - -/** - * The type Server. - * - * @author slievrly - */ -public class Server { - - /** - * The entry point of application. - * @param args the input arguments - */ - public static void start(String[] args) { - // initialize the parameter parser - // Note that the parameter parser should always be the first line to execute. - // Because, here we need to parse the parameters needed for startup. - ParameterParser parameterParser = new ParameterParser(args); - - // initialize the metrics - MetricsManager.get().init(); - - ThreadPoolExecutor workingThreads = new ThreadPoolExecutor(NettyServerConfig.getMinServerPoolSize(), - NettyServerConfig.getMaxServerPoolSize(), NettyServerConfig.getKeepAliveTime(), TimeUnit.SECONDS, - new LinkedBlockingQueue<>(NettyServerConfig.getMaxTaskQueueSize()), - new NamedThreadFactory("ServerHandlerThread", NettyServerConfig.getMaxServerPoolSize()), - new ThreadPoolExecutor.CallerRunsPolicy()); - - // 127.0.0.1 and 0.0.0.0 are not valid here. - if (NetUtil.isValidIp(parameterParser.getHost(), false)) { - XID.setIpAddress(parameterParser.getHost()); - } - else { - String preferredNetworks = ConfigurationFactory.getInstance().getConfig(REGISTRY_PREFERED_NETWORKS); - if (StringUtils.isNotBlank(preferredNetworks)) { - XID.setIpAddress(NetUtil.getLocalIp(preferredNetworks.split(REGEX_SPLIT_CHAR))); - } - else { - XID.setIpAddress(NetUtil.getLocalIp()); - } - } - NettyRemotingServer nettyRemotingServer = new NettyRemotingServer(workingThreads); - XID.setPort(nettyRemotingServer.getListenPort()); - UUIDGenerator.init(parameterParser.getServerNode()); - ConfigurableListableBeanFactory beanFactory = ((GenericWebApplicationContext) ObjectHolder.INSTANCE - .getObject(OBJECT_KEY_SPRING_APPLICATION_CONTEXT)).getBeanFactory(); - DefaultCoordinator coordinator = DefaultCoordinator.getInstance(nettyRemotingServer); - if (coordinator instanceof ApplicationListener) { - beanFactory.registerSingleton(NettyRemotingServer.class.getName(), nettyRemotingServer); - beanFactory.registerSingleton(DefaultCoordinator.class.getName(), coordinator); - ((GenericWebApplicationContext) ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_APPLICATION_CONTEXT)) - .addApplicationListener((ApplicationListener) coordinator); - } - // log store mode : file, db, redis - SessionHolder.init(); - LockerManagerFactory.init(); - coordinator.init(); - nettyRemotingServer.setHandler(coordinator); - - // let ServerRunner do destroy instead ShutdownHook, see - // https://github.com/seata/seata/issues/4028 - ServerRunner.addDisposable(coordinator); - - nettyRemotingServer.init(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/ServerRunner.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/ServerRunner.java deleted file mode 100644 index e9a4b74712..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/ServerRunner.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.seata.server; - -import io.micrometer.core.lang.NonNullApi; -import io.seata.core.rpc.Disposable; -import lombok.RequiredArgsConstructor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.core.Ordered; -import org.springframework.stereotype.Component; - -import java.net.InetAddress; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * @author spilledyear@outlook.com - */ -@Component -@NonNullApi -@RequiredArgsConstructor -public class ServerRunner implements CommandLineRunner, DisposableBean, Ordered { - - private final ServerProperties serverProperties; - - private static final Logger LOGGER = LoggerFactory.getLogger(ServerRunner.class); - - private boolean started = Boolean.FALSE; - - @Value("${logging.file.path}") - private String logPath; - - private static final List DISPOSABLE_LIST = new CopyOnWriteArrayList<>(); - - public static void addDisposable(Disposable disposable) { - DISPOSABLE_LIST.add(disposable); - } - - @Override - public void run(String... args) { - try { - long start = System.currentTimeMillis(); - Server.start(args); - started = true; - long cost = System.currentTimeMillis() - start; - String url = (serverProperties.getSsl().isEnabled() ? "https://" : "http://") - + InetAddress.getLocalHost().getHostAddress() + ":" + serverProperties.getPort(); - LOGGER.info("\n\nseata访问地址:{},日志路径: {}\n", url, this.logPath); - LOGGER.info("seata server started in {} millSeconds", cost); - } - catch (Throwable e) { - started = Boolean.FALSE; - LOGGER.error("seata server start error: {} ", e.getMessage(), e); - System.exit(-1); - } - } - - public boolean started() { - return started; - } - - @Override - public void destroy() throws Exception { - - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("destoryAll starting"); - } - - for (Disposable disposable : DISPOSABLE_LIST) { - disposable.destroy(); - } - - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("destoryAll finish"); - } - } - - @Override - public int getOrder() { - return Ordered.LOWEST_PRECEDENCE; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/UUIDGenerator.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/UUIDGenerator.java deleted file mode 100644 index c2f0f1a539..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/UUIDGenerator.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server; - -import io.seata.common.util.IdWorker; - -/** - * The type Uuid generator. - * - * @author sharajava - */ -public class UUIDGenerator { - - private static volatile IdWorker idWorker; - - /** - * generate UUID using snowflake algorithm. - * @return UUID - */ - public static long generateUUID() { - if (idWorker == null) { - synchronized (UUIDGenerator.class) { - if (idWorker == null) { - init(null); - } - } - } - return idWorker.nextId(); - } - - /** - * init IdWorker. - * @param serverNode the server node id, consider as machine id in snowflake - */ - public static void init(Long serverNode) { - idWorker = new IdWorker(serverNode); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/auth/AbstractCheckAuthHandler.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/auth/AbstractCheckAuthHandler.java deleted file mode 100644 index 16800e7a8b..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/auth/AbstractCheckAuthHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.auth; - -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.protocol.RegisterRMRequest; -import io.seata.core.protocol.RegisterTMRequest; -import io.seata.core.rpc.RegisterCheckAuthHandler; - -import static io.seata.common.DefaultValues.DEFAULT_SERVER_ENABLE_CHECK_AUTH; - -/** - * @author slievrly - */ -public abstract class AbstractCheckAuthHandler implements RegisterCheckAuthHandler { - - private static final Boolean ENABLE_CHECK_AUTH = ConfigurationFactory.getInstance() - .getBoolean(ConfigurationKeys.SERVER_ENABLE_CHECK_AUTH, DEFAULT_SERVER_ENABLE_CHECK_AUTH); - - @Override - public boolean regTransactionManagerCheckAuth(RegisterTMRequest request) { - if (!ENABLE_CHECK_AUTH) { - return true; - } - return doRegTransactionManagerCheck(request); - } - - public abstract boolean doRegTransactionManagerCheck(RegisterTMRequest request); - - @Override - public boolean regResourceManagerCheckAuth(RegisterRMRequest request) { - if (!ENABLE_CHECK_AUTH) { - return true; - } - return doRegResourceManagerCheck(request); - } - - public abstract boolean doRegResourceManagerCheck(RegisterRMRequest request); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/auth/DefaultCheckAuthHandler.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/auth/DefaultCheckAuthHandler.java deleted file mode 100644 index 8fe75e8988..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/auth/DefaultCheckAuthHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.auth; - -import io.seata.common.loader.LoadLevel; -import io.seata.core.protocol.RegisterRMRequest; -import io.seata.core.protocol.RegisterTMRequest; - -/** - * @author slievrly - */ -@LoadLevel(name = "defaultCheckAuthHandler", order = 100) -public class DefaultCheckAuthHandler extends AbstractCheckAuthHandler { - - @Override - public boolean doRegTransactionManagerCheck(RegisterTMRequest request) { - return true; - } - - @Override - public boolean doRegResourceManagerCheck(RegisterRMRequest request) { - return true; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/listener/ClusterChangeEvent.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/listener/ClusterChangeEvent.java deleted file mode 100644 index 638cee1282..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/listener/ClusterChangeEvent.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.listener; - -import java.time.Clock; -import org.springframework.context.ApplicationEvent; - -/** - * @author funkye - */ -public class ClusterChangeEvent extends ApplicationEvent { - - private String group; - - private boolean leader; - - private long term; - - public ClusterChangeEvent(Object source, String group, long term, boolean leader) { - super(source); - this.group = group; - this.term = term; - this.leader = leader; - } - - public ClusterChangeEvent(Object source, String group) { - super(source); - this.group = group; - } - - public ClusterChangeEvent(Object source, Clock clock) { - super(source, clock); - } - - public String getGroup() { - return group; - } - - public void setGroup(String group) { - this.group = group; - } - - public long getTerm() { - return term; - } - - public void setTerm(long term) { - this.term = term; - } - - public boolean isLeader() { - return leader; - } - - public void setLeader(boolean leader) { - this.leader = leader; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/listener/ClusterChangeListener.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/listener/ClusterChangeListener.java deleted file mode 100644 index b6e5850f26..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/listener/ClusterChangeListener.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.listener; - -/** - * @author funkye - */ -public interface ClusterChangeListener { - - /** - * cluster change event. - * @param event event - */ - void onChangeEvent(ClusterChangeEvent event); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/manager/ClusterWatcherManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/manager/ClusterWatcherManager.java deleted file mode 100644 index d892791cae..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/manager/ClusterWatcherManager.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.manager; - -import java.util.Map; -import java.util.Optional; -import java.util.Queue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import javax.annotation.PostConstruct; -import javax.servlet.AsyncContext; -import javax.servlet.http.HttpServletResponse; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.server.cluster.listener.ClusterChangeEvent; -import io.seata.server.cluster.listener.ClusterChangeListener; -import io.seata.server.cluster.watch.Watcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.event.EventListener; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Component; - -/** - * @author funkye - */ -@Component -public class ClusterWatcherManager implements ClusterChangeListener { - - private final Logger logger = LoggerFactory.getLogger(getClass()); - - private static final Map>> WATCHERS = new ConcurrentHashMap<>(); - - private static final Map GROUP_UPDATE_TIME = new ConcurrentHashMap<>(); - - private final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("long-polling", 1)); - - @PostConstruct - public void init() { - // Responds to monitors that time out - scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> { - for (String group : WATCHERS.keySet()) { - Optional.ofNullable(WATCHERS.remove(group)) - .ifPresent(watchers -> watchers.parallelStream().forEach(watcher -> { - if (System.currentTimeMillis() >= watcher.getTimeout()) { - HttpServletResponse httpServletResponse = (HttpServletResponse) ((AsyncContext) watcher - .getAsyncContext()).getResponse(); - watcher.setDone(true); - httpServletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED); - ((AsyncContext) watcher.getAsyncContext()).complete(); - } - if (!watcher.isDone()) { - // Re-register - registryWatcher(watcher); - } - })); - } - }, 1, 1, TimeUnit.SECONDS); - } - - @Override - @EventListener - @Async - public void onChangeEvent(ClusterChangeEvent event) { - if (event.getTerm() > 0) { - GROUP_UPDATE_TIME.put(event.getGroup(), event.getTerm()); - // Notifications are made of changes in cluster information - Optional.ofNullable(WATCHERS.remove(event.getGroup())) - .ifPresent(watchers -> watchers.parallelStream().forEach(this::notify)); - } - } - - private void notify(Watcher watcher) { - AsyncContext asyncContext = (AsyncContext) watcher.getAsyncContext(); - HttpServletResponse httpServletResponse = (HttpServletResponse) asyncContext.getResponse(); - watcher.setDone(true); - if (logger.isDebugEnabled()) { - logger.debug("notify cluster change event to: {}", asyncContext.getRequest().getRemoteAddr()); - } - httpServletResponse.setStatus(HttpServletResponse.SC_OK); - asyncContext.complete(); - } - - public void registryWatcher(Watcher watcher) { - String group = watcher.getGroup(); - Long term = GROUP_UPDATE_TIME.get(group); - if (term == null || watcher.getTerm() >= term) { - WATCHERS.computeIfAbsent(group, value -> new ConcurrentLinkedQueue<>()).add(watcher); - } - else { - notify(watcher); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftServer.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftServer.java deleted file mode 100644 index fe77a2f10c..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftServer.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import com.alipay.sofa.jraft.Node; -import com.alipay.sofa.jraft.RaftGroupService; -import com.alipay.sofa.jraft.RouteTable; -import com.alipay.sofa.jraft.entity.PeerId; -import com.alipay.sofa.jraft.option.NodeOptions; -import com.alipay.sofa.jraft.rpc.RpcServer; -import com.codahale.metrics.Slf4jReporter; -import io.seata.config.ConfigurationFactory; -import io.seata.core.rpc.Disposable; -import org.apache.commons.io.FileUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_REPORTER_ENABLED; -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_REPORTER_INITIAL_DELAY; - -/** - * @author funkye - */ -public class RaftServer implements Disposable, Closeable { - - private final Logger logger = LoggerFactory.getLogger(getClass()); - - private final RaftStateMachine raftStateMachine; - - private final String groupId; - - private final String groupPath; - - private final NodeOptions nodeOptions; - - private final PeerId serverId; - - private final RpcServer rpcServer; - - private RaftGroupService raftGroupService; - - private Node node; - - public RaftServer(final String dataPath, final String groupId, final PeerId serverId, final NodeOptions nodeOptions, - final RpcServer rpcServer) throws IOException { - this.groupId = groupId; - this.groupPath = dataPath + File.separator + groupId; - // Initialize the state machine - this.raftStateMachine = new RaftStateMachine(groupId); - this.nodeOptions = nodeOptions; - this.serverId = serverId; - this.rpcServer = rpcServer; - } - - public void start() throws IOException { - // Initialization path - FileUtils.forceMkdir(new File(groupPath)); - // Set the state machine to startup parameters - nodeOptions.setFsm(this.raftStateMachine); - // Set the storage path - // Log, must - nodeOptions.setLogUri(groupPath + File.separator + "log"); - // Meta information, must - nodeOptions.setRaftMetaUri(groupPath + File.separator + "raft_meta"); - // Snapshot, optional, is generally recommended - nodeOptions.setSnapshotUri(groupPath + File.separator + "snapshot"); - boolean reporterEnabled = ConfigurationFactory.getInstance().getBoolean(SERVER_RAFT_REPORTER_ENABLED, false); - nodeOptions.setEnableMetrics(reporterEnabled); - // Initialize the raft Group service framework - this.raftGroupService = new RaftGroupService(groupId, serverId, nodeOptions, rpcServer, true); - this.node = this.raftGroupService.start(false); - RouteTable.getInstance().updateConfiguration(groupId, node.getOptions().getInitialConf()); - if (reporterEnabled) { - final Slf4jReporter reporter = Slf4jReporter.forRegistry(node.getNodeMetrics().getMetricRegistry()) - .outputTo(logger) - .convertRatesTo(TimeUnit.SECONDS) - .convertDurationsTo(TimeUnit.MILLISECONDS) - .build(); - reporter.start(ConfigurationFactory.getInstance().getInt(SERVER_RAFT_REPORTER_INITIAL_DELAY, 60), - TimeUnit.MINUTES); - } - } - - public Node getNode() { - return this.node; - } - - public RaftStateMachine getRaftStateMachine() { - return raftStateMachine; - } - - @Override - public void close() { - destroy(); - } - - @Override - public void destroy() { - Optional.ofNullable(raftGroupService).ifPresent(r -> { - r.shutdown(); - try { - r.join(); - } - catch (InterruptedException e) { - logger.warn("Interrupted when RaftServer destroying", e); - } - }); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftServerFactory.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftServerFactory.java deleted file mode 100644 index 1c8d37c20a..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftServerFactory.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft; - -import java.io.Closeable; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import com.alipay.sofa.jraft.CliService; -import com.alipay.sofa.jraft.RaftServiceFactory; -import com.alipay.sofa.jraft.conf.Configuration; -import com.alipay.sofa.jraft.entity.PeerId; -import com.alipay.sofa.jraft.option.CliOptions; -import com.alipay.sofa.jraft.option.NodeOptions; -import com.alipay.sofa.jraft.option.RaftOptions; -import com.alipay.sofa.jraft.rpc.CliClientService; -import com.alipay.sofa.jraft.rpc.RaftRpcServerFactory; -import com.alipay.sofa.jraft.rpc.RpcServer; -import com.alipay.sofa.jraft.rpc.impl.cli.CliClientServiceImpl; -import io.seata.common.ConfigurationKeys; -import io.seata.common.XID; -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.core.rpc.Disposable; -import io.seata.discovery.registry.FileRegistryServiceImpl; -import io.seata.discovery.registry.MultiRegistryFactory; -import io.seata.discovery.registry.RegistryService; -import io.seata.server.store.StoreConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_PORT_CAMEL; -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_SYNC; -import static io.seata.common.DefaultValues.DEFAULT_SERVER_RAFT_ELECTION_TIMEOUT_MS; -import static io.seata.common.DefaultValues.DEFAULT_SESSION_STORE_FILE_DIR; -import static io.seata.common.DefaultValues.DEFAULT_SEATA_GROUP; -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_APPLY_BATCH; -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_DISRUPTOR_BUFFER_SIZE; -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_ELECTION_TIMEOUT_MS; -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_MAX_APPEND_BUFFER_SIZE; -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_MAX_REPLICATOR_INFLIGHT_MSGS; -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_SNAPSHOT_INTERVAL; -import static java.io.File.separator; - -/** - * @author funkye - */ -public class RaftServerFactory implements Disposable, Closeable { - - private static final Logger LOGGER = LoggerFactory.getLogger(RaftServerFactory.class); - - private static final Map RAFT_SERVER_MAP = new HashMap<>(); - - private Boolean raftMode = false; - - private RpcServer rpcServer; - - private static final io.seata.config.Configuration CONFIG = ConfigurationFactory.getInstance(); - - public static RaftServerFactory getInstance() { - return SingletonHandler.INSTANCE; - } - - public static CliService getCliServiceInstance() { - return SingletonHandler.CLI_SERVICE; - } - - public static CliClientService getCliClientServiceInstance() { - return SingletonHandler.CLI_CLIENT_SERVICE; - } - - public void init() { - String initConfStr = CONFIG.getConfig(ConfigurationKeys.SERVER_RAFT_SERVER_ADDR); - StoreConfig.SessionMode storeMode = StoreConfig.getSessionMode(); - raftMode = storeMode.equals(StoreConfig.SessionMode.RAFT); - if (StringUtils.isBlank(initConfStr)) { - if (raftMode) { - throw new IllegalArgumentException( - "Raft store mode must config: " + ConfigurationKeys.SERVER_RAFT_SERVER_ADDR); - } - return; - } - else { - if (raftMode) { - for (RegistryService instance : MultiRegistryFactory.getInstances()) { - if (!(instance instanceof FileRegistryServiceImpl)) { - throw new IllegalArgumentException("Raft store mode not support other Registration Center"); - } - } - } - LOGGER.warn("raft mode and raft cluster is an experimental feature"); - } - final Configuration initConf = new Configuration(); - if (!initConf.parse(initConfStr)) { - throw new IllegalArgumentException("fail to parse initConf:" + initConfStr); - } - int port = Integer.parseInt(System.getProperty(SERVER_RAFT_PORT_CAMEL, "0")); - PeerId serverId = null; - String host = XID.getIpAddress(); - if (port <= 0) { - // Highly available deployments require different nodes - for (PeerId peer : initConf.getPeers()) { - if (StringUtils.equals(peer.getIp(), host)) { - if (serverId != null) { - throw new IllegalArgumentException( - "server.raft.cluster has duplicate ip, For local debugging, use -Dserver.raftPort to specify the raft port"); - } - serverId = peer; - } - } - } - else { - // Local debugging use - serverId = new PeerId(host, port); - } - final String dataPath = CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR, DEFAULT_SESSION_STORE_FILE_DIR) - + separator + "raft" + separator + serverId.getPort(); - String group = CONFIG.getConfig(ConfigurationKeys.SERVER_RAFT_GROUP, DEFAULT_SEATA_GROUP); - try { - // Here you have raft RPC and business RPC using the same RPC server, and you - // can usually do this separately - this.rpcServer = RaftRpcServerFactory.createRaftRpcServer(serverId.getEndpoint()); - RaftServer raftServer = new RaftServer(dataPath, group, serverId, initNodeOptions(initConf), - this.rpcServer); - // as the foundation for multi raft group in the future - RAFT_SERVER_MAP.put(group, raftServer); - } - catch (IOException e) { - throw new IllegalArgumentException("fail init raft cluster:" + e.getMessage(), e); - } - } - - public void start() { - RAFT_SERVER_MAP.forEach((group, raftServer) -> { - try { - raftServer.start(); - } - catch (IOException e) { - LOGGER.error("start seata server raft cluster error, group: {} ", group, e); - throw new RuntimeException(e); - } - LOGGER.info("started seata server raft cluster, group: {} ", group); - }); - if (!this.rpcServer.init(null)) { - throw new RuntimeException("start raft node fail!"); - } - } - - @Override - public void destroy() { - this.close(); - rpcServer = null; - raftMode = false; - } - - @Override - public void close() { - RAFT_SERVER_MAP.forEach((group, raftServer) -> { - raftServer.close(); - LOGGER.info("closed seata server raft cluster, group: {} ", group); - }); - Optional.ofNullable(rpcServer).ifPresent(RpcServer::shutdown); - RAFT_SERVER_MAP.clear(); - } - - public RaftServer getRaftServer(String group) { - return RAFT_SERVER_MAP.get(group); - } - - public Collection getRaftServers() { - return RAFT_SERVER_MAP.values(); - } - - public Boolean isLeader(String group) { - AtomicReference stateMachine = new AtomicReference<>(); - Optional.ofNullable(RAFT_SERVER_MAP.get(group)).ifPresent(raftServer -> { - stateMachine.set(raftServer.getRaftStateMachine()); - }); - RaftStateMachine raftStateMachine = stateMachine.get(); - return !isRaftMode() && RAFT_SERVER_MAP.isEmpty() || (raftStateMachine != null && raftStateMachine.isLeader()); - } - - public Boolean isRaftMode() { - return raftMode; - } - - private RaftOptions initRaftOptions() { - RaftOptions raftOptions = new RaftOptions(); - raftOptions.setApplyBatch(CONFIG.getInt(SERVER_RAFT_APPLY_BATCH, raftOptions.getApplyBatch())); - raftOptions.setMaxAppendBufferSize( - CONFIG.getInt(SERVER_RAFT_MAX_APPEND_BUFFER_SIZE, raftOptions.getMaxAppendBufferSize())); - raftOptions.setDisruptorBufferSize( - CONFIG.getInt(SERVER_RAFT_DISRUPTOR_BUFFER_SIZE, raftOptions.getDisruptorBufferSize())); - raftOptions.setMaxReplicatorInflightMsgs( - CONFIG.getInt(SERVER_RAFT_MAX_REPLICATOR_INFLIGHT_MSGS, raftOptions.getMaxReplicatorInflightMsgs())); - raftOptions.setSync(CONFIG.getBoolean(SERVER_RAFT_SYNC, raftOptions.isSync())); - return raftOptions; - } - - private NodeOptions initNodeOptions(Configuration initConf) { - NodeOptions nodeOptions = new NodeOptions(); - // enable the CLI service. - nodeOptions.setDisableCli(false); - // snapshot should be made every 600 seconds - int snapshotInterval = CONFIG.getInt(SERVER_RAFT_SNAPSHOT_INTERVAL, 60 * 10); - nodeOptions.setSnapshotIntervalSecs(snapshotInterval); - nodeOptions.setRaftOptions(initRaftOptions()); - // set the election timeout to 1 second - nodeOptions.setElectionTimeoutMs( - CONFIG.getInt(SERVER_RAFT_ELECTION_TIMEOUT_MS, DEFAULT_SERVER_RAFT_ELECTION_TIMEOUT_MS)); - // set up the initial cluster configuration - nodeOptions.setInitialConf(initConf); - return nodeOptions; - } - - public static Set groups() { - return RAFT_SERVER_MAP.keySet(); - } - - private static class SingletonHandler { - - private static final RaftServerFactory INSTANCE = new RaftServerFactory(); - - private static final CliService CLI_SERVICE = RaftServiceFactory.createAndInitCliService(new CliOptions()); - - private static final CliClientService CLI_CLIENT_SERVICE = new CliClientServiceImpl(); - static { - CLI_CLIENT_SERVICE.init(new CliOptions()); - } - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftStateMachine.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftStateMachine.java deleted file mode 100644 index f44e0bae73..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/RaftStateMachine.java +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft; - -import com.alipay.sofa.jraft.Closure; -import com.alipay.sofa.jraft.Iterator; -import com.alipay.sofa.jraft.RouteTable; -import com.alipay.sofa.jraft.Status; -import com.alipay.sofa.jraft.conf.Configuration; -import com.alipay.sofa.jraft.core.StateMachineAdapter; -import com.alipay.sofa.jraft.entity.LeaderChangeContext; -import com.alipay.sofa.jraft.storage.snapshot.SnapshotReader; -import com.alipay.sofa.jraft.storage.snapshot.SnapshotWriter; -import io.seata.common.XID; -import io.seata.common.holder.ObjectHolder; -import io.seata.common.metadata.ClusterRole; -import io.seata.common.metadata.Node; -import io.seata.common.store.StoreMode; -import io.seata.common.util.StringUtils; -import io.seata.server.cluster.listener.ClusterChangeEvent; -import io.seata.server.cluster.raft.context.SeataClusterContext; -import io.seata.server.cluster.raft.execute.RaftMsgExecute; -import io.seata.server.cluster.raft.execute.branch.AddBranchSessionExecute; -import io.seata.server.cluster.raft.execute.branch.RemoveBranchSessionExecute; -import io.seata.server.cluster.raft.execute.branch.UpdateBranchSessionExecute; -import io.seata.server.cluster.raft.execute.global.AddGlobalSessionExecute; -import io.seata.server.cluster.raft.execute.global.RemoveGlobalSessionExecute; -import io.seata.server.cluster.raft.execute.global.UpdateGlobalSessionExecute; -import io.seata.server.cluster.raft.execute.lock.BranchReleaseLockExecute; -import io.seata.server.cluster.raft.execute.lock.GlobalReleaseLockExecute; -import io.seata.server.cluster.raft.snapshot.StoreSnapshotFile; -import io.seata.server.cluster.raft.snapshot.metadata.LeaderMetadataSnapshotFile; -import io.seata.server.cluster.raft.snapshot.session.SessionSnapshotFile; -import io.seata.server.cluster.raft.sync.RaftSyncMessageSerializer; -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; -import io.seata.server.cluster.raft.sync.msg.RaftClusterMetadataMsg; -import io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType; -import io.seata.server.cluster.raft.sync.msg.dto.RaftClusterMetadata; -import io.seata.server.cluster.raft.util.RaftTaskUtil; -import io.seata.server.session.SessionHolder; -import io.seata.server.store.StoreConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.core.env.Environment; - -import java.nio.ByteBuffer; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; - -import static io.seata.common.Constants.OBJECT_KEY_SPRING_APPLICATION_CONTEXT; -import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; -import static io.seata.common.DefaultValues.SERVICE_OFFSET_SPRING_BOOT; -import static io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType.*; - -/** - * @author funkye - */ -public class RaftStateMachine extends StateMachineAdapter { - - private static final Logger LOGGER = LoggerFactory.getLogger(RaftStateMachine.class); - - private final String mode; - - private final String group; - - private final List snapshotFiles = new ArrayList<>(); - - private static final Map> EXECUTES = new HashMap<>(); - - private volatile RaftClusterMetadata raftClusterMetadata; - - /** - * Leader term. - */ - private final AtomicLong leaderTerm = new AtomicLong(-1); - - /** - * current term. - */ - private final AtomicLong currentTerm = new AtomicLong(-1); - - public boolean isLeader() { - return this.leaderTerm.get() > 0; - } - - public RaftStateMachine(String group) { - this.group = group; - mode = StoreConfig.getSessionMode().getName(); - EXECUTES.put(REFRESH_CLUSTER_METADATA, syncMsg -> { - refreshClusterMetadata(syncMsg); - return null; - }); - registryStoreSnapshotFile(new LeaderMetadataSnapshotFile(group)); - if (StoreMode.RAFT.getName().equalsIgnoreCase(mode)) { - registryStoreSnapshotFile(new SessionSnapshotFile(group)); - EXECUTES.put(ADD_GLOBAL_SESSION, new AddGlobalSessionExecute()); - EXECUTES.put(ADD_BRANCH_SESSION, new AddBranchSessionExecute()); - EXECUTES.put(REMOVE_BRANCH_SESSION, new RemoveBranchSessionExecute()); - EXECUTES.put(UPDATE_GLOBAL_SESSION_STATUS, new UpdateGlobalSessionExecute()); - EXECUTES.put(RELEASE_GLOBAL_SESSION_LOCK, new GlobalReleaseLockExecute()); - EXECUTES.put(REMOVE_GLOBAL_SESSION, new RemoveGlobalSessionExecute()); - EXECUTES.put(UPDATE_BRANCH_SESSION_STATUS, new UpdateBranchSessionExecute()); - EXECUTES.put(RELEASE_BRANCH_SESSION_LOCK, new BranchReleaseLockExecute()); - } - } - - @Override - public void onApply(Iterator iterator) { - while (iterator.hasNext()) { - Closure done = iterator.done(); - if (done != null) { - // leader does not need to be serialized, just execute the task directly - done.run(Status.OK()); - } - else { - ByteBuffer byteBuffer = iterator.getData(); - // if data is empty, it is only a heartbeat event and can be ignored - if (byteBuffer != null && byteBuffer.hasRemaining()) { - RaftBaseMsg msg = (RaftBaseMsg) RaftSyncMessageSerializer.decode(byteBuffer.array()).getBody(); - // follower executes the corresponding task - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("sync msg: {}", msg); - } - onExecuteRaft(msg); - } - } - iterator.next(); - } - } - - @Override - public void onSnapshotSave(final SnapshotWriter writer, final Closure done) { - if (!StringUtils.equals(StoreConfig.SessionMode.RAFT.getName(), mode)) { - done.run(Status.OK()); - return; - } - long current = System.currentTimeMillis(); - for (StoreSnapshotFile snapshotFile : snapshotFiles) { - Status status = snapshotFile.save(writer); - if (!status.isOk()) { - done.run(status); - return; - } - } - LOGGER.info("groupId: {}, onSnapshotSave cost: {} ms.", group, System.currentTimeMillis() - current); - done.run(Status.OK()); - } - - @Override - public boolean onSnapshotLoad(final SnapshotReader reader) { - if (!StringUtils.equals(StoreConfig.SessionMode.RAFT.getName(), mode)) { - return true; - } - if (isLeader()) { - if (LOGGER.isWarnEnabled()) { - LOGGER.warn("Leader is not supposed to load snapshot"); - } - return false; - } - long current = System.currentTimeMillis(); - for (StoreSnapshotFile snapshotFile : snapshotFiles) { - if (!snapshotFile.load(reader)) { - return false; - } - } - LOGGER.info("groupId: {}, onSnapshotLoad cost: {} ms.", group, System.currentTimeMillis() - current); - return true; - } - - @Override - public void onLeaderStart(final long term) { - boolean leader = isLeader(); - this.leaderTerm.set(term); - LOGGER.info("groupId: {}, onLeaderStart: term={}.", group, term); - this.currentTerm.set(term); - SeataClusterContext.bindGroup(group); - syncMetadata(); - if (!leader && RaftServerFactory.getInstance().isRaftMode()) { - CompletableFuture.runAsync(() -> { - LOGGER.info("reload session, groupId: {}, session map size: {} ", group, - SessionHolder.getRootSessionManager().allSessions().size()); - SeataClusterContext.bindGroup(group); - try { - // become the leader again,reloading global session - SessionHolder.reload(SessionHolder.getRootSessionManager().allSessions(), - StoreConfig.SessionMode.RAFT, false); - } - finally { - SeataClusterContext.unbindGroup(); - } - }); - } - } - - @Override - public void onLeaderStop(final Status status) { - this.leaderTerm.set(-1); - LOGGER.info("groupId: {}, onLeaderStop: status={}.", group, status); - } - - @Override - public void onStopFollowing(final LeaderChangeContext ctx) { - LOGGER.info("groupId: {}, onStopFollowing: {}.", group, ctx); - } - - @Override - public void onStartFollowing(final LeaderChangeContext ctx) { - LOGGER.info("groupId: {}, onStartFollowing: {}.", group, ctx); - this.currentTerm.set(ctx.getTerm()); - } - - @Override - public void onConfigurationCommitted(Configuration conf) { - LOGGER.info("groupId: {}, onConfigurationCommitted: {}.", group, conf); - syncMetadata(); - RouteTable.getInstance().updateConfiguration(group, conf); - } - - private void syncMetadata() { - if (isLeader()) { - SeataClusterContext.bindGroup(group); - try { - RaftClusterMetadataMsg raftClusterMetadataMsg = new RaftClusterMetadataMsg( - createNewRaftClusterMetadata()); - RaftTaskUtil.createTask(status -> refreshClusterMetadata(raftClusterMetadataMsg), - raftClusterMetadataMsg, null); - } - catch (Exception e) { - LOGGER.error(e.getMessage(), e); - } - finally { - SeataClusterContext.unbindGroup(); - } - } - } - - private void onExecuteRaft(RaftBaseMsg msg) { - RaftMsgExecute execute = EXECUTES.get(msg.getMsgType()); - if (execute == null) { - throw new RuntimeException( - "the state machine does not allow events that cannot be executed, please feedback the information to the Seata community !!! msg: " - + msg); - } - try { - execute.execute(msg); - } - catch (Throwable e) { - LOGGER.error("Message synchronization failure: {}, msgType: {}", e.getMessage(), msg.getMsgType(), e); - throw new RuntimeException(e); - } - } - - public AtomicLong getCurrentTerm() { - return currentTerm; - } - - public void registryStoreSnapshotFile(StoreSnapshotFile storeSnapshotFile) { - snapshotFiles.add(storeSnapshotFile); - } - - public RaftClusterMetadata getRaftLeaderMetadata() { - return raftClusterMetadata; - } - - public void setRaftLeaderMetadata(RaftClusterMetadata raftClusterMetadata) { - this.raftClusterMetadata = raftClusterMetadata; - } - - public RaftClusterMetadata createNewRaftClusterMetadata() { - RaftClusterMetadata metadata = new RaftClusterMetadata(this.currentTerm.get()); - Node leader = metadata.createNode(XID.getIpAddress(), XID.getPort(), - Integer.parseInt( - ((Environment) ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT)) - .getProperty("server.port", String.valueOf(8088))), - group, Collections.emptyMap()); - leader.setRole(ClusterRole.LEADER); - metadata.setLeader(leader); - Configuration configuration = RouteTable.getInstance().getConfiguration(this.group); - List learners = configuration.getLearners().stream().map(learner -> { - int nettyPort = learner.getPort() - SERVICE_OFFSET_SPRING_BOOT; - Node learnerNode = metadata.createNode(learner.getIp(), nettyPort, nettyPort - SERVICE_OFFSET_SPRING_BOOT, - this.group, Collections.emptyMap()); - learnerNode.setRole(ClusterRole.LEARNER); - return learnerNode; - }).collect(Collectors.toList()); - metadata.setLearner(learners); - List followers = configuration.getPeers().stream().map(follower -> { - int nettyPort = follower.getPort() - SERVICE_OFFSET_SPRING_BOOT; - Node followerNode = metadata.createNode(follower.getIp(), nettyPort, nettyPort - SERVICE_OFFSET_SPRING_BOOT, - this.group, Collections.emptyMap()); - followerNode.setRole(ClusterRole.FOLLOWER); - return followerNode; - }).collect(Collectors.toList()); - metadata.setFollowers(followers); - return metadata; - } - - public void refreshClusterMetadata(RaftBaseMsg syncMsg) { - raftClusterMetadata = ((RaftClusterMetadataMsg) syncMsg).getRaftClusterMetadata(); - ((ApplicationEventPublisher) ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_APPLICATION_CONTEXT)) - .publishEvent(new ClusterChangeEvent(this, group, raftClusterMetadata.getTerm(), this.isLeader())); - LOGGER.info("groupId: {}, refresh cluster metadata: {}", group, raftClusterMetadata); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/context/SeataClusterContext.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/context/SeataClusterContext.java deleted file mode 100644 index cee3477648..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/context/SeataClusterContext.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.context; - -import io.seata.common.ConfigurationKeys; -import io.seata.config.ConfigurationFactory; -import io.seata.core.context.ContextCore; -import io.seata.core.context.ContextCoreLoader; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import static io.seata.common.DefaultValues.DEFAULT_SEATA_GROUP; - -/** - * @author funkye - */ -public final class SeataClusterContext { - - private static final String GROUP = ConfigurationFactory.getInstance() - .getConfig(ConfigurationKeys.SERVER_RAFT_GROUP, DEFAULT_SEATA_GROUP); - - private SeataClusterContext() { - } - - /** - * The constant KEY_GROUP. - */ - public static final String KEY_GROUP = "TX_GROUP"; - - private static ContextCore CONTEXT_HOLDER = ContextCoreLoader.load(); - - /** - * Bind group. - * @param group the group - */ - public static void bindGroup(@Nonnull String group) { - CONTEXT_HOLDER.put(KEY_GROUP, group); - } - - /** - * Bind group. - * - */ - public static String bindGroup() { - CONTEXT_HOLDER.put(KEY_GROUP, GROUP); - return GROUP; - } - - /** - * Unbind group. - */ - public static void unbindGroup() { - CONTEXT_HOLDER.remove(KEY_GROUP); - } - - @Nullable - public static String getGroup() { - return (String) CONTEXT_HOLDER.get(KEY_GROUP); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/AbstractRaftMsgExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/AbstractRaftMsgExecute.java deleted file mode 100644 index 22cd7007ed..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/AbstractRaftMsgExecute.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.seata.server.lock.LockerManagerFactory; -import io.seata.server.storage.raft.lock.RaftLockManager; - -/** - * @author jianbin.chen - */ -public abstract class AbstractRaftMsgExecute implements RaftMsgExecute { - - protected final Logger logger = LoggerFactory.getLogger(getClass()); - - protected RaftLockManager raftLockManager = (RaftLockManager) LockerManagerFactory.getLockManager(); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/RaftMsgExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/RaftMsgExecute.java deleted file mode 100644 index 22e7785443..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/RaftMsgExecute.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute; - -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; - -/** - * @author jianbin.chen - */ -public interface RaftMsgExecute { - - /** - * Execute t. - * @param syncMsg the sessionSyncMsg - * @return the t - * @throws Throwable the throwable - */ - T execute(RaftBaseMsg syncMsg) throws Throwable; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/AddBranchSessionExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/AddBranchSessionExecute.java deleted file mode 100644 index d6a90762e9..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/AddBranchSessionExecute.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute.branch; - -import io.seata.server.cluster.raft.execute.AbstractRaftMsgExecute; -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; -import io.seata.server.cluster.raft.sync.msg.RaftBranchSessionSyncMsg; -import io.seata.server.cluster.raft.sync.msg.dto.BranchTransactionDTO; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import io.seata.server.storage.SessionConverter; -import io.seata.server.storage.raft.session.RaftSessionManager; - -/** - * @author jianbin.chen - */ -public class AddBranchSessionExecute extends AbstractRaftMsgExecute { - - @Override - public Boolean execute(RaftBaseMsg syncMsg) throws Throwable { - RaftBranchSessionSyncMsg sessionSyncMsg = (RaftBranchSessionSyncMsg) syncMsg; - RaftSessionManager raftSessionManager = (RaftSessionManager) SessionHolder - .getRootSessionManager(sessionSyncMsg.getGroup()); - BranchTransactionDTO branchTransactionDTO = sessionSyncMsg.getBranchSession(); - GlobalSession globalSession = raftSessionManager.findGlobalSession(branchTransactionDTO.getXid()); - BranchSession branchSession = SessionConverter.convertBranchSession(branchTransactionDTO); - branchSession.lock(); - globalSession.add(branchSession); - if (logger.isDebugEnabled()) { - logger.debug("addBranch xid: {},branchId: {}", branchTransactionDTO.getXid(), - branchTransactionDTO.getBranchId()); - } - return true; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/RemoveBranchSessionExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/RemoveBranchSessionExecute.java deleted file mode 100644 index 4cce6167c7..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/RemoveBranchSessionExecute.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute.branch; - -import io.seata.server.cluster.raft.execute.AbstractRaftMsgExecute; -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; -import io.seata.server.cluster.raft.sync.msg.RaftBranchSessionSyncMsg; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import io.seata.server.storage.raft.session.RaftSessionManager; - -/** - * @author jianbin.chen - */ -public class RemoveBranchSessionExecute extends AbstractRaftMsgExecute { - - @Override - public Boolean execute(RaftBaseMsg syncMsg) throws Throwable { - RaftBranchSessionSyncMsg sessionSyncMsg = (RaftBranchSessionSyncMsg) syncMsg; - RaftSessionManager raftSessionManager = (RaftSessionManager) SessionHolder - .getRootSessionManager(sessionSyncMsg.getGroup()); - GlobalSession globalSession = raftSessionManager.findGlobalSession(sessionSyncMsg.getBranchSession().getXid()); - if (globalSession != null) { - BranchSession branchSession = globalSession.getBranch(sessionSyncMsg.getBranchSession().getBranchId()); - if (branchSession != null) { - raftLockManager.localReleaseLock(branchSession); - globalSession.remove(branchSession); - } - if (logger.isDebugEnabled()) { - logger.debug("removeBranch xid: {},branchId: {}", globalSession.getXid(), - sessionSyncMsg.getBranchSession().getBranchId()); - } - } - return true; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/UpdateBranchSessionExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/UpdateBranchSessionExecute.java deleted file mode 100644 index 50f68c46a6..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/branch/UpdateBranchSessionExecute.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute.branch; - -import io.seata.core.model.BranchStatus; -import io.seata.server.cluster.raft.execute.AbstractRaftMsgExecute; -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; -import io.seata.server.cluster.raft.sync.msg.RaftBranchSessionSyncMsg; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import io.seata.server.storage.raft.session.RaftSessionManager; - -/** - * @author jianbin.chen - */ -public class UpdateBranchSessionExecute extends AbstractRaftMsgExecute { - - @Override - public Boolean execute(RaftBaseMsg syncMsg) throws Throwable { - RaftBranchSessionSyncMsg sessionSyncMsg = (RaftBranchSessionSyncMsg) syncMsg; - RaftSessionManager raftSessionManager = (RaftSessionManager) SessionHolder - .getRootSessionManager(sessionSyncMsg.getGroup()); - GlobalSession globalSession = raftSessionManager.findGlobalSession(sessionSyncMsg.getBranchSession().getXid()); - BranchSession branchSession = globalSession.getBranch(sessionSyncMsg.getBranchSession().getBranchId()); - BranchStatus status = BranchStatus.get(sessionSyncMsg.getBranchSession().getStatus()); - branchSession.setStatus(status); - if (logger.isDebugEnabled()) { - logger.debug("update branch: {} , status: {}", branchSession.getBranchId(), branchSession.getStatus()); - } - return true; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/AddGlobalSessionExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/AddGlobalSessionExecute.java deleted file mode 100644 index 21a51a25e0..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/AddGlobalSessionExecute.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute.global; - -import io.seata.server.cluster.raft.execute.AbstractRaftMsgExecute; -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; -import io.seata.server.cluster.raft.sync.msg.RaftGlobalSessionSyncMsg; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import io.seata.server.storage.SessionConverter; -import io.seata.server.storage.raft.session.RaftSessionManager; - -/** - * @author jianbin.chen - */ -public class AddGlobalSessionExecute extends AbstractRaftMsgExecute { - - @Override - public Boolean execute(RaftBaseMsg syncMsg) throws Throwable { - RaftGlobalSessionSyncMsg sessionSyncMsg = (RaftGlobalSessionSyncMsg) syncMsg; - RaftSessionManager raftSessionManager = (RaftSessionManager) SessionHolder - .getRootSessionManager(sessionSyncMsg.getGroup()); - GlobalSession globalSession = SessionConverter.convertGlobalSession(sessionSyncMsg.getGlobalSession()); - raftSessionManager.addGlobalSession(globalSession); - if (logger.isDebugEnabled()) { - logger.debug("add session xid: {}", globalSession.getXid()); - } - return true; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/RemoveGlobalSessionExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/RemoveGlobalSessionExecute.java deleted file mode 100644 index 4a87d918de..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/RemoveGlobalSessionExecute.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute.global; - -import java.util.Optional; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.core.exception.TransactionException; -import io.seata.server.cluster.raft.execute.AbstractRaftMsgExecute; -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; -import io.seata.server.cluster.raft.sync.msg.RaftGlobalSessionSyncMsg; -import io.seata.server.session.SessionHolder; -import io.seata.server.storage.raft.session.RaftSessionManager; - -/** - * @author jianbin.chen - */ -public class RemoveGlobalSessionExecute extends AbstractRaftMsgExecute { - - private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(1, 1, Integer.MAX_VALUE, - TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(2048), - new NamedThreadFactory("RemoveGlobalSessionExecute", 1), new ThreadPoolExecutor.CallerRunsPolicy()); - - @Override - public Boolean execute(RaftBaseMsg syncMsg) throws Throwable { - RaftGlobalSessionSyncMsg sessionSyncMsg = (RaftGlobalSessionSyncMsg) syncMsg; - // when the global transaction needs to be deleted, it does not affect any - // consistency issues, and can be - // deleted in an asynchronous thread to improve the throughput of the state - // machine - RaftSessionManager raftSessionManager = (RaftSessionManager) SessionHolder - .getRootSessionManager(sessionSyncMsg.getGroup()); - Optional.ofNullable(raftSessionManager.findGlobalSession(sessionSyncMsg.getGlobalSession().getXid())) - .ifPresent(globalSession -> { - try { - raftLockManager.localReleaseGlobalSessionLock(globalSession); - EXECUTOR.execute(() -> { - try { - raftSessionManager.removeGlobalSession(globalSession); - if (logger.isDebugEnabled()) { - logger.debug("remove session xid: {}", globalSession.getXid()); - } - } - catch (TransactionException e) { - logger.error("remove global fail error:{}", e.getMessage()); - } - }); - } - catch (TransactionException e) { - logger.error(e.getMessage(), e); - } - }); - return true; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/UpdateGlobalSessionExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/UpdateGlobalSessionExecute.java deleted file mode 100644 index a6095c2ed5..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/global/UpdateGlobalSessionExecute.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute.global; - -import io.seata.core.model.GlobalStatus; -import io.seata.core.model.LockStatus; -import io.seata.server.cluster.raft.execute.AbstractRaftMsgExecute; -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; -import io.seata.server.cluster.raft.sync.msg.RaftGlobalSessionSyncMsg; -import io.seata.server.cluster.raft.sync.msg.dto.GlobalTransactionDTO; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import io.seata.server.storage.raft.session.RaftSessionManager; - -/** - * @author jianbin.chen - */ -public class UpdateGlobalSessionExecute extends AbstractRaftMsgExecute { - - @Override - public Boolean execute(RaftBaseMsg syncMsg) throws Throwable { - RaftGlobalSessionSyncMsg sessionSyncMsg = (RaftGlobalSessionSyncMsg) syncMsg; - RaftSessionManager raftSessionManager = (RaftSessionManager) SessionHolder - .getRootSessionManager(sessionSyncMsg.getGroup()); - GlobalTransactionDTO globalTransactionDTO = sessionSyncMsg.getGlobalSession(); - GlobalSession globalSession = raftSessionManager.findGlobalSession(globalTransactionDTO.getXid()); - if (globalSession != null) { - globalSession.setStatus(GlobalStatus.get(globalTransactionDTO.getStatus())); - if (GlobalStatus.RollbackRetrying.equals(globalSession.getStatus()) - || GlobalStatus.Rollbacking.equals(globalSession.getStatus()) - || GlobalStatus.TimeoutRollbacking.equals(globalSession.getStatus())) { - globalSession.getBranchSessions() - .parallelStream() - .forEach(branchSession -> branchSession.setLockStatus(LockStatus.Rollbacking)); - } - if (logger.isDebugEnabled()) { - logger.debug("xid: {}, change status: {}", globalSession.getXid(), globalSession.getStatus()); - } - } - return true; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/lock/BranchReleaseLockExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/lock/BranchReleaseLockExecute.java deleted file mode 100644 index 5bc6cc25ad..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/lock/BranchReleaseLockExecute.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute.lock; - -import io.seata.server.cluster.raft.execute.AbstractRaftMsgExecute; -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; -import io.seata.server.cluster.raft.sync.msg.RaftBranchSessionSyncMsg; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; - -/** - * @author jianbin.chen - */ -public class BranchReleaseLockExecute extends AbstractRaftMsgExecute { - - @Override - public Boolean execute(RaftBaseMsg syncMsg) throws Throwable { - RaftBranchSessionSyncMsg sessionSyncMsg = (RaftBranchSessionSyncMsg) syncMsg; - GlobalSession globalSession = SessionHolder.getRootSessionManager() - .findGlobalSession(sessionSyncMsg.getBranchSession().getXid()); - BranchSession branchSession = globalSession.getBranch(sessionSyncMsg.getBranchSession().getBranchId()); - if (branchSession != null) { - if (logger.isDebugEnabled()) { - logger.debug("releaseBranchSessionLock xid: {}", globalSession.getXid()); - } - return raftLockManager.localReleaseLock(branchSession); - } - return false; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/lock/GlobalReleaseLockExecute.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/lock/GlobalReleaseLockExecute.java deleted file mode 100644 index c5c35cb109..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/execute/lock/GlobalReleaseLockExecute.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.execute.lock; - -import io.seata.server.cluster.raft.execute.AbstractRaftMsgExecute; -import io.seata.server.cluster.raft.sync.msg.RaftBaseMsg; -import io.seata.server.cluster.raft.sync.msg.RaftGlobalSessionSyncMsg; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; - -/** - * @author jianbin.chen - */ -public class GlobalReleaseLockExecute extends AbstractRaftMsgExecute { - - @Override - public Boolean execute(RaftBaseMsg syncMsg) throws Throwable { - RaftGlobalSessionSyncMsg sessionSyncMsg = (RaftGlobalSessionSyncMsg) syncMsg; - GlobalSession globalSession = SessionHolder.getRootSessionManager() - .findGlobalSession(sessionSyncMsg.getGlobalSession().getXid()); - if (globalSession != null) { - if (logger.isDebugEnabled()) { - logger.debug("releaseGlobalSessionLock xid: {}", globalSession.getXid()); - } - globalSession.setActive(false); - return raftLockManager.localReleaseGlobalSessionLock(globalSession); - } - return false; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/serializer/JacksonSerializer.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/serializer/JacksonSerializer.java deleted file mode 100644 index 4183c2ea14..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/serializer/JacksonSerializer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.serializer; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.seata.common.loader.LoadLevel; -import io.seata.core.serializer.Serializer; - -import java.io.IOException; - -/** - * @author jianbin.chen - */ -@LoadLevel(name = "JACKSON") -public class JacksonSerializer implements Serializer { - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Override - public byte[] serialize(T t) { - try { - JsonInfo jsonInfo = new JsonInfo(objectMapper.writeValueAsBytes(t), t.getClass()); - return objectMapper.writeValueAsBytes(jsonInfo); - } - catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - @Override - public T deserialize(byte[] bytes) { - try { - JsonInfo jsonInfo = objectMapper.readValue(bytes, JsonInfo.class); - return (T) objectMapper.readValue(jsonInfo.getObj(), jsonInfo.getClz()); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - - static class JsonInfo { - - byte[] obj; - - Class clz; - - JsonInfo() { - } - - JsonInfo(byte[] obj, Class clz) { - this.obj = obj; - this.clz = clz; - } - - public byte[] getObj() { - return obj; - } - - public void setObj(byte[] obj) { - this.obj = obj; - } - - public Class getClz() { - return clz; - } - - public void setClz(Class clz) { - this.clz = clz; - } - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/RaftSnapshot.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/RaftSnapshot.java deleted file mode 100644 index 10ebfafe96..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/RaftSnapshot.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.snapshot; - -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.core.compressor.CompressorType; -import io.seata.core.protocol.Version; -import io.seata.core.serializer.SerializerType; - -import java.io.Serializable; - -import static io.seata.common.ConfigurationKeys.SERVER_RAFT_COMPRESSOR; -import static io.seata.common.DefaultValues.DEFAULT_RAFT_COMPRESSOR; -import static io.seata.common.DefaultValues.DEFAULT_RAFT_SERIALIZATION; - -/** - * @author funkye - */ -public class RaftSnapshot implements Serializable { - - private byte codec = SerializerType.getByName(DEFAULT_RAFT_SERIALIZATION).getCode(); - - private byte compressor = CompressorType - .getByName(ConfigurationFactory.getInstance().getConfig(SERVER_RAFT_COMPRESSOR, DEFAULT_RAFT_COMPRESSOR)) - .getCode(); - - private Object body; - - private String version = Version.getCurrent(); - - private SnapshotType type; - - /** - * Gets body. - * @return the body - */ - public Object getBody() { - return body; - } - - /** - * Sets body. - * @param body the body - */ - public void setBody(Object body) { - this.body = body; - } - - /** - * Gets codec. - * @return the codec - */ - public byte getCodec() { - return codec; - } - - /** - * Sets codec. - * @param codec the codec - * @return the codec - */ - public RaftSnapshot setCodec(byte codec) { - this.codec = codec; - return this; - } - - /** - * Gets compressor. - * @return the compressor - */ - public byte getCompressor() { - return compressor; - } - - /** - * Sets compressor. - * @param compressor the compressor - * @return the compressor - */ - public RaftSnapshot setCompressor(byte compressor) { - this.compressor = compressor; - return this; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public SnapshotType getType() { - return type; - } - - public void setType(SnapshotType type) { - this.type = type; - } - - @Override - public String toString() { - return StringUtils.toString(this); - } - - public enum SnapshotType { - - /** - * session snapshot. - */ - session("session"), - /** - * leader metadata snapshot. - */ - leader_metadata("leader_metadata"); - - final String type; - - SnapshotType(String type) { - this.type = type; - } - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/RaftSnapshotSerializer.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/RaftSnapshotSerializer.java deleted file mode 100644 index 3758da803f..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/RaftSnapshotSerializer.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.snapshot; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.Optional; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.core.compressor.CompressorFactory; -import io.seata.core.serializer.Serializer; -import io.seata.core.serializer.SerializerType; - -/** - * @author funkye - */ -public class RaftSnapshotSerializer { - - private static final Logger LOGGER = LoggerFactory.getLogger(RaftSnapshotSerializer.class); - - public static byte[] encode(RaftSnapshot raftSnapshot) throws IOException { - try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos)) { - Serializer serializer = EnhancedServiceLoader.load(Serializer.class, - SerializerType.getByCode(raftSnapshot.getCodec()).name()); - Optional.ofNullable(raftSnapshot.getBody()) - .ifPresent(value -> raftSnapshot.setBody(CompressorFactory.getCompressor(raftSnapshot.getCompressor()) - .compress(serializer.serialize(value)))); - oos.writeObject(raftSnapshot); - return bos.toByteArray(); - } - } - - public static RaftSnapshot decode(byte[] raftSnapshotByte) throws IOException { - try (ByteArrayInputStream bin = new ByteArrayInputStream(raftSnapshotByte); - ObjectInputStream ois = new ObjectInputStream(bin)) { - RaftSnapshot raftSnapshot = (RaftSnapshot) ois.readObject(); - Serializer serializer = EnhancedServiceLoader.load(Serializer.class, - SerializerType.getByCode(raftSnapshot.getCodec()).name()); - Optional.ofNullable(raftSnapshot.getBody()) - .ifPresent(value -> raftSnapshot - .setBody(serializer.deserialize(CompressorFactory.getCompressor(raftSnapshot.getCompressor()) - .decompress((byte[]) raftSnapshot.getBody())))); - return raftSnapshot; - } - catch (ClassNotFoundException e) { - LOGGER.info("Failed to read raft snapshot: {}", e.getMessage(), e); - throw new IOException(e); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/StoreSnapshotFile.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/StoreSnapshotFile.java deleted file mode 100644 index 8714618f70..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/StoreSnapshotFile.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.snapshot; - -import com.alipay.sofa.jraft.Status; -import com.alipay.sofa.jraft.storage.snapshot.SnapshotReader; -import com.alipay.sofa.jraft.storage.snapshot.SnapshotWriter; -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.io.IOException; - -/** - * @author funkye - */ -public interface StoreSnapshotFile { - - /** - * Save a snapshot . - * @param writer snapshot writer - * @return true if save succeed - */ - Status save(SnapshotWriter writer); - - /** - * Load snapshot for the specified region. - * @param reader snapshot reader - * @return true if load succeed - */ - boolean load(SnapshotReader reader); - - default boolean save(final RaftSnapshot value, String path) throws IOException { - FileUtils.writeByteArrayToFile(new File(path), RaftSnapshotSerializer.encode(value)); - return true; - } - - /** - * Save value to snapshot file. - */ - default Object load(String path) throws IOException { - RaftSnapshot raftSnapshot = RaftSnapshotSerializer.decode(FileUtils.readFileToByteArray(new File(path))); - return raftSnapshot.getBody(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/metadata/LeaderMetadataSnapshotFile.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/metadata/LeaderMetadataSnapshotFile.java deleted file mode 100644 index 94341c1eac..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/metadata/LeaderMetadataSnapshotFile.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.snapshot.metadata; - -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import com.alipay.sofa.jraft.Status; -import com.alipay.sofa.jraft.error.RaftError; -import com.alipay.sofa.jraft.storage.snapshot.SnapshotReader; -import com.alipay.sofa.jraft.storage.snapshot.SnapshotWriter; -import io.seata.server.cluster.raft.RaftServerFactory; -import io.seata.server.cluster.raft.snapshot.RaftSnapshot; -import io.seata.server.cluster.raft.snapshot.StoreSnapshotFile; -import io.seata.server.cluster.raft.sync.msg.dto.RaftClusterMetadata; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author jianbin.chen - */ -public class LeaderMetadataSnapshotFile implements Serializable, StoreSnapshotFile { - - private static final long serialVersionUID = 78637164618855724L; - - private static final Logger LOGGER = LoggerFactory.getLogger(LeaderMetadataSnapshotFile.class); - - private final String group; - - private final String fileName = "leader_metadata"; - - public LeaderMetadataSnapshotFile(String group) { - this.group = group; - } - - @Override - public Status save(SnapshotWriter writer) { - RaftSnapshot raftSnapshot = new RaftSnapshot(); - RaftClusterMetadata raftClusterMetadata = RaftServerFactory.getInstance() - .getRaftServer(group) - .getRaftStateMachine() - .getRaftLeaderMetadata(); - raftSnapshot.setBody(raftClusterMetadata); - raftSnapshot.setType(RaftSnapshot.SnapshotType.leader_metadata); - String path = new StringBuilder(writer.getPath()).append(File.separator).append(fileName).toString(); - try { - if (save(raftSnapshot, path)) { - if (writer.addFile(fileName)) { - return Status.OK(); - } - else { - return new Status(RaftError.EIO, "Fail to add file to writer"); - } - } - } - catch (IOException e) { - LOGGER.error("Fail to save groupId: {} snapshot {}", group, path, e); - } - return new Status(RaftError.EIO, "Fail to save groupId: " + group + " snapshot %s", path); - } - - @Override - public boolean load(SnapshotReader reader) { - if (reader.getFileMeta(fileName) == null) { - LOGGER.error("Fail to find data file in {}", reader.getPath()); - return false; - } - String path = new StringBuilder(reader.getPath()).append(File.separator).append(fileName).toString(); - try { - RaftClusterMetadata raftClusterMetadata = (RaftClusterMetadata) load(path); - RaftServerFactory.getInstance() - .getRaftServer(group) - .getRaftStateMachine() - .setRaftLeaderMetadata(raftClusterMetadata); - return true; - } - catch (final Exception e) { - LOGGER.error("fail to load snapshot from {}", path, e); - return false; - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/session/RaftSessionSnapshot.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/session/RaftSessionSnapshot.java deleted file mode 100644 index a097fae939..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/session/RaftSessionSnapshot.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.snapshot.session; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; -import io.seata.common.util.CollectionUtils; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.GlobalStatus; -import io.seata.core.model.LockStatus; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class RaftSessionSnapshot implements java.io.Serializable { - - private static final Logger LOGGER = LoggerFactory.getLogger(RaftSessionSnapshot.class); - - private static final long serialVersionUID = -2257327786007900291L; - - private Map/* branch sessions */> globalsessions = new ConcurrentHashMap<>(); - - public Map> getGlobalsessions() { - return globalsessions; - } - - public void setGlobalsessions(Map> globalsessions) { - this.globalsessions = globalsessions; - } - - public Map convert2GlobalSession() { - Map sessionMap = new HashMap<>(); - globalsessions.forEach((globalSessionByte, branchSessionBytes) -> { - GlobalSession globalSession = new GlobalSession(); - globalSession.decode(globalSessionByte); - branchSessionBytes.forEach(branch -> { - BranchSession branchSession = new BranchSession(); - branchSession.decode(branch); - if (globalSession.isActive()) { - try { - branchSession.lock(); - } - catch (TransactionException e) { - LOGGER.error(e.getMessage()); - } - } - globalSession.add(branchSession); - }); - if (GlobalStatus.Rollbacking.equals(globalSession.getStatus()) - || GlobalStatus.TimeoutRollbacking.equals(globalSession.getStatus())) { - globalSession.getBranchSessions() - .parallelStream() - .forEach(branchSession -> branchSession.setLockStatus(LockStatus.Rollbacking)); - } - sessionMap.put(globalSession.getXid(), globalSession); - }); - return sessionMap; - } - - public void convert2GlobalSessionByte(GlobalSession globalSession) { - byte[] globalSessionByte = globalSession.encode(); - if (CollectionUtils.isEmpty(globalSession.getBranchSessions())) { - globalsessions.put(globalSessionByte, Collections.emptyList()); - } - else { - globalsessions.put(globalSessionByte, - globalSession.getBranchSessions() - .parallelStream() - .map(branch -> branch.encode()) - .collect(Collectors.toList())); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/session/SessionSnapshotFile.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/session/SessionSnapshotFile.java deleted file mode 100644 index b0be52493e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/snapshot/session/SessionSnapshotFile.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.snapshot.session; - -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.util.Map; -import com.alipay.sofa.jraft.Status; -import com.alipay.sofa.jraft.error.RaftError; -import com.alipay.sofa.jraft.storage.snapshot.SnapshotReader; -import com.alipay.sofa.jraft.storage.snapshot.SnapshotWriter; -import io.seata.server.cluster.raft.snapshot.RaftSnapshot; -import io.seata.server.cluster.raft.snapshot.StoreSnapshotFile; -import io.seata.server.lock.LockerManagerFactory; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import io.seata.server.storage.raft.session.RaftSessionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author funkye - */ -public class SessionSnapshotFile implements Serializable, StoreSnapshotFile { - - private static final Logger LOGGER = LoggerFactory.getLogger(SessionSnapshotFile.class); - - private static final long serialVersionUID = 7942307427240595916L; - - String group; - - String fileName = "session"; - - public SessionSnapshotFile(String group) { - this.group = group; - } - - @Override - public Status save(SnapshotWriter writer) { - RaftSessionManager raftSessionManager = (RaftSessionManager) SessionHolder.getRootSessionManager(group); - Map sessionMap = raftSessionManager.getSessionMap(); - RaftSessionSnapshot sessionSnapshot = new RaftSessionSnapshot(); - sessionMap.forEach((xid, session) -> sessionSnapshot.convert2GlobalSessionByte(session)); - RaftSnapshot raftSnapshot = new RaftSnapshot(); - raftSnapshot.setBody(sessionSnapshot); - raftSnapshot.setType(RaftSnapshot.SnapshotType.session); - LOGGER.info("groupId: {}, global session size: {}", group, sessionSnapshot.getGlobalsessions().size()); - String path = new StringBuilder(writer.getPath()).append(File.separator).append(fileName).toString(); - try { - if (save(raftSnapshot, path)) { - if (writer.addFile(fileName)) { - return Status.OK(); - } - else { - return new Status(RaftError.EIO, "Fail to add file to writer"); - } - } - } - catch (IOException e) { - LOGGER.error("Fail to save groupId: {} snapshot {}", group, path, e); - } - return new Status(RaftError.EIO, "Fail to save groupId: " + group + " snapshot %s", path); - } - - @Override - public boolean load(SnapshotReader reader) { - if (reader.getFileMeta(fileName) == null) { - LOGGER.error("Fail to find data file in {}", reader.getPath()); - return false; - } - String path = new StringBuilder(reader.getPath()).append(File.separator).append(fileName).toString(); - try { - LOGGER.info("on snapshot load start index: {}", reader.load().getLastIncludedIndex()); - RaftSessionSnapshot sessionSnapshot = (RaftSessionSnapshot) load(path); - RaftSessionManager raftSessionManager = (RaftSessionManager) SessionHolder.getRootSessionManager(group); - Map rootSessionMap = raftSessionManager.getSessionMap(); - // be sure to clear the data before loading it, because this is a full - // overwrite update - LockerManagerFactory.getLockManager().cleanAllLocks(); - rootSessionMap.clear(); - rootSessionMap.putAll(sessionSnapshot.convert2GlobalSession()); - if (LOGGER.isInfoEnabled()) { - LOGGER.info("on snapshot load end index: {}", reader.load().getLastIncludedIndex()); - } - return true; - } - catch (final Exception e) { - LOGGER.error("fail to load snapshot from {}", path, e); - return false; - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/RaftSyncMessageSerializer.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/RaftSyncMessageSerializer.java deleted file mode 100644 index d89cf3cf5a..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/RaftSyncMessageSerializer.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.Optional; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.core.compressor.CompressorFactory; -import io.seata.core.serializer.Serializer; -import io.seata.core.serializer.SerializerType; -import io.seata.server.cluster.raft.sync.msg.RaftSyncMessage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author funkye - */ -public class RaftSyncMessageSerializer { - - private static final Logger LOGGER = LoggerFactory.getLogger(RaftSyncMessageSerializer.class); - - public static byte[] encode(RaftSyncMessage raftSyncMessage) throws IOException { - try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos)) { - Serializer serializer = EnhancedServiceLoader.load(Serializer.class, - SerializerType.getByCode(raftSyncMessage.getCodec()).name()); - Optional.ofNullable(raftSyncMessage.getBody()) - .ifPresent(value -> raftSyncMessage - .setBody(CompressorFactory.getCompressor(raftSyncMessage.getCompressor()) - .compress(serializer.serialize(value)))); - oos.writeObject(raftSyncMessage); - return bos.toByteArray(); - } - } - - public static RaftSyncMessage decode(byte[] raftSyncMsgByte) { - try (ByteArrayInputStream bin = new ByteArrayInputStream(raftSyncMsgByte); - ObjectInputStream ois = new ObjectInputStream(bin)) { - RaftSyncMessage raftSyncMessage = (RaftSyncMessage) ois.readObject(); - Serializer serializer = EnhancedServiceLoader.load(Serializer.class, - SerializerType.getByCode(raftSyncMessage.getCodec()).name()); - Optional.ofNullable(raftSyncMessage.getBody()) - .ifPresent(value -> raftSyncMessage - .setBody(serializer.deserialize(CompressorFactory.getCompressor(raftSyncMessage.getCompressor()) - .decompress((byte[]) raftSyncMessage.getBody())))); - return raftSyncMessage; - } - catch (ClassNotFoundException | IOException e) { - LOGGER.info("Failed to read raft synchronization log: {}", e.getMessage(), e); - throw new RuntimeException(e); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftBaseMsg.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftBaseMsg.java deleted file mode 100644 index f92f8d7839..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftBaseMsg.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync.msg; - -import static io.seata.common.DefaultValues.DEFAULT_SEATA_GROUP; - -/** - * @author jianbin.chen - */ -public class RaftBaseMsg implements java.io.Serializable { - - private static final long serialVersionUID = -1439073440621259777L; - - protected RaftSyncMsgType msgType; - - protected String group = DEFAULT_SEATA_GROUP; - - public RaftSyncMsgType getMsgType() { - return msgType; - } - - public void setMsgType(RaftSyncMsgType msgType) { - this.msgType = msgType; - } - - public String getGroup() { - return group; - } - - public void setGroup(String group) { - this.group = group; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftBranchSessionSyncMsg.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftBranchSessionSyncMsg.java deleted file mode 100644 index 8b32cc9d8b..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftBranchSessionSyncMsg.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync.msg; - -import static io.seata.common.DefaultValues.DEFAULT_SEATA_GROUP; - -import io.seata.common.util.StringUtils; -import io.seata.server.cluster.raft.sync.msg.dto.BranchTransactionDTO; - -/** - * @author funkye - */ -public class RaftBranchSessionSyncMsg extends RaftBaseMsg { - - private static final long serialVersionUID = -8577994371969898054L; - - private BranchTransactionDTO branchSession; - - private String group = DEFAULT_SEATA_GROUP; - - public RaftBranchSessionSyncMsg(RaftSyncMsgType msgType, BranchTransactionDTO branchSession) { - this.msgType = msgType; - this.branchSession = branchSession; - } - - public RaftBranchSessionSyncMsg() { - } - - public BranchTransactionDTO getBranchSession() { - return branchSession; - } - - public void setBranchSession(BranchTransactionDTO branchSession) { - this.branchSession = branchSession; - } - - public String getGroup() { - return group; - } - - public void setGroup(String group) { - this.group = group; - } - - @Override - public String toString() { - return StringUtils.toString(this); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftClusterMetadataMsg.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftClusterMetadataMsg.java deleted file mode 100644 index 7e7847c1cf..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftClusterMetadataMsg.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync.msg; - -import io.seata.common.util.StringUtils; -import io.seata.server.cluster.raft.sync.msg.dto.RaftClusterMetadata; - -/** - * @author jianbin.chen - */ -public class RaftClusterMetadataMsg extends RaftBaseMsg { - - private static final long serialVersionUID = 6208583637662412658L; - - private RaftClusterMetadata raftClusterMetadata; - - public RaftClusterMetadataMsg(RaftClusterMetadata raftClusterMetadata) { - this.msgType = RaftSyncMsgType.REFRESH_CLUSTER_METADATA; - this.raftClusterMetadata = raftClusterMetadata; - } - - public RaftClusterMetadataMsg() { - } - - public RaftClusterMetadata getRaftClusterMetadata() { - return raftClusterMetadata; - } - - public void setRaftClusterMetadata(RaftClusterMetadata raftClusterMetadata) { - this.raftClusterMetadata = raftClusterMetadata; - } - - @Override - public String toString() { - return StringUtils.toString(this); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftGlobalSessionSyncMsg.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftGlobalSessionSyncMsg.java deleted file mode 100644 index 8a3e35b935..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftGlobalSessionSyncMsg.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync.msg; - -import io.seata.common.util.StringUtils; -import io.seata.server.cluster.raft.sync.msg.dto.GlobalTransactionDTO; - -/** - * @author funkye - */ -public class RaftGlobalSessionSyncMsg extends RaftBaseMsg { - - private static final long serialVersionUID = -8577994371969898054L; - - private GlobalTransactionDTO globalSession; - - public RaftGlobalSessionSyncMsg(RaftSyncMsgType msgType, GlobalTransactionDTO globalSession) { - this.msgType = msgType; - this.globalSession = globalSession; - } - - public RaftGlobalSessionSyncMsg() { - } - - public GlobalTransactionDTO getGlobalSession() { - return globalSession; - } - - public void setGlobalSession(GlobalTransactionDTO globalSession) { - this.globalSession = globalSession; - } - - @Override - public String toString() { - return StringUtils.toString(this); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftSyncMessage.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftSyncMessage.java deleted file mode 100644 index f58694c93b..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftSyncMessage.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync.msg; - -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.core.compressor.CompressorType; -import io.seata.core.protocol.Version; -import io.seata.core.serializer.SerializerType; - -import static io.seata.common.DefaultValues.DEFAULT_RAFT_COMPRESSOR; -import static io.seata.common.DefaultValues.DEFAULT_RAFT_SERIALIZATION; -import static io.seata.core.constants.ConfigurationKeys.SERVER_RAFT_COMPRESSOR; - -/** - * @author funkye - */ -public class RaftSyncMessage implements java.io.Serializable { - - private static final long serialVersionUID = 8225279734319945365L; - - private byte codec = SerializerType.getByName(DEFAULT_RAFT_SERIALIZATION).getCode(); - - private byte compressor = CompressorType - .getByName(ConfigurationFactory.getInstance().getConfig(SERVER_RAFT_COMPRESSOR, DEFAULT_RAFT_COMPRESSOR)) - .getCode(); - - private Object body; - - private String version = Version.getCurrent(); - - /** - * Gets body. - * @return the body - */ - public Object getBody() { - return body; - } - - /** - * Sets body. - * @param body the body - */ - public void setBody(Object body) { - this.body = body; - } - - /** - * Gets codec. - * @return the codec - */ - public byte getCodec() { - return codec; - } - - /** - * Sets codec. - * @param codec the codec - * @return the codec - */ - public RaftSyncMessage setCodec(byte codec) { - this.codec = codec; - return this; - } - - /** - * Gets compressor. - * @return the compressor - */ - public byte getCompressor() { - return compressor; - } - - /** - * Sets compressor. - * @param compressor the compressor - * @return the compressor - */ - public RaftSyncMessage setCompressor(byte compressor) { - this.compressor = compressor; - return this; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - @Override - public String toString() { - return StringUtils.toString(this); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftSyncMsgType.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftSyncMsgType.java deleted file mode 100644 index 4a0c337ab8..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/RaftSyncMsgType.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync.msg; - -/** - * @author jianbin.chen - */ -public enum RaftSyncMsgType { - - /** - * addGlobalSession. - */ - ADD_GLOBAL_SESSION, - /** - * removeGlobalSession. - */ - REMOVE_GLOBAL_SESSION, - /** - * - */ - ADD_BRANCH_SESSION, - /** - * addBranchSession. - */ - REMOVE_BRANCH_SESSION, - /** - * updateGlobalSessionStatus. - */ - UPDATE_GLOBAL_SESSION_STATUS, - /** - * updateBranchSessionStatus. - */ - UPDATE_BRANCH_SESSION_STATUS, - /** - * releaseGlobalSessionLock. - */ - RELEASE_GLOBAL_SESSION_LOCK, - /** - * releaseBranchSessionLock. - */ - RELEASE_BRANCH_SESSION_LOCK, - /** - * refresh cluster metadata. - */ - REFRESH_CLUSTER_METADATA; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/BranchTransactionDTO.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/BranchTransactionDTO.java deleted file mode 100644 index 245b9d7f97..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/BranchTransactionDTO.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync.msg.dto; - -import io.seata.core.store.BranchTransactionDO; - -/** - * @author jianbin.chen - */ -public class BranchTransactionDTO extends BranchTransactionDO { - - private static final long serialVersionUID = 4550610938263777969L; - - private String lockKey; - - public BranchTransactionDTO(String xid, long branchId) { - super(xid, branchId); - } - - public BranchTransactionDTO() { - super(); - } - - public String getLockKey() { - return lockKey; - } - - public void setLockKey(String lockKey) { - this.lockKey = lockKey; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/GlobalTransactionDTO.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/GlobalTransactionDTO.java deleted file mode 100644 index e43a01c957..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/GlobalTransactionDTO.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync.msg.dto; - -import io.seata.core.store.GlobalTransactionDO; - -/** - * @author jianbin.chen - */ -public class GlobalTransactionDTO extends GlobalTransactionDO { - - private static final long serialVersionUID = 8402806824435215696L; - - public GlobalTransactionDTO(String xid) { - super(xid); - } - - public GlobalTransactionDTO() { - super(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java deleted file mode 100644 index 40ac2787bd..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.sync.msg.dto; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import io.seata.common.metadata.Node; -import io.seata.common.util.StringUtils; - -/** - * @author jianbin.chen - */ -public class RaftClusterMetadata implements Serializable { - - private static final long serialVersionUID = 6208583637662412658L; - - private Node leader; - - private List followers; - - private List learner; - - private long term; - - public RaftClusterMetadata() { - } - - public RaftClusterMetadata(long term) { - this.term = term; - } - - public Node createNode(String host, int txPort, int controlPort, String group, Map metadata) { - Node node = new Node(); - node.setTransaction(node.createEndpoint(host, txPort, "seata")); - node.setControl(node.createEndpoint(host, controlPort, "http")); - node.setGroup(group); - Optional.ofNullable(metadata).ifPresent(node::setMetadata); - return node; - } - - public Node getLeader() { - return leader; - } - - public void setLeader(Node leader) { - this.leader = leader; - } - - public long getTerm() { - return term; - } - - public List getFollowers() { - return followers; - } - - public void setFollowers(List followers) { - this.followers = followers; - } - - public List getLearner() { - return learner; - } - - public void setLearner(List learner) { - this.learner = learner; - } - - public void setTerm(long term) { - this.term = term; - } - - @Override - public String toString() { - return StringUtils.toString(this); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/util/RaftTaskUtil.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/util/RaftTaskUtil.java deleted file mode 100644 index edc0eca2ed..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/raft/util/RaftTaskUtil.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.raft.util; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import com.alipay.sofa.jraft.Closure; -import com.alipay.sofa.jraft.entity.Task; -import io.seata.core.exception.GlobalTransactionException; -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.server.cluster.raft.RaftServerFactory; -import io.seata.server.cluster.raft.context.SeataClusterContext; -import io.seata.server.cluster.raft.sync.RaftSyncMessageSerializer; -import io.seata.server.cluster.raft.sync.msg.RaftSyncMessage; - -/** - * @author funkye - */ -public class RaftTaskUtil { - - public static boolean createTask(Closure done, Object data, CompletableFuture completableFuture) - throws TransactionException { - final Task task = new Task(); - if (data != null) { - RaftSyncMessage raftSyncMessage = new RaftSyncMessage(); - raftSyncMessage.setBody(data); - try { - task.setData(ByteBuffer.wrap(RaftSyncMessageSerializer.encode(raftSyncMessage))); - } - catch (IOException e) { - throw new TransactionException(e); - } - } - task.setDone(done == null ? status -> { - } : done); - RaftServerFactory.getInstance().getRaftServer(SeataClusterContext.getGroup()).getNode().apply(task); - if (completableFuture != null) { - return futureGet(completableFuture); - } - return true; - } - - public static boolean createTask(Closure done, CompletableFuture completableFuture) - throws TransactionException { - return createTask(done, null, completableFuture); - } - - public static boolean futureGet(CompletableFuture completableFuture) throws TransactionException { - try { - return completableFuture.get(); - } - catch (InterruptedException e) { - throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession, - "Fail to store global session: " + e.getMessage()); - } - catch (ExecutionException e) { - if (e.getCause() instanceof TransactionException) { - throw (TransactionException) e.getCause(); - } - else { - throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession, - "Fail to store global session: " + e.getMessage()); - } - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/watch/Watcher.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/watch/Watcher.java deleted file mode 100644 index 14f1944701..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/cluster/watch/Watcher.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.cluster.watch; - -import static io.seata.server.cluster.watch.Watcher.Protocol.HTTP; - -/** - * @author funkye - */ -public class Watcher { - - private String group; - - private volatile boolean done = false; - - private T asyncContext; - - private long timeout; - - private long term; - - private String protocol = HTTP; - - public Watcher(String group, T asyncContext, int timeout, long term) { - this.group = group; - this.asyncContext = asyncContext; - this.timeout = System.currentTimeMillis() + timeout; - this.term = term; - } - - public String getGroup() { - return group; - } - - public void setGroup(String group) { - this.group = group; - } - - public boolean isDone() { - return done; - } - - public void setDone(boolean done) { - this.done = done; - } - - public T getAsyncContext() { - return asyncContext; - } - - public void setAsyncContext(T asyncContext) { - this.asyncContext = asyncContext; - } - - public long getTimeout() { - return timeout; - } - - public void setTimeout(long timeout) { - this.timeout = timeout; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public long getTerm() { - return term; - } - - public void setTerm(long term) { - this.term = term; - } - - public interface Protocol { - - /** - * grpc协议. - */ - String GRPC = "grpc"; - - /** - * http协议. - */ - String HTTP = "http"; - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/BranchSessionController.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/BranchSessionController.java deleted file mode 100644 index eec862e4cc..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/BranchSessionController.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.controller; - -import io.seata.server.console.service.BranchSessionService; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; - -/** - * Branch Session Controller. - * - * @author zhongxiang.wang - */ -@RestController -@RequestMapping("console/branchSession") -public class BranchSessionController { - - @Resource(type = BranchSessionService.class) - private BranchSessionService branchSessionService; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/GlobalLockController.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/GlobalLockController.java deleted file mode 100644 index 64ad87789d..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/GlobalLockController.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.controller; - -import io.seata.console.result.PageResult; -import io.seata.server.console.param.GlobalLockParam; -import io.seata.server.console.service.GlobalLockService; -import io.seata.server.console.vo.GlobalLockVO; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; - -/** - * Global Lock Controller. - * - * @author zhongxiang.wang - */ -@RestController -@RequestMapping("/api/v1/console/globalLock") -public class GlobalLockController { - - @Resource(type = GlobalLockService.class) - private GlobalLockService globalLockService; - - /** - * Query locks by param. - * @param param the param - * @return the list of GlobalLockVO - */ - @GetMapping("query") - public PageResult query(@ModelAttribute GlobalLockParam param) { - return globalLockService.query(param); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/GlobalSessionController.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/GlobalSessionController.java deleted file mode 100644 index 196e657fda..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/controller/GlobalSessionController.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.controller; - -import io.seata.console.result.PageResult; -import io.seata.server.console.param.GlobalSessionParam; -import io.seata.server.console.service.GlobalSessionService; -import io.seata.server.console.vo.GlobalSessionVO; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; - -/** - * Global Session Controller. - * - * @author zhongxiang.wang - */ -@RestController -@RequestMapping("/api/v1/console/globalSession") -public class GlobalSessionController { - - @Resource(type = GlobalSessionService.class) - private GlobalSessionService globalSessionService; - - /** - * Query all globalSession. - * @param param param for query globalSession - * @return the list of GlobalSessionVO - */ - @GetMapping("query") - public PageResult query(@ModelAttribute GlobalSessionParam param) { - return globalSessionService.query(param); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/BranchSessionDBServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/BranchSessionDBServiceImpl.java deleted file mode 100644 index 3a15ddd985..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/BranchSessionDBServiceImpl.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.db; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import javax.sql.DataSource; - -import io.seata.common.ConfigurationKeys; -import io.seata.common.exception.StoreException; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.util.IOUtil; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.console.result.PageResult; -import io.seata.core.store.db.DataSourceProvider; -import io.seata.core.store.db.sql.log.LogStoreSqlsFactory; -import io.seata.server.console.service.BranchSessionService; -import io.seata.server.console.vo.BranchSessionVO; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -import static io.seata.common.DefaultValues.DEFAULT_STORE_DB_BRANCH_TABLE; - -/** - * Branch Session DataBase ServiceImpl. - * - * @author zhongxiang.wang - * @author lvekee 734843455@qq.com - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'db'.equals('${sessionMode}')}") -public class BranchSessionDBServiceImpl implements BranchSessionService { - - private String branchTable; - - private String dbType; - - private DataSource dataSource; - - public BranchSessionDBServiceImpl() { - Configuration configuration = ConfigurationFactory.getInstance(); - branchTable = configuration.getConfig(ConfigurationKeys.STORE_DB_BRANCH_TABLE, DEFAULT_STORE_DB_BRANCH_TABLE); - dbType = configuration.getConfig(ConfigurationKeys.STORE_DB_TYPE); - if (StringUtils.isBlank(dbType)) { - throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_TYPE + " should not be blank"); - } - String dbDataSource = configuration.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); - if (StringUtils.isBlank(dbDataSource)) { - throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE + " should not be blank"); - } - dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, dbDataSource).provide(); - } - - @Override - public PageResult queryByXid(String xid) { - if (StringUtils.isBlank(xid)) { - throw new IllegalArgumentException("xid should not be blank"); - } - - String whereCondition = " where xid = ? "; - String branchSessionSQL = LogStoreSqlsFactory.getLogStoreSqls(dbType) - .getAllBranchSessionSQL(branchTable, whereCondition); - - List list = new ArrayList<>(); - ResultSet rs = null; - - try (Connection conn = dataSource.getConnection(); - PreparedStatement ps = conn.prepareStatement(branchSessionSQL)) { - ps.setObject(1, xid); - rs = ps.executeQuery(); - while (rs.next()) { - list.add(BranchSessionVO.convert(rs)); - } - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(rs); - } - return PageResult.success(list, list.size(), 0, 0, 0); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/GlobalLockDBServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/GlobalLockDBServiceImpl.java deleted file mode 100644 index b6fa2f4eb0..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/GlobalLockDBServiceImpl.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.db; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import javax.sql.DataSource; - -import io.seata.common.ConfigurationKeys; -import io.seata.common.exception.StoreException; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.util.IOUtil; -import io.seata.common.util.PageUtil; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.console.result.PageResult; -import io.seata.core.store.db.DataSourceProvider; -import io.seata.core.store.db.sql.lock.LockStoreSqlFactory; -import io.seata.server.console.param.GlobalLockParam; -import io.seata.server.console.service.GlobalLockService; -import io.seata.server.console.vo.GlobalLockVO; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -import static io.seata.common.DefaultValues.DEFAULT_LOCK_DB_TABLE; - -/** - * Global Lock DB ServiceImpl. - * - * @author zhongxiang.wang - * @author lvekee 734843455@qq.com - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'db'.equals('${lockMode}')}") -public class GlobalLockDBServiceImpl implements GlobalLockService { - - private String lockTable; - - private String dbType; - - private DataSource dataSource; - - public GlobalLockDBServiceImpl() { - Configuration configuration = ConfigurationFactory.getInstance(); - lockTable = configuration.getConfig(ConfigurationKeys.LOCK_DB_TABLE, DEFAULT_LOCK_DB_TABLE); - dbType = configuration.getConfig(ConfigurationKeys.STORE_DB_TYPE); - if (StringUtils.isBlank(dbType)) { - throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_TYPE + " should not be blank"); - } - String dbDataSource = configuration.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); - if (StringUtils.isBlank(dbDataSource)) { - throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE + " should not be blank"); - } - dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, dbDataSource).provide(); - } - - @Override - public PageResult query(GlobalLockParam param) { - PageUtil.checkParam(param.getPageNum(), param.getPageSize()); - - List sqlParamList = new ArrayList<>(); - String whereCondition = this.getWhereConditionByParam(param, sqlParamList); - - String sourceSql = LockStoreSqlFactory.getLogStoreSql(dbType).getAllLockSql(lockTable, whereCondition); - String queryLockSql = PageUtil.pageSql(sourceSql, dbType, param.getPageNum(), param.getPageSize()); - String lockCountSql = PageUtil.countSql(sourceSql, dbType); - - List list = new ArrayList<>(); - int count = 0; - - ResultSet rs = null; - ResultSet countRs = null; - - try (Connection conn = dataSource.getConnection(); - PreparedStatement ps = conn.prepareStatement(queryLockSql); - PreparedStatement countPs = conn.prepareStatement(lockCountSql)) { - PageUtil.setObject(ps, sqlParamList); - rs = ps.executeQuery(); - while (rs.next()) { - list.add(GlobalLockVO.convert(rs)); - } - PageUtil.setObject(countPs, sqlParamList); - countRs = countPs.executeQuery(); - if (countRs.next()) { - count = countRs.getInt(1); - } - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(rs, countRs); - } - return PageResult.success(list, count, param.getPageNum(), param.getPageSize()); - } - - private String getWhereConditionByParam(GlobalLockParam param, List sqlParamList) { - StringBuilder whereConditionBuilder = new StringBuilder(); - if (StringUtils.isNotBlank(param.getXid())) { - whereConditionBuilder.append(" and xid = ? "); - sqlParamList.add(param.getXid()); - } - if (StringUtils.isNotBlank(param.getTableName())) { - whereConditionBuilder.append(" and table_name = ? "); - sqlParamList.add(param.getTableName()); - } - if (StringUtils.isNotBlank(param.getTransactionId())) { - whereConditionBuilder.append(" and transaction_id = ? "); - sqlParamList.add(param.getTransactionId()); - } - if (StringUtils.isNotBlank(param.getBranchId())) { - whereConditionBuilder.append(" and branch_id = ? "); - sqlParamList.add(param.getBranchId()); - } - if (param.getTimeStart() != null) { - whereConditionBuilder.append(" and gmt_create >= ? "); - sqlParamList.add(param.getTimeStart()); - } - if (param.getTimeEnd() != null) { - whereConditionBuilder.append(" and gmt_create <= ? "); - sqlParamList.add(param.getTimeEnd()); - } - String whereCondition = whereConditionBuilder.toString(); - return whereCondition.replaceFirst("and", "where"); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/GlobalSessionDBServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/GlobalSessionDBServiceImpl.java deleted file mode 100644 index d97a26607f..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/db/GlobalSessionDBServiceImpl.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.db; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.List; - -import javax.annotation.Resource; -import javax.sql.DataSource; - -import io.seata.common.ConfigurationKeys; -import io.seata.common.exception.StoreException; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.util.IOUtil; -import io.seata.common.util.PageUtil; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.console.result.PageResult; -import io.seata.core.store.db.DataSourceProvider; -import io.seata.core.store.db.sql.log.LogStoreSqlsFactory; -import io.seata.server.console.param.GlobalSessionParam; -import io.seata.server.console.service.BranchSessionService; -import io.seata.server.console.service.GlobalSessionService; -import io.seata.server.console.vo.BranchSessionVO; -import io.seata.server.console.vo.GlobalSessionVO; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -import static io.seata.common.DefaultValues.DEFAULT_STORE_DB_GLOBAL_TABLE; - -/** - * Global Session DataBase ServiceImpl. - * - * @author zhongxiang.wang - * @author lvekee 734843455@qq.com - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'db'.equals('${sessionMode}')}") -public class GlobalSessionDBServiceImpl implements GlobalSessionService { - - private String globalTable; - - private String dbType; - - private DataSource dataSource; - - @Resource(type = BranchSessionService.class) - private BranchSessionService branchSessionService; - - public GlobalSessionDBServiceImpl() { - Configuration configuration = ConfigurationFactory.getInstance(); - globalTable = configuration.getConfig(ConfigurationKeys.STORE_DB_GLOBAL_TABLE, DEFAULT_STORE_DB_GLOBAL_TABLE); - dbType = configuration.getConfig(ConfigurationKeys.STORE_DB_TYPE); - if (StringUtils.isBlank(dbType)) { - throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_TYPE + " should not be blank"); - } - String dbDataSource = configuration.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); - if (StringUtils.isBlank(dbDataSource)) { - throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE + " should not be blank"); - } - dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, dbDataSource).provide(); - } - - @Override - public PageResult query(GlobalSessionParam param) { - PageUtil.checkParam(param.getPageNum(), param.getPageSize()); - - List sqlParamList = new ArrayList<>(); - String whereCondition = getWhereConditionByParam(param, sqlParamList); - - String sourceSql = LogStoreSqlsFactory.getLogStoreSqls(dbType) - .getAllGlobalSessionSql(globalTable, whereCondition); - String querySessionSql = PageUtil.pageSql(sourceSql, dbType, param.getPageNum(), param.getPageSize()); - String sessionCountSql = PageUtil.countSql(sourceSql, dbType); - - List list = new ArrayList<>(); - int count = 0; - - ResultSet rs = null; - ResultSet countRs = null; - - try (Connection conn = dataSource.getConnection(); - PreparedStatement ps = conn.prepareStatement(querySessionSql); - PreparedStatement countPs = conn.prepareStatement(sessionCountSql)) { - PageUtil.setObject(ps, sqlParamList); - rs = ps.executeQuery(); - while (rs.next()) { - list.add(GlobalSessionVO.convert(rs)); - } - - PageUtil.setObject(countPs, sqlParamList); - countRs = countPs.executeQuery(); - if (countRs.next()) { - count = countRs.getInt(1); - } - if (param.isWithBranch()) { - for (GlobalSessionVO globalSessionVO : list) { - PageResult pageResp = branchSessionService.queryByXid(globalSessionVO.getXid()); - globalSessionVO.setBranchSessionVOs(new HashSet<>(pageResp.getData())); - } - } - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(rs, countRs); - } - return PageResult.success(list, count, param.getPageNum(), param.getPageSize()); - } - - private String getWhereConditionByParam(GlobalSessionParam param, List sqlParamList) { - StringBuilder whereConditionBuilder = new StringBuilder(); - if (StringUtils.isNotBlank(param.getXid())) { - whereConditionBuilder.append(" and xid = ? "); - sqlParamList.add(param.getXid()); - } - if (StringUtils.isNotBlank(param.getApplicationId())) { - whereConditionBuilder.append(" and application_id = ? "); - sqlParamList.add(param.getApplicationId()); - } - if (param.getStatus() != null) { - whereConditionBuilder.append(" and status = ? "); - sqlParamList.add(param.getStatus()); - } - if (StringUtils.isNotBlank(param.getTransactionName())) { - whereConditionBuilder.append(" and transaction_name = ? "); - sqlParamList.add(param.getTransactionName()); - } - if (param.getTimeStart() != null) { - whereConditionBuilder.append(" and gmt_create >= ? "); - sqlParamList.add(new Date(param.getTimeStart())); - } - if (param.getTimeEnd() != null) { - whereConditionBuilder.append(" and gmt_create <= ? "); - sqlParamList.add(new Date(param.getTimeEnd())); - } - String whereCondition = whereConditionBuilder.toString(); - return whereCondition.replaceFirst("and", "where"); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/BranchSessionFileServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/BranchSessionFileServiceImpl.java deleted file mode 100644 index 8acb84aab3..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/BranchSessionFileServiceImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.file; - -import io.seata.common.exception.NotSupportYetException; -import io.seata.server.console.vo.BranchSessionVO; -import io.seata.console.result.PageResult; -import io.seata.server.console.service.BranchSessionService; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -/** - * Branch Session File ServiceImpl. - * - * @author zhongxiang.wang - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'file'.equals('${sessionMode}')}") -public class BranchSessionFileServiceImpl implements BranchSessionService { - - @Override - public PageResult queryByXid(String xid) { - throw new NotSupportYetException(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/GlobalLockFileServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/GlobalLockFileServiceImpl.java deleted file mode 100644 index f16d455666..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/GlobalLockFileServiceImpl.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.file; - -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.console.result.PageResult; -import io.seata.core.lock.RowLock; -import io.seata.server.console.param.GlobalLockParam; -import io.seata.server.console.service.GlobalLockService; -import io.seata.server.console.vo.GlobalLockVO; -import io.seata.server.lock.LockerManagerFactory; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -import java.util.Collection; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static io.seata.common.util.StringUtils.isBlank; -import static io.seata.server.console.vo.GlobalLockVO.convert; -import static java.util.Objects.isNull; - -/** - * Global Lock File ServiceImpl. - * - * @author zhongxiang.wang - * @author miaoxueyu - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'file'.equals('${lockMode}')}") -public class GlobalLockFileServiceImpl implements GlobalLockService { - - @Override - public PageResult query(GlobalLockParam param) { - checkParam(param); - - final Collection allSessions = SessionHolder.getRootSessionManager().allSessions(); - - final AtomicInteger total = new AtomicInteger(); - List result = allSessions.parallelStream() - .filter(obtainGlobalSessionPredicate(param)) - .flatMap(globalSession -> globalSession.getBranchSessions().stream()) - .filter(obtainBranchSessionPredicate(param)) - .flatMap(branchSession -> filterAndMap(param, branchSession)) - .peek(globalSession -> total.incrementAndGet()) - .collect(Collectors.toList()); - - return PageResult.build(convert(result), param.getPageNum(), param.getPageSize()); - - } - - /** - * filter with tableName and generate RowLock. - * @param param the query param - * @param branchSession the branch session - * @return the RowLock list - */ - private Stream filterAndMap(GlobalLockParam param, BranchSession branchSession) { - if (CollectionUtils.isEmpty(branchSession.getLockHolder())) { - return Stream.empty(); - } - - final String tableName = param.getTableName(); - - // get rowLock from branchSession - final List rowLocks = LockerManagerFactory.getLockManager().collectRowLocks(branchSession); - - if (StringUtils.isNotBlank(tableName)) { - return rowLocks.parallelStream().filter(rowLock -> rowLock.getTableName().contains(param.getTableName())); - } - - return rowLocks.stream(); - } - - /** - * check the param. - * @param param the param - */ - private void checkParam(GlobalLockParam param) { - if (param.getPageSize() <= 0 || param.getPageNum() <= 0) { - throw new IllegalArgumentException("wrong pageSize or pageNum"); - } - - // verification data type - try { - Long.parseLong(param.getTransactionId()); - } - catch (NumberFormatException e) { - param.setTransactionId(null); - } - try { - Long.parseLong(param.getBranchId()); - } - catch (NumberFormatException e) { - param.setBranchId(null); - } - - } - - /** - * obtain the branch session condition. - * @param param condition for query branch session - * @return the filter condition - */ - private Predicate obtainBranchSessionPredicate(GlobalLockParam param) { - return branchSession -> { - // transactionId - return (isBlank(param.getTransactionId()) - || String.valueOf(branchSession.getTransactionId()).contains(param.getTransactionId())) - - && - // branch id - (isBlank(param.getBranchId()) - || String.valueOf(branchSession.getBranchId()).contains(param.getBranchId())); - }; - } - - /** - * obtain the global session condition. - * @param param condition for query global session - * @return the filter condition - */ - private Predicate obtainGlobalSessionPredicate(GlobalLockParam param) { - - return globalSession -> { - // first, there must be withBranchSession - return CollectionUtils.isNotEmpty(globalSession.getBranchSessions()) - - && - // The second is other conditions - // xid - (isBlank(param.getXid()) || globalSession.getXid().contains(param.getXid())) - - && - // timeStart - (isNull(param.getTimeStart()) || param.getTimeStart() <= globalSession.getBeginTime()) - - && - // timeEnd - (isNull(param.getTimeEnd()) || param.getTimeEnd() >= globalSession.getBeginTime()); - }; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/GlobalSessionFileServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/GlobalSessionFileServiceImpl.java deleted file mode 100644 index bfa3f6e223..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/file/GlobalSessionFileServiceImpl.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.file; - -import io.seata.console.result.PageResult; -import io.seata.server.console.param.GlobalSessionParam; -import io.seata.server.console.service.GlobalSessionService; -import io.seata.server.console.vo.GlobalSessionVO; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import io.seata.server.storage.SessionConverter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static io.seata.common.util.StringUtils.isBlank; -import static java.util.Objects.isNull; - -/** - * Global Session File ServiceImpl. - * - * @author zhongxiang.wang - * @author miaoxueyu - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'file'.equals('${sessionMode}')}") -public class GlobalSessionFileServiceImpl implements GlobalSessionService { - - @Override - public PageResult query(GlobalSessionParam param) { - if (param.getPageSize() <= 0 || param.getPageNum() <= 0) { - throw new IllegalArgumentException("wrong pageSize or pageNum"); - } - - final Collection allSessions = SessionHolder.getRootSessionManager().allSessions(); - - final List filteredSessions = allSessions.parallelStream() - .filter(obtainPredicate(param)) - .collect(Collectors.toList()); - - return PageResult.build(SessionConverter.convertGlobalSession(filteredSessions), param.getPageNum(), - param.getPageSize()); - } - - /** - * obtain the condition. - * @param param condition for query global session - * @return the filter condition - */ - private Predicate obtainPredicate(GlobalSessionParam param) { - - return session -> { - return - // xid - (isBlank(param.getXid()) || session.getXid().contains(param.getXid())) - - && - // applicationId - (isBlank(param.getApplicationId()) || session.getApplicationId().contains(param.getApplicationId())) - - && - // status - (isNull(param.getStatus()) || Objects.equals(session.getStatus().getCode(), param.getStatus())) - - && - // transactionName - (isBlank(param.getTransactionName()) - || session.getTransactionName().contains(param.getTransactionName())) - - && - // timeStart - (isNull(param.getTimeStart()) || param.getTimeStart() <= session.getBeginTime()) - - && - // timeEnd - (isNull(param.getTimeEnd()) || param.getTimeEnd() >= session.getBeginTime()); - - }; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/BranchSessionRaftServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/BranchSessionRaftServiceImpl.java deleted file mode 100644 index dce8fb50bf..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/BranchSessionRaftServiceImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.raft; - -import io.seata.server.console.impl.file.BranchSessionFileServiceImpl; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -/** - * Branch Session File ServiceImpl. - * - * @author zhongxiang.wang - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'raft'.equals('${sessionMode}')}") -public class BranchSessionRaftServiceImpl extends BranchSessionFileServiceImpl { - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/GlobalLockRaftServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/GlobalLockRaftServiceImpl.java deleted file mode 100644 index 974b374cbc..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/GlobalLockRaftServiceImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.raft; - -import io.seata.server.console.impl.file.GlobalLockFileServiceImpl; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -/** - * Global Lock File ServiceImpl. - * - * @author zhongxiang.wang - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'raft'.equals('${lockMode}')}") -public class GlobalLockRaftServiceImpl extends GlobalLockFileServiceImpl { - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/GlobalSessionRaftServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/GlobalSessionRaftServiceImpl.java deleted file mode 100644 index d81a41a880..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/raft/GlobalSessionRaftServiceImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.raft; - -import io.seata.server.console.impl.file.GlobalSessionFileServiceImpl; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -/** - * Global Session File ServiceImpl. - * - * @author zhongxiang.wang - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'raft'.equals('${sessionMode}')}") -public class GlobalSessionRaftServiceImpl extends GlobalSessionFileServiceImpl { - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/BranchSessionRedisServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/BranchSessionRedisServiceImpl.java deleted file mode 100644 index af135121a6..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/BranchSessionRedisServiceImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.redis; - -import java.util.ArrayList; -import java.util.List; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.console.result.PageResult; -import io.seata.server.console.vo.BranchSessionVO; -import io.seata.core.store.BranchTransactionDO; -import io.seata.server.console.service.BranchSessionService; -import io.seata.server.storage.redis.store.RedisTransactionStoreManager; -import io.seata.server.storage.redis.store.RedisTransactionStoreManagerFactory; -import org.springframework.beans.BeanUtils; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -/** - * Branch Session Redis ServiceImpl. - * - * @author zhongxiang.wang - * @author doubleDimple - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'redis'.equals('${sessionMode}')}") -public class BranchSessionRedisServiceImpl implements BranchSessionService { - - @Override - public PageResult queryByXid(String xid) { - if (StringUtils.isBlank(xid)) { - return PageResult.success(); - } - - List branchSessionVos = new ArrayList<>(); - - RedisTransactionStoreManager instance = RedisTransactionStoreManagerFactory.getInstance(); - - List branchSessionDos = instance.findBranchSessionByXid(xid); - - if (CollectionUtils.isNotEmpty(branchSessionDos)) { - for (BranchTransactionDO branchSessionDo : branchSessionDos) { - BranchSessionVO branchSessionVO = new BranchSessionVO(); - BeanUtils.copyProperties(branchSessionDo, branchSessionVO); - branchSessionVos.add(branchSessionVO); - } - } - - return PageResult.success(branchSessionVos, branchSessionVos.size(), 0, branchSessionVos.size()); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/GlobalLockRedisServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/GlobalLockRedisServiceImpl.java deleted file mode 100644 index 9530caab39..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/GlobalLockRedisServiceImpl.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.redis; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import io.seata.common.util.CollectionUtils; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; -import io.seata.common.util.BeanUtils; -import io.seata.server.console.param.GlobalLockParam; -import io.seata.console.result.PageResult; -import io.seata.server.console.vo.GlobalLockVO; -import io.seata.server.console.service.GlobalLockService; -import io.seata.server.storage.redis.JedisPooledFactory; -import redis.clients.jedis.Jedis; -import static io.seata.common.Constants.ROW_LOCK_KEY_SPLIT_CHAR; -import static io.seata.common.exception.FrameworkErrorCode.ParameterRequired; -import static io.seata.common.util.StringUtils.isNotBlank; -import static io.seata.console.result.PageResult.checkPage; -import static io.seata.core.constants.RedisKeyConstants.DEFAULT_REDIS_SEATA_GLOBAL_LOCK_PREFIX; -import static io.seata.core.constants.RedisKeyConstants.DEFAULT_REDIS_SEATA_ROW_LOCK_PREFIX; -import static io.seata.core.constants.RedisKeyConstants.SPLIT; - -/** - * Global Lock Redis Service Impl. - * - * @author zhongxiang.wang - * @author doubleDimple - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'redis'.equals('${lockMode}')}") -public class GlobalLockRedisServiceImpl implements GlobalLockService { - - @Override - public PageResult query(GlobalLockParam param) { - - int total = 0; - List globalLockVos; - checkPage(param); - if (isNotBlank(param.getXid())) { - globalLockVos = queryGlobalByXid(param.getXid()); - total = globalLockVos.size(); - return PageResult.success(globalLockVos, total, param.getPageNum(), param.getPageSize()); - } - else if (isNotBlank(param.getTableName()) && isNotBlank(param.getPk()) && isNotBlank(param.getResourceId())) { - // SEATA_ROW_LOCK_jdbc:mysql://116.62.62.26/seata-order^^^order^^^2188 - String tableName = param.getTableName(); - String pk = param.getPk(); - String resourceId = param.getResourceId(); - globalLockVos = queryGlobalLockByRowKey(buildRowKey(tableName, pk, resourceId)); - total = globalLockVos.size(); - return PageResult.success(globalLockVos, total, param.getPageNum(), param.getPageSize()); - } - else { - return PageResult.failure(ParameterRequired.getErrCode(), - "only three parameters of tableName,pk,resourceId or Xid are supported"); - } - } - - private List queryGlobalLockByRowKey(String buildRowKey) { - return readGlobalLockByRowKey(buildRowKey); - } - - private String buildRowKey(String tableName, String pk, String resourceId) { - return DEFAULT_REDIS_SEATA_ROW_LOCK_PREFIX + resourceId + SPLIT + tableName + SPLIT + pk; - } - - private List queryGlobalByXid(String xid) { - return readGlobalLockByXid(DEFAULT_REDIS_SEATA_GLOBAL_LOCK_PREFIX + xid); - } - - private List readGlobalLockByXid(String key) { - List vos = new ArrayList<>(); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - Map mapGlobalKeys = jedis.hgetAll(key); - if (CollectionUtils.isNotEmpty(mapGlobalKeys)) { - List rowLockKeys = new ArrayList<>(); - mapGlobalKeys.forEach((k, v) -> rowLockKeys.addAll(Arrays.asList(v.split(ROW_LOCK_KEY_SPLIT_CHAR)))); - for (String rowLoclKey : rowLockKeys) { - Map mapRowLockKey = jedis.hgetAll(rowLoclKey); - GlobalLockVO vo = (GlobalLockVO) BeanUtils.mapToObject(mapRowLockKey, GlobalLockVO.class); - if (vo != null) { - vos.add(vo); - } - } - } - } - - return vos; - } - - private List readGlobalLockByRowKey(String key) { - List vos = new ArrayList<>(); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - Map map = jedis.hgetAll(key); - GlobalLockVO vo = (GlobalLockVO) BeanUtils.mapToObject(map, GlobalLockVO.class); - if (vo != null) { - vos.add(vo); - } - } - return vos; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/GlobalSessionRedisServiceImpl.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/GlobalSessionRedisServiceImpl.java deleted file mode 100644 index 12121aa554..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/impl/redis/GlobalSessionRedisServiceImpl.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.impl.redis; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import io.seata.common.util.CollectionUtils; -import io.seata.console.result.PageResult; -import io.seata.server.console.param.GlobalSessionParam; -import io.seata.server.console.vo.GlobalSessionVO; -import io.seata.core.model.GlobalStatus; -import io.seata.server.console.service.GlobalSessionService; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.storage.redis.store.RedisTransactionStoreManager; -import io.seata.server.storage.redis.store.RedisTransactionStoreManagerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; -import static io.seata.common.exception.FrameworkErrorCode.ParameterRequired; -import static io.seata.common.util.StringUtils.isBlank; -import static io.seata.common.util.StringUtils.isNotBlank; -import static io.seata.console.result.PageResult.checkPage; -import static io.seata.server.storage.SessionConverter.convertToGlobalSessionVo; - -/** - * Global Session Redis ServiceImpl. - * - * @author zhongxiang.wang - * @author doubleDimple - */ -@Component -@org.springframework.context.annotation.Configuration -@ConditionalOnExpression("#{'redis'.equals('${sessionMode}')}") -public class GlobalSessionRedisServiceImpl implements GlobalSessionService { - - private static final Logger LOGGER = LoggerFactory.getLogger(GlobalSessionRedisServiceImpl.class); - - @Override - public PageResult query(GlobalSessionParam param) { - List result = new ArrayList<>(); - Long total = 0L; - if (param.getTimeStart() != null || param.getTimeEnd() != null) { - // not support time range query - LOGGER.debug("not supported according to time range query"); - return PageResult.failure(ParameterRequired.getErrCode(), "not supported according to time range query"); - } - List globalSessions = new ArrayList<>(); - - RedisTransactionStoreManager instance = RedisTransactionStoreManagerFactory.getInstance(); - - checkPage(param); - - if (isBlank(param.getXid()) && param.getStatus() == null) { - total = instance.countByGlobalSessions(GlobalStatus.values()); - globalSessions = instance.findGlobalSessionByPage(param.getPageNum(), param.getPageSize(), - param.isWithBranch()); - } - else { - List globalSessionsNew = new ArrayList<>(); - if (isNotBlank(param.getXid())) { - SessionCondition sessionCondition = new SessionCondition(); - sessionCondition.setXid(param.getXid()); - sessionCondition.setLazyLoadBranch(!param.isWithBranch()); - globalSessions = instance.readSession(sessionCondition); - total = (long) globalSessions.size(); - } - - if (param.getStatus() != null && GlobalStatus.get(param.getStatus()) != null) { - if (CollectionUtils.isNotEmpty(globalSessions)) { - globalSessionsNew = globalSessions.stream() - .filter(globalSession -> globalSession.getStatus().getCode() == (param.getStatus())) - .collect(Collectors.toList()); - total = (long) globalSessionsNew.size(); - } - else { - total = instance.countByGlobalSessions(new GlobalStatus[] { GlobalStatus.get(param.getStatus()) }); - globalSessionsNew = instance.readSessionStatusByPage(param); - } - } - - if (LOGGER.isDebugEnabled()) { - if (isNotBlank(param.getApplicationId())) { - // not support - LOGGER.debug("not supported according to applicationId query"); - } - if (isNotBlank(param.getTransactionName())) { - // not support - LOGGER.debug("not supported according to transactionName query"); - } - } - globalSessions = globalSessionsNew.size() > 0 ? globalSessionsNew : globalSessions; - } - - convertToGlobalSessionVo(result, globalSessions); - - return PageResult.success(result, total.intValue(), param.getPageNum(), param.getPageSize()); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/param/GlobalLockParam.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/param/GlobalLockParam.java deleted file mode 100644 index f688768394..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/param/GlobalLockParam.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.param; - -import io.seata.console.param.BaseParam; - -import java.io.Serializable; - -/** - * Global lock param. - * - * @author zhongxiang.wang - */ -public class GlobalLockParam extends BaseParam implements Serializable { - - private static final long serialVersionUID = 615412528070131284L; - - /** - * the xid. - */ - private String xid; - - /** - * the table name. - */ - private String tableName; - - /** - * the transaction id. - */ - private String transactionId; - - /** - * the branch id. - */ - private String branchId; - - /** - * the primary Key. - */ - private String pk; - - /** - * the resourceId. - */ - private String resourceId; - - public String getTransactionId() { - return transactionId; - } - - public void setTransactionId(String transactionId) { - this.transactionId = transactionId; - } - - public String getBranchId() { - return branchId; - } - - public void setBranchId(String branchId) { - this.branchId = branchId; - } - - public String getXid() { - return xid; - } - - public void setXid(String xid) { - this.xid = xid; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } - - public String getPk() { - return pk; - } - - public void setPk(String pk) { - this.pk = pk; - } - - public String getResourceId() { - return resourceId; - } - - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - @Override - public String toString() { - return "GlobalLockParam{" + "xid='" + xid + '\'' + ", tableName='" + tableName + '\'' + ", transactionId='" - + transactionId + '\'' + ", branchId='" + branchId + '\'' + ", pk='" + pk + '\'' + ", resourceId='" - + resourceId + '\'' + '}'; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/param/GlobalSessionParam.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/param/GlobalSessionParam.java deleted file mode 100644 index 75792b58df..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/param/GlobalSessionParam.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.param; - -import io.seata.console.param.BaseParam; - -import java.io.Serializable; - -/** - * Global session param. - * - * @author zhongxiang.wang - */ -public class GlobalSessionParam extends BaseParam implements Serializable { - - private static final long serialVersionUID = 115488252809011284L; - - /** - * the xid. - */ - private String xid; - - /** - * the application id. - */ - private String applicationId; - - /** - * the global session status. - */ - private Integer status; - - /** - * the transaction name. - */ - private String transactionName; - - /** - * if with branch true: with branch session false: no branch session. - */ - private boolean withBranch; - - public String getXid() { - return xid; - } - - public void setXid(String xid) { - this.xid = xid; - } - - public String getTransactionName() { - return transactionName; - } - - public void setTransactionName(String transactionName) { - this.transactionName = transactionName; - } - - public String getApplicationId() { - return applicationId; - } - - public void setApplicationId(String applicationId) { - this.applicationId = applicationId; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public boolean isWithBranch() { - return withBranch; - } - - public void setWithBranch(boolean withBranch) { - this.withBranch = withBranch; - } - - @Override - public String toString() { - return "GlobalSessionParam{" + "xid='" + xid + '\'' + ", applicationId='" + applicationId + '\'' + ", status=" - + status + ", transactionName='" + transactionName + '\'' + ", withBranch=" + withBranch + '}'; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/BranchSessionService.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/BranchSessionService.java deleted file mode 100644 index d980b916e2..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/BranchSessionService.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.service; - -import io.seata.server.console.vo.BranchSessionVO; -import io.seata.console.result.PageResult; - -/** - * Branch session service. - * - * @author wangzhongxiang - */ -public interface BranchSessionService { - - /** - * Query branch session by xid. - * @param xid the xid - * @return the BranchSessionVO list - */ - PageResult queryByXid(String xid); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/GlobalLockService.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/GlobalLockService.java deleted file mode 100644 index 25b0e08b94..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/GlobalLockService.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.service; - -import io.seata.server.console.param.GlobalLockParam; -import io.seata.server.console.vo.GlobalLockVO; -import io.seata.console.result.PageResult; - -/** - * Global lock service. - * - * @author wangzhongxiang - */ -public interface GlobalLockService { - - /** - * Query locks by param. - * @param param the param - * @return the list of GlobalLockVO - */ - PageResult query(GlobalLockParam param); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/GlobalSessionService.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/GlobalSessionService.java deleted file mode 100644 index 49b073bc28..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/service/GlobalSessionService.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.service; - -import io.seata.server.console.param.GlobalSessionParam; -import io.seata.server.console.vo.GlobalSessionVO; -import io.seata.console.result.PageResult; - -/** - * Global session service. - * - * @author wangzhongxiang - */ -public interface GlobalSessionService { - - /** - * Query global session. - * @param param the param - * @return the GlobalSessionVO list - */ - PageResult query(GlobalSessionParam param); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/BranchSessionVO.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/BranchSessionVO.java deleted file mode 100644 index b359053786..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/BranchSessionVO.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.vo; - -import io.seata.core.constants.ServerTableColumnsName; - -import java.sql.Date; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Objects; - -/** - * BranchSessionVO. - * - * @author zhongxiang.wang - */ -public class BranchSessionVO { - - private String xid; - - private String transactionId; - - private String branchId; - - private String resourceGroupId; - - private String resourceId; - - private String branchType; - - private Integer status; - - private String clientId; - - private String applicationData; - - private Long gmtCreate; - - private Long gmtModified; - - public BranchSessionVO() { - - } - - public BranchSessionVO(String xid, Long transactionId, Long branchId, String resourceGroupId, String resourceId, - String branchType, Integer status, String clientId, String applicationData) { - this.xid = xid; - this.transactionId = String.valueOf(transactionId); - this.branchId = String.valueOf(branchId); - this.resourceGroupId = resourceGroupId; - this.resourceId = resourceId; - this.branchType = branchType; - this.status = status; - this.clientId = clientId; - this.applicationData = applicationData; - } - - public String getXid() { - return xid; - } - - public void setXid(String xid) { - this.xid = xid; - } - - public String getTransactionId() { - return transactionId; - } - - public void setTransactionId(Long transactionId) { - this.transactionId = String.valueOf(transactionId); - } - - public String getBranchId() { - return branchId; - } - - public void setBranchId(Long branchId) { - this.branchId = String.valueOf(branchId); - } - - public String getResourceGroupId() { - return resourceGroupId; - } - - public void setResourceGroupId(String resourceGroupId) { - this.resourceGroupId = resourceGroupId; - } - - public String getResourceId() { - return resourceId; - } - - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - public String getBranchType() { - return branchType; - } - - public void setBranchType(String branchType) { - this.branchType = branchType; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getApplicationData() { - return applicationData; - } - - public void setApplicationData(String applicationData) { - this.applicationData = applicationData; - } - - public Long getGmtCreate() { - return gmtCreate; - } - - public void setGmtCreate(Long gmtCreate) { - this.gmtCreate = gmtCreate; - } - - public Long getGmtModified() { - return gmtModified; - } - - public void setGmtModified(Long gmtModified) { - this.gmtModified = gmtModified; - } - - public static BranchSessionVO convert(ResultSet rs) throws SQLException { - BranchSessionVO branchSessionVO = new BranchSessionVO(); - branchSessionVO.setXid(rs.getString(ServerTableColumnsName.BRANCH_TABLE_XID)); - branchSessionVO.setTransactionId(rs.getLong(ServerTableColumnsName.BRANCH_TABLE_TRANSACTION_ID)); - branchSessionVO.setBranchId(rs.getLong(ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID)); - branchSessionVO.setResourceGroupId(rs.getString(ServerTableColumnsName.BRANCH_TABLE_RESOURCE_GROUP_ID)); - branchSessionVO.setResourceId(rs.getString(ServerTableColumnsName.BRANCH_TABLE_RESOURCE_ID)); - branchSessionVO.setBranchType(rs.getString(ServerTableColumnsName.BRANCH_TABLE_BRANCH_TYPE)); - branchSessionVO.setStatus(rs.getInt(ServerTableColumnsName.BRANCH_TABLE_STATUS)); - branchSessionVO.setClientId(rs.getString(ServerTableColumnsName.BRANCH_TABLE_CLIENT_ID)); - branchSessionVO.setApplicationData(rs.getString(ServerTableColumnsName.BRANCH_TABLE_APPLICATION_DATA)); - Date gmtCreateTimestamp = rs.getDate(ServerTableColumnsName.BRANCH_TABLE_GMT_CREATE); - if (gmtCreateTimestamp != null) { - branchSessionVO.setGmtCreate(gmtCreateTimestamp.getTime()); - } - Date gmtModifiedTimestamp = rs.getDate(ServerTableColumnsName.BRANCH_TABLE_GMT_MODIFIED); - if (gmtModifiedTimestamp != null) { - branchSessionVO.setGmtModified(gmtModifiedTimestamp.getTime()); - } - return branchSessionVO; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - BranchSessionVO that = (BranchSessionVO) o; - return Objects.equals(xid, that.xid) && Objects.equals(transactionId, that.transactionId) - && Objects.equals(branchId, that.branchId) && Objects.equals(resourceGroupId, that.resourceGroupId) - && Objects.equals(resourceId, that.resourceId) && Objects.equals(branchType, that.branchType) - && Objects.equals(status, that.status) && Objects.equals(clientId, that.clientId) - && Objects.equals(applicationData, that.applicationData) && Objects.equals(gmtCreate, that.gmtCreate) - && Objects.equals(gmtModified, that.gmtModified); - } - - @Override - public int hashCode() { - return Objects.hash(xid, transactionId, branchId, resourceGroupId, resourceId, branchType, status, clientId, - applicationData, gmtCreate, gmtModified); - } - - @Override - public String toString() { - return "BranchSessionVO{" + "xid='" + xid + '\'' + ", transactionId=" + transactionId + ", branchId=" + branchId - + ", resourceGroupId='" + resourceGroupId + '\'' + ", resourceId='" + resourceId + '\'' - + ", branchType='" + branchType + '\'' + ", status=" + status + ", clientId='" + clientId + '\'' - + ", applicationData='" + applicationData + '\'' + ", gmtCreate=" + gmtCreate + ", gmtModified=" - + gmtModified + '}'; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/GlobalLockVO.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/GlobalLockVO.java deleted file mode 100644 index 9a07754b13..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/GlobalLockVO.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.vo; - -import io.seata.common.util.CollectionUtils; -import io.seata.core.constants.ServerTableColumnsName; -import io.seata.core.lock.RowLock; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * GlobalLockVO. - * - * @author zhongxiang.wang - * @author miaoxueyu - */ -public class GlobalLockVO { - - private String xid; - - private String transactionId; - - private String branchId; - - private String resourceId; - - private String tableName; - - private String pk; - - private String rowKey; - - private Long gmtCreate; - - private Long gmtModified; - - /** - * convert RowLock list to GlobalLockVO list. - * @param rowLocks the RowLock list - * @return the GlobalLockVO list - */ - public static List convert(List rowLocks) { - if (CollectionUtils.isEmpty(rowLocks)) { - return Collections.emptyList(); - } - final List result = new ArrayList<>(rowLocks.size()); - for (RowLock rowLock : rowLocks) { - result.add(convert(rowLock)); - } - - return result; - } - - /** - * convert RowLock to GlobalLockVO. - * @param rowLock the RowLock - * @return the GlobalLockVO - */ - public static GlobalLockVO convert(RowLock rowLock) { - final GlobalLockVO globalLockVO = new GlobalLockVO(); - globalLockVO.setXid(rowLock.getXid()); - globalLockVO.setTransactionId(rowLock.getTransactionId()); - globalLockVO.setBranchId(rowLock.getBranchId()); - globalLockVO.setResourceId(rowLock.getResourceId()); - globalLockVO.setTableName(rowLock.getTableName()); - globalLockVO.setPk(rowLock.getPk()); - globalLockVO.setRowKey(rowLock.getRowKey()); - return globalLockVO; - } - - public String getXid() { - return xid; - } - - public void setXid(String xid) { - this.xid = xid; - } - - public String getTransactionId() { - return transactionId; - } - - public void setTransactionId(Long transactionId) { - this.transactionId = String.valueOf(transactionId); - } - - public String getBranchId() { - return branchId; - } - - public void setBranchId(Long branchId) { - this.branchId = String.valueOf(branchId); - } - - public String getResourceId() { - return resourceId; - } - - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } - - public String getPk() { - return pk; - } - - public void setPk(String pk) { - this.pk = pk; - } - - public String getRowKey() { - return rowKey; - } - - public void setRowKey(String rowKey) { - this.rowKey = rowKey; - } - - public Long getGmtCreate() { - return gmtCreate; - } - - public void setGmtCreate(Long gmtCreate) { - this.gmtCreate = gmtCreate; - } - - public Long getGmtModified() { - return gmtModified; - } - - public void setGmtModified(Long gmtModified) { - this.gmtModified = gmtModified; - } - - public static GlobalLockVO convert(ResultSet rs) throws SQLException { - GlobalLockVO globalLockVO = new GlobalLockVO(); - globalLockVO.setRowKey(rs.getString(ServerTableColumnsName.LOCK_TABLE_ROW_KEY)); - globalLockVO.setXid(rs.getString(ServerTableColumnsName.LOCK_TABLE_XID)); - globalLockVO.setTransactionId(rs.getLong(ServerTableColumnsName.LOCK_TABLE_TRANSACTION_ID)); - globalLockVO.setBranchId(rs.getLong(ServerTableColumnsName.LOCK_TABLE_BRANCH_ID)); - globalLockVO.setResourceId(rs.getString(ServerTableColumnsName.LOCK_TABLE_RESOURCE_ID)); - globalLockVO.setTableName(rs.getString(ServerTableColumnsName.LOCK_TABLE_TABLE_NAME)); - globalLockVO.setPk(rs.getString(ServerTableColumnsName.LOCK_TABLE_PK)); - Timestamp gmtCreateTimestamp = rs.getTimestamp(ServerTableColumnsName.LOCK_TABLE_GMT_CREATE); - if (gmtCreateTimestamp != null) { - globalLockVO.setGmtCreate(gmtCreateTimestamp.getTime()); - } - Timestamp gmtModifiedTimestamp = rs.getTimestamp(ServerTableColumnsName.LOCK_TABLE_GMT_MODIFIED); - if (gmtModifiedTimestamp != null) { - globalLockVO.setGmtModified(gmtModifiedTimestamp.getTime()); - } - return globalLockVO; - } - - @Override - public String toString() { - return "GlobalLockVO{" + "xid='" + xid + '\'' + ", transactionId=" + transactionId + ", branchId=" + branchId - + ", resourceId='" + resourceId + '\'' + ", tableName='" + tableName + '\'' + ", pk='" + pk + '\'' - + ", rowKey='" + rowKey + '\'' + ", gmtCreate=" + gmtCreate + ", gmtModified=" + gmtModified + '}'; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/GlobalSessionVO.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/GlobalSessionVO.java deleted file mode 100644 index 55d9968c4c..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/console/vo/GlobalSessionVO.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.console.vo; - -import io.seata.core.constants.ServerTableColumnsName; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.Set; - -/** - * GlobalSessionVO. - * - * @author zhongxiang.wang - */ -public class GlobalSessionVO { - - private String xid; - - private String transactionId; - - private Integer status; - - private String applicationId; - - private String transactionServiceGroup; - - private String transactionName; - - private Long timeout; - - private Long beginTime; - - private String applicationData; - - private Long gmtCreate; - - private Long gmtModified; - - private Set branchSessionVOs; - - public GlobalSessionVO() { - - } - - public GlobalSessionVO(String xid, Long transactionId, Integer status, String applicationId, - String transactionServiceGroup, String transactionName, Long timeout, Long beginTime, - String applicationData, Set branchSessionVOs) { - this.xid = xid; - this.transactionId = String.valueOf(transactionId); - this.status = status; - this.applicationId = applicationId; - this.transactionServiceGroup = transactionServiceGroup; - this.transactionName = transactionName; - this.timeout = timeout; - this.beginTime = beginTime; - this.applicationData = applicationData; - this.branchSessionVOs = branchSessionVOs; - } - - public String getXid() { - return xid; - } - - public void setXid(String xid) { - this.xid = xid; - } - - public String getTransactionId() { - return transactionId; - } - - public void setTransactionId(Long transactionId) { - this.transactionId = String.valueOf(transactionId); - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public String getApplicationId() { - return applicationId; - } - - public void setApplicationId(String applicationId) { - this.applicationId = applicationId; - } - - public String getTransactionServiceGroup() { - return transactionServiceGroup; - } - - public void setTransactionServiceGroup(String transactionServiceGroup) { - this.transactionServiceGroup = transactionServiceGroup; - } - - public String getTransactionName() { - return transactionName; - } - - public void setTransactionName(String transactionName) { - this.transactionName = transactionName; - } - - public Long getTimeout() { - return timeout; - } - - public void setTimeout(Long timeout) { - this.timeout = timeout; - } - - public Long getBeginTime() { - return beginTime; - } - - public void setBeginTime(Long beginTime) { - this.beginTime = beginTime; - } - - public String getApplicationData() { - return applicationData; - } - - public void setApplicationData(String applicationData) { - this.applicationData = applicationData; - } - - public Long getGmtCreate() { - return gmtCreate; - } - - public void setGmtCreate(Long gmtCreate) { - this.gmtCreate = gmtCreate; - } - - public Long getGmtModified() { - return gmtModified; - } - - public void setGmtModified(Long gmtModified) { - this.gmtModified = gmtModified; - } - - public Set getBranchSessionVOs() { - return branchSessionVOs; - } - - public void setBranchSessionVOs(Set branchSessionVOs) { - this.branchSessionVOs = branchSessionVOs; - } - - public static GlobalSessionVO convert(ResultSet rs) throws SQLException { - GlobalSessionVO globalSessionVO = new GlobalSessionVO(); - globalSessionVO.setXid(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_XID)); - globalSessionVO.setTransactionId(rs.getLong(ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID)); - globalSessionVO.setStatus(rs.getInt(ServerTableColumnsName.GLOBAL_TABLE_STATUS)); - globalSessionVO.setApplicationId(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_APPLICATION_ID)); - globalSessionVO - .setTransactionServiceGroup(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_SERVICE_GROUP)); - globalSessionVO.setTransactionName(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_NAME)); - globalSessionVO.setTimeout(rs.getLong(ServerTableColumnsName.GLOBAL_TABLE_TIMEOUT)); - globalSessionVO.setBeginTime(rs.getLong(ServerTableColumnsName.GLOBAL_TABLE_BEGIN_TIME)); - globalSessionVO.setApplicationData(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_APPLICATION_DATA)); - Timestamp gmtCreateTimestamp = rs.getTimestamp(ServerTableColumnsName.GLOBAL_TABLE_GMT_CREATE); - if (gmtCreateTimestamp != null) { - globalSessionVO.setGmtCreate(gmtCreateTimestamp.getTime()); - } - Timestamp gmtModifiedTimestamp = rs.getTimestamp(ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED); - if (gmtModifiedTimestamp != null) { - globalSessionVO.setGmtModified(gmtModifiedTimestamp.getTime()); - } - return globalSessionVO; - } - - @Override - public String toString() { - return "GlobalSessionVO{" + "xid='" + xid + '\'' + ", transactionId=" + transactionId + ", status=" + status - + ", applicationId='" + applicationId + '\'' + ", transactionServiceGroup='" + transactionServiceGroup - + '\'' + ", transactionName='" + transactionName + '\'' + ", timeout=" + timeout + ", beginTime=" - + beginTime + ", applicationData='" + applicationData + '\'' + ", gmtCreate=" + gmtCreate - + ", gmtModified=" + gmtModified + ", branchSessionVOs=" + branchSessionVOs + '}'; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/controller/ClusterController.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/controller/ClusterController.java deleted file mode 100644 index 4f00571853..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/controller/ClusterController.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.controller; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.PostConstruct; -import javax.annotation.Resource; -import javax.servlet.AsyncContext; -import javax.servlet.http.HttpServletRequest; - -import com.alipay.sofa.jraft.RouteTable; -import com.alipay.sofa.jraft.conf.Configuration; -import com.alipay.sofa.jraft.entity.PeerId; -import io.seata.common.ConfigurationKeys; -import io.seata.common.metadata.MetadataResponse; -import io.seata.common.metadata.Node; -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.console.result.Result; -import io.seata.server.cluster.manager.ClusterWatcherManager; -import io.seata.server.cluster.raft.RaftServer; -import io.seata.server.cluster.raft.RaftServerFactory; -import io.seata.server.cluster.raft.sync.msg.dto.RaftClusterMetadata; -import io.seata.server.cluster.watch.Watcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.context.ApplicationContext; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import static io.seata.common.ConfigurationKeys.STORE_MODE; -import static io.seata.common.DefaultValues.DEFAULT_SEATA_GROUP; - -/** - * @author funkye - */ -@RestController -@RequestMapping("/metadata/v1") -public class ClusterController { - - private static final Logger LOGGER = LoggerFactory.getLogger(ClusterController.class); - - @Resource - private ClusterWatcherManager clusterWatcherManager; - - private ServerProperties serverProperties; - - @Resource - ApplicationContext applicationContext; - - @PostConstruct - private void init() { - this.serverProperties = applicationContext.getBean(ServerProperties.class); - } - - @PostMapping("/changeCluster") - public Result changeCluster(@RequestParam String raftClusterStr) { - Result result = new Result<>(); - final Configuration newConf = new Configuration(); - if (!newConf.parse(raftClusterStr)) { - result.setMessage("fail to parse initConf:" + raftClusterStr); - } - else { - RaftServerFactory.groups().forEach(group -> { - RaftServerFactory.getCliServiceInstance() - .changePeers(group, RouteTable.getInstance().getConfiguration(group), newConf); - RouteTable.getInstance().updateConfiguration(group, newConf); - }); - } - return result; - } - - @GetMapping("/cluster") - public MetadataResponse cluster(String group) { - MetadataResponse metadataResponse = new MetadataResponse(); - if (StringUtils.isBlank(group)) { - group = ConfigurationFactory.getInstance() - .getConfig(ConfigurationKeys.SERVER_RAFT_GROUP, DEFAULT_SEATA_GROUP); - } - RaftServer raftServer = RaftServerFactory.getInstance().getRaftServer(group); - if (raftServer != null) { - String mode = ConfigurationFactory.getInstance().getConfig(STORE_MODE); - metadataResponse.setStoreMode(mode); - RouteTable routeTable = RouteTable.getInstance(); - try { - routeTable.refreshLeader(RaftServerFactory.getCliClientServiceInstance(), group, 1000); - PeerId leader = routeTable.selectLeader(group); - if (leader != null) { - Set nodes = new HashSet<>(); - RaftClusterMetadata raftClusterMetadata = raftServer.getRaftStateMachine().getRaftLeaderMetadata(); - Node leaderNode = raftServer.getRaftStateMachine().getRaftLeaderMetadata().getLeader(); - leaderNode.setGroup(group); - nodes.add(leaderNode); - nodes.addAll(raftClusterMetadata.getLearner()); - nodes.addAll(raftClusterMetadata.getFollowers()); - metadataResponse.setTerm(raftClusterMetadata.getTerm()); - metadataResponse.setNodes(new ArrayList<>(nodes)); - } - } - catch (Exception e) { - LOGGER.error("there is an exception to getting the leader address: {}", e.getMessage(), e); - } - } - return metadataResponse; - } - - @PostMapping("/watch") - public void watch(HttpServletRequest request, @RequestParam Map groupTerms, - @RequestParam(defaultValue = "28000") int timeout) { - AsyncContext context = request.startAsync(); - context.setTimeout(0L); - groupTerms.forEach((group, term) -> { - Watcher watcher = new Watcher<>(group, context, timeout, - Long.parseLong(String.valueOf(term))); - clusterWatcherManager.registryWatcher(watcher); - }); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/controller/HealthController.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/controller/HealthController.java deleted file mode 100644 index eaf7a31b76..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/controller/HealthController.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.controller; - -import io.seata.server.ServerRunner; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -/** - * @author spilledyear@outlook.com - */ -@Controller -@RequestMapping -public class HealthController { - - private static final String OK = "ok"; - - private static final String NOT_OK = "not_ok"; - - @Autowired - private ServerRunner serverRunner; - - @RequestMapping("/health") - @ResponseBody - String healthCheck() { - return serverRunner.started() ? OK : NOT_OK; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/AbstractCore.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/AbstractCore.java deleted file mode 100644 index f2c41d52a5..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/AbstractCore.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -import io.seata.core.context.RootContext; -import io.seata.core.exception.BranchTransactionException; -import io.seata.core.exception.GlobalTransactionException; -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.core.protocol.transaction.BranchCommitRequest; -import io.seata.core.protocol.transaction.BranchCommitResponse; -import io.seata.core.protocol.transaction.BranchRollbackRequest; -import io.seata.core.protocol.transaction.BranchRollbackResponse; -import io.seata.core.rpc.RemotingServer; -import io.seata.server.lock.LockManager; -import io.seata.server.lock.LockerManagerFactory; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHelper; -import io.seata.server.session.SessionHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import static io.seata.core.exception.TransactionExceptionCode.BranchTransactionNotExist; -import static io.seata.core.exception.TransactionExceptionCode.FailedToAddBranch; -import static io.seata.core.exception.TransactionExceptionCode.GlobalTransactionNotActive; -import static io.seata.core.exception.TransactionExceptionCode.GlobalTransactionStatusInvalid; -import static io.seata.core.exception.TransactionExceptionCode.FailedToSendBranchCommitRequest; -import static io.seata.core.exception.TransactionExceptionCode.FailedToSendBranchRollbackRequest; - -/** - * The type abstract core. - * - * @author ph3636 - */ -public abstract class AbstractCore implements Core { - - protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractCore.class); - - protected LockManager lockManager = LockerManagerFactory.getLockManager(); - - protected RemotingServer remotingServer; - - protected AbstractCore(RemotingServer remotingServer) { - if (remotingServer == null) { - throw new IllegalArgumentException("remotingServer must be not null"); - } - this.remotingServer = remotingServer; - } - - public abstract BranchType getHandleBranchType(); - - @Override - public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, - String applicationData, String lockKeys) throws TransactionException { - GlobalSession globalSession = assertGlobalSessionNotNull(xid, false); - return SessionHolder.lockAndExecute(globalSession, () -> { - globalSessionStatusCheck(globalSession); - BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, branchType, resourceId, - applicationData, lockKeys, clientId); - MDC.put(RootContext.MDC_KEY_BRANCH_ID, String.valueOf(branchSession.getBranchId())); - branchSessionLock(globalSession, branchSession); - try { - globalSession.addBranch(branchSession); - } - catch (RuntimeException ex) { - branchSessionUnlock(branchSession); - throw new BranchTransactionException(FailedToAddBranch, - String.format("Failed to store branch xid = %s branchId = %s", globalSession.getXid(), - branchSession.getBranchId()), - ex); - } - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Register branch successfully, xid = {}, branchId = {}, resourceId = {} ,lockKeys = {}", - globalSession.getXid(), branchSession.getBranchId(), resourceId, lockKeys); - } - return branchSession.getBranchId(); - }); - } - - protected void globalSessionStatusCheck(GlobalSession globalSession) throws GlobalTransactionException { - if (!globalSession.isActive()) { - throw new GlobalTransactionException(GlobalTransactionNotActive, String.format( - "Could not register branch into global session xid = %s status = %s, cause by globalSession not active", - globalSession.getXid(), globalSession.getStatus())); - } - if (globalSession.getStatus() != GlobalStatus.Begin) { - throw new GlobalTransactionException(GlobalTransactionStatusInvalid, - String.format( - "Could not register branch into global session xid = %s status = %s while expecting %s", - globalSession.getXid(), globalSession.getStatus(), GlobalStatus.Begin)); - } - } - - protected void branchSessionLock(GlobalSession globalSession, BranchSession branchSession) - throws TransactionException { - - } - - protected void branchSessionUnlock(BranchSession branchSession) throws TransactionException { - - } - - private GlobalSession assertGlobalSessionNotNull(String xid, boolean withBranchSessions) - throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid, withBranchSessions); - if (globalSession == null) { - throw new GlobalTransactionException(TransactionExceptionCode.GlobalTransactionNotExist, - String.format("Could not found global transaction xid = %s, may be has finished.", xid)); - } - return globalSession; - } - - @Override - public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status, - String applicationData) throws TransactionException { - GlobalSession globalSession = assertGlobalSessionNotNull(xid, true); - BranchSession branchSession = globalSession.getBranch(branchId); - if (branchSession == null) { - throw new BranchTransactionException(BranchTransactionNotExist, - String.format("Could not found branch session xid = %s branchId = %s", xid, branchId)); - } - branchSession.setApplicationData(applicationData); - globalSession.changeBranchStatus(branchSession, status); - - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Report branch status successfully, xid = {}, branchId = {}", globalSession.getXid(), - branchSession.getBranchId()); - } - } - - @Override - public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys) - throws TransactionException { - return true; - } - - @Override - public BranchStatus branchCommit(GlobalSession globalSession, BranchSession branchSession) - throws TransactionException { - try { - BranchCommitRequest request = new BranchCommitRequest(); - request.setXid(branchSession.getXid()); - request.setBranchId(branchSession.getBranchId()); - request.setResourceId(branchSession.getResourceId()); - request.setApplicationData(branchSession.getApplicationData()); - request.setBranchType(branchSession.getBranchType()); - return branchCommitSend(request, globalSession, branchSession); - } - catch (IOException | TimeoutException e) { - throw new BranchTransactionException(FailedToSendBranchCommitRequest, - String.format("Send branch commit failed, xid = %s branchId = %s", branchSession.getXid(), - branchSession.getBranchId()), - e); - } - } - - protected BranchStatus branchCommitSend(BranchCommitRequest request, GlobalSession globalSession, - BranchSession branchSession) throws IOException, TimeoutException { - - BranchCommitResponse response = (BranchCommitResponse) remotingServer - .sendSyncRequest(branchSession.getResourceId(), branchSession.getClientId(), request, branchSession.isAT()); - return response.getBranchStatus(); - } - - @Override - public BranchStatus branchRollback(GlobalSession globalSession, BranchSession branchSession) - throws TransactionException { - try { - BranchRollbackRequest request = new BranchRollbackRequest(); - request.setXid(branchSession.getXid()); - request.setBranchId(branchSession.getBranchId()); - request.setResourceId(branchSession.getResourceId()); - request.setApplicationData(branchSession.getApplicationData()); - request.setBranchType(branchSession.getBranchType()); - return branchRollbackSend(request, globalSession, branchSession); - } - catch (IOException | TimeoutException e) { - throw new BranchTransactionException(FailedToSendBranchRollbackRequest, - String.format("Send branch rollback failed, xid = %s branchId = %s", branchSession.getXid(), - branchSession.getBranchId()), - e); - } - } - - protected BranchStatus branchRollbackSend(BranchRollbackRequest request, GlobalSession globalSession, - BranchSession branchSession) throws IOException, TimeoutException { - - BranchRollbackResponse response = (BranchRollbackResponse) remotingServer - .sendSyncRequest(branchSession.getResourceId(), branchSession.getClientId(), request, branchSession.isAT()); - return response.getBranchStatus(); - } - - @Override - public String begin(String applicationId, String transactionServiceGroup, String name, int timeout) - throws TransactionException { - return null; - } - - @Override - public GlobalStatus commit(String xid) throws TransactionException { - return null; - } - - @Override - public boolean doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException { - return true; - } - - @Override - public GlobalStatus globalReport(String xid, GlobalStatus globalStatus) throws TransactionException { - return null; - } - - @Override - public GlobalStatus rollback(String xid) throws TransactionException { - return null; - } - - @Override - public boolean doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException { - return true; - } - - @Override - public GlobalStatus getStatus(String xid) throws TransactionException { - return null; - } - - @Override - public void doGlobalReport(GlobalSession globalSession, String xid, GlobalStatus globalStatus) - throws TransactionException { - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/Core.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/Core.java deleted file mode 100644 index 8def2e56f8..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/Core.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.GlobalStatus; -import io.seata.server.session.GlobalSession; - -/** - * The interface Core. - * - * @author sharajava - */ -public interface Core extends TransactionCoordinatorInbound, TransactionCoordinatorOutbound { - - /** - * Do global commit. - * @param globalSession the global session - * @param retrying the retrying - * @return is global commit. - * @throws TransactionException the transaction exception - */ - boolean doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException; - - /** - * Do global rollback. - * @param globalSession the global session - * @param retrying the retrying - * @return is global rollback. - * @throws TransactionException the transaction exception - */ - boolean doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException; - - /** - * Do global report. - * @param globalSession the global session - * @param xid Transaction id. - * @param param the global status - * @throws TransactionException the transaction exception - */ - void doGlobalReport(GlobalSession globalSession, String xid, GlobalStatus param) throws TransactionException; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java deleted file mode 100644 index 4b40a7b57a..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ /dev/null @@ -1,629 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import io.netty.channel.Channel; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.util.CollectionUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.context.RootContext; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.GlobalStatus; -import io.seata.core.protocol.AbstractMessage; -import io.seata.core.protocol.AbstractResultMessage; -import io.seata.core.protocol.transaction.*; -import io.seata.core.rpc.Disposable; -import io.seata.core.rpc.RemotingServer; -import io.seata.core.rpc.RpcContext; -import io.seata.core.rpc.TransactionMessageHandler; -import io.seata.core.rpc.netty.ChannelManager; -import io.seata.core.rpc.netty.NettyRemotingServer; -import io.seata.server.AbstractTCInboundHandler; -import io.seata.server.metrics.MetricsPublisher; -import io.seata.server.session.*; -import io.seata.server.store.StoreConfig; -import org.apache.commons.lang.time.DateFormatUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import static io.seata.common.Constants.*; -import static io.seata.common.DefaultValues.*; - -/** - * The type Default coordinator. - */ -public class DefaultCoordinator extends AbstractTCInboundHandler implements TransactionMessageHandler, Disposable { - - protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultCoordinator.class); - - private static final int TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS = 5000; - - private static final String TIME_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS"; - - /** - * The constant COMMITTING_RETRY_PERIOD. - */ - protected static final long COMMITTING_RETRY_PERIOD = CONFIG.getLong(ConfigurationKeys.COMMITING_RETRY_PERIOD, - DEFAULT_COMMITING_RETRY_PERIOD); - - /** - * The constant ASYNC_COMMITTING_RETRY_PERIOD. - */ - protected static final long ASYNC_COMMITTING_RETRY_PERIOD = CONFIG - .getLong(ConfigurationKeys.ASYNC_COMMITING_RETRY_PERIOD, DEFAULT_ASYNC_COMMITTING_RETRY_PERIOD); - - /** - * The constant ROLLBACKING_RETRY_PERIOD. - */ - protected static final long ROLLBACKING_RETRY_PERIOD = CONFIG.getLong(ConfigurationKeys.ROLLBACKING_RETRY_PERIOD, - DEFAULT_ROLLBACKING_RETRY_PERIOD); - - /** - * The constant TIMEOUT_RETRY_PERIOD. - */ - protected static final long TIMEOUT_RETRY_PERIOD = CONFIG.getLong(ConfigurationKeys.TIMEOUT_RETRY_PERIOD, - DEFAULT_TIMEOUT_RETRY_PERIOD); - - /** - * The Transaction undo log delete period. - */ - protected static final long UNDO_LOG_DELETE_PERIOD = CONFIG - .getLong(ConfigurationKeys.TRANSACTION_UNDO_LOG_DELETE_PERIOD, DEFAULT_UNDO_LOG_DELETE_PERIOD); - - /** - * The Transaction undo log delay delete period. - */ - protected static final long UNDO_LOG_DELAY_DELETE_PERIOD = 3 * 60 * 1000; - - private static final int ALWAYS_RETRY_BOUNDARY = 0; - - /** - * default branch async queue size. - */ - private static final int DEFAULT_BRANCH_ASYNC_QUEUE_SIZE = 5000; - - /** - * the pool size of branch asynchronous remove thread pool. - */ - private static final int BRANCH_ASYNC_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2; - - private static final long MAX_COMMIT_RETRY_TIMEOUT = ConfigurationFactory.getInstance() - .getLong(ConfigurationKeys.MAX_COMMIT_RETRY_TIMEOUT, DEFAULT_MAX_COMMIT_RETRY_TIMEOUT); - - private static final long MAX_ROLLBACK_RETRY_TIMEOUT = ConfigurationFactory.getInstance() - .getLong(ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT); - - private static final boolean ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE = ConfigurationFactory.getInstance() - .getBoolean(ConfigurationKeys.ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE, - DEFAULT_ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE); - - private final ScheduledThreadPoolExecutor retryRollbacking = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory(RETRY_ROLLBACKING, 1)); - - private final ScheduledThreadPoolExecutor retryCommitting = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory(RETRY_COMMITTING, 1)); - - private final ScheduledThreadPoolExecutor asyncCommitting = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory(ASYNC_COMMITTING, 1)); - - private final ScheduledThreadPoolExecutor timeoutCheck = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory(TX_TIMEOUT_CHECK, 1)); - - private final ScheduledThreadPoolExecutor undoLogDelete = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory(UNDOLOG_DELETE, 1)); - - private final GlobalStatus[] rollbackingStatuses = new GlobalStatus[] { GlobalStatus.TimeoutRollbacking, - GlobalStatus.TimeoutRollbackRetrying, GlobalStatus.RollbackRetrying, GlobalStatus.Rollbacking }; - - private final GlobalStatus[] retryCommittingStatuses = new GlobalStatus[] { GlobalStatus.Committing, - GlobalStatus.CommitRetrying, GlobalStatus.Committed }; - - private final ThreadPoolExecutor branchRemoveExecutor; - - private RemotingServer remotingServer; - - private final DefaultCore core; - - private static volatile DefaultCoordinator instance; - - /** - * Instantiates a new Default coordinator. - * @param remotingServer the remoting server - */ - protected DefaultCoordinator(RemotingServer remotingServer) { - if (remotingServer == null) { - throw new IllegalArgumentException("RemotingServer not allowed be null."); - } - this.remotingServer = remotingServer; - this.core = new DefaultCore(remotingServer); - boolean enableBranchAsyncRemove = CONFIG.getBoolean(ConfigurationKeys.ENABLE_BRANCH_ASYNC_REMOVE, - DEFAULT_ENABLE_BRANCH_ASYNC_REMOVE); - // create branchRemoveExecutor - if (enableBranchAsyncRemove && StoreConfig.getSessionMode() != StoreConfig.SessionMode.FILE) { - branchRemoveExecutor = new ThreadPoolExecutor(BRANCH_ASYNC_POOL_SIZE, BRANCH_ASYNC_POOL_SIZE, - Integer.MAX_VALUE, TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>(CONFIG.getInt(ConfigurationKeys.SESSION_BRANCH_ASYNC_QUEUE_SIZE, - DEFAULT_BRANCH_ASYNC_QUEUE_SIZE)), - new NamedThreadFactory("branchSessionRemove", BRANCH_ASYNC_POOL_SIZE), - new ThreadPoolExecutor.CallerRunsPolicy()); - } - else { - branchRemoveExecutor = null; - } - } - - public static DefaultCoordinator getInstance(RemotingServer remotingServer) { - if (null == instance) { - synchronized (DefaultCoordinator.class) { - if (null == instance) { - StoreConfig.SessionMode storeMode = StoreConfig.getSessionMode(); - instance = Objects.equals(StoreConfig.SessionMode.RAFT, storeMode) - ? new RaftCoordinator(remotingServer) : new DefaultCoordinator(remotingServer); - } - } - } - return instance; - } - - public static DefaultCoordinator getInstance() { - if (null == instance) { - throw new IllegalArgumentException("The instance has not been created."); - } - return instance; - } - - /** - * Asynchronous remove branch. - * @param globalSession the globalSession - * @param branchSession the branchSession - */ - public void doBranchRemoveAsync(GlobalSession globalSession, BranchSession branchSession) { - if (globalSession == null) { - return; - } - branchRemoveExecutor.execute(new BranchRemoveTask(globalSession, branchSession)); - } - - /** - * Asynchronous remove all branch. - * @param globalSession the globalSession - */ - public void doBranchRemoveAllAsync(GlobalSession globalSession) { - if (globalSession == null) { - return; - } - branchRemoveExecutor.execute(new BranchRemoveTask(globalSession)); - } - - @Override - protected void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response, RpcContext rpcContext) - throws TransactionException { - response.setXid(core.begin(rpcContext.getApplicationId(), rpcContext.getTransactionServiceGroup(), - request.getTransactionName(), request.getTimeout())); - if (LOGGER.isInfoEnabled()) { - LOGGER.info( - "Begin new global transaction applicationId: {},transactionServiceGroup: {}, transactionName: {},timeout:{},xid:{}", - rpcContext.getApplicationId(), rpcContext.getTransactionServiceGroup(), - request.getTransactionName(), request.getTimeout(), response.getXid()); - } - } - - @Override - protected void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response, RpcContext rpcContext) - throws TransactionException { - MDC.put(RootContext.MDC_KEY_XID, request.getXid()); - response.setGlobalStatus(core.commit(request.getXid())); - } - - @Override - protected void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response, - RpcContext rpcContext) throws TransactionException { - MDC.put(RootContext.MDC_KEY_XID, request.getXid()); - response.setGlobalStatus(core.rollback(request.getXid())); - } - - @Override - protected void doGlobalStatus(GlobalStatusRequest request, GlobalStatusResponse response, RpcContext rpcContext) - throws TransactionException { - MDC.put(RootContext.MDC_KEY_XID, request.getXid()); - response.setGlobalStatus(core.getStatus(request.getXid())); - } - - @Override - protected void doGlobalReport(GlobalReportRequest request, GlobalReportResponse response, RpcContext rpcContext) - throws TransactionException { - MDC.put(RootContext.MDC_KEY_XID, request.getXid()); - response.setGlobalStatus(core.globalReport(request.getXid(), request.getGlobalStatus())); - } - - @Override - protected void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response, - RpcContext rpcContext) throws TransactionException { - MDC.put(RootContext.MDC_KEY_XID, request.getXid()); - response.setBranchId(core.branchRegister(request.getBranchType(), request.getResourceId(), - rpcContext.getClientId(), request.getXid(), request.getApplicationData(), request.getLockKey())); - } - - @Override - protected void doBranchReport(BranchReportRequest request, BranchReportResponse response, RpcContext rpcContext) - throws TransactionException { - MDC.put(RootContext.MDC_KEY_XID, request.getXid()); - MDC.put(RootContext.MDC_KEY_BRANCH_ID, String.valueOf(request.getBranchId())); - core.branchReport(request.getBranchType(), request.getXid(), request.getBranchId(), request.getStatus(), - request.getApplicationData()); - } - - @Override - protected void doLockCheck(GlobalLockQueryRequest request, GlobalLockQueryResponse response, RpcContext rpcContext) - throws TransactionException { - MDC.put(RootContext.MDC_KEY_XID, request.getXid()); - response.setLockable(core.lockQuery(request.getBranchType(), request.getResourceId(), request.getXid(), - request.getLockKey())); - } - - /** - * Timeout check. - */ - protected void timeoutCheck() { - SessionCondition sessionCondition = new SessionCondition(GlobalStatus.Begin); - sessionCondition.setLazyLoadBranch(true); - Collection beginGlobalsessions = SessionHolder.getRootSessionManager() - .findGlobalSessions(sessionCondition); - if (CollectionUtils.isEmpty(beginGlobalsessions)) { - return; - } - if (!beginGlobalsessions.isEmpty() && LOGGER.isDebugEnabled()) { - LOGGER.debug("Global transaction timeout check begin, size: {}", beginGlobalsessions.size()); - } - SessionHelper.forEach(beginGlobalsessions, globalSession -> { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(globalSession.getXid() + " " + globalSession.getStatus() + " " - + globalSession.getBeginTime() + " " + globalSession.getTimeout()); - } - SessionHolder.lockAndExecute(globalSession, () -> { - if (globalSession.getStatus() != GlobalStatus.Begin || !globalSession.isTimeout()) { - return false; - } - - LOGGER.warn( - "Global transaction[{}] is timeout and will be rollback,transaction begin time:{} and now:{}", - globalSession.getXid(), - DateFormatUtils.format(globalSession.getBeginTime(), TIME_FORMAT_PATTERN), - DateFormatUtils.format(System.currentTimeMillis(), TIME_FORMAT_PATTERN)); - - globalSession.close(); - globalSession.changeGlobalStatus(GlobalStatus.TimeoutRollbacking); - - // transaction timeout and start rollbacking event - MetricsPublisher.postSessionDoingEvent(globalSession, GlobalStatus.TimeoutRollbacking.name(), false, - false); - - return true; - }); - }); - if (!beginGlobalsessions.isEmpty() && LOGGER.isDebugEnabled()) { - LOGGER.debug("Global transaction timeout check end. "); - } - - } - - /** - * Handle retry rollbacking. - */ - protected void handleRetryRollbacking() { - SessionCondition sessionCondition = new SessionCondition(rollbackingStatuses); - sessionCondition.setLazyLoadBranch(true); - Collection rollbackingSessions = SessionHolder.getRootSessionManager() - .findGlobalSessions(sessionCondition); - if (CollectionUtils.isEmpty(rollbackingSessions)) { - return; - } - long now = System.currentTimeMillis(); - SessionHelper.forEach(rollbackingSessions, rollbackingSession -> { - try { - // prevent repeated rollback - if (rollbackingSession.getStatus() == GlobalStatus.Rollbacking && !rollbackingSession.isDeadSession()) { - // The function of this 'return' is 'continue'. - return; - } - if (isRetryTimeout(now, MAX_ROLLBACK_RETRY_TIMEOUT, rollbackingSession.getBeginTime())) { - if (ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE) { - rollbackingSession.clean(); - } - - SessionHelper.endRollbackFailed(rollbackingSession, true, true); - - // The function of this 'return' is 'continue'. - return; - } - core.doGlobalRollback(rollbackingSession, true); - } - catch (TransactionException ex) { - LOGGER.error("Failed to retry rollbacking [{}] {} {}", rollbackingSession.getXid(), ex.getCode(), - ex.getMessage()); - } - }); - } - - /** - * Handle retry committing. - */ - protected void handleRetryCommitting() { - SessionCondition retryCommittingSessionCondition = new SessionCondition(retryCommittingStatuses); - retryCommittingSessionCondition.setLazyLoadBranch(true); - Collection committingSessions = SessionHolder.getRootSessionManager() - .findGlobalSessions(retryCommittingSessionCondition); - if (CollectionUtils.isEmpty(committingSessions)) { - return; - } - long now = System.currentTimeMillis(); - SessionHelper.forEach(committingSessions, committingSession -> { - try { - // prevent repeated commit - if ((GlobalStatus.Committing.equals(committingSession.getStatus()) - || GlobalStatus.Committed.equals(committingSession.getStatus())) - && !committingSession.isDeadSession()) { - // The function of this 'return' is 'continue'. - return; - } - if (isRetryTimeout(now, MAX_COMMIT_RETRY_TIMEOUT, committingSession.getBeginTime())) { - - // commit retry timeout event - SessionHelper.endCommitFailed(committingSession, true, true); - - // The function of this 'return' is 'continue'. - return; - } - if (GlobalStatus.Committed.equals(committingSession.getStatus()) - && committingSession.getBranchSessions().isEmpty()) { - SessionHelper.endCommitted(committingSession, true); - } - core.doGlobalCommit(committingSession, true); - } - catch (TransactionException ex) { - LOGGER.error("Failed to retry committing [{}] {} {}", committingSession.getXid(), ex.getCode(), - ex.getMessage()); - } - }); - } - - /** - * Handle async committing. - */ - protected void handleAsyncCommitting() { - SessionCondition sessionCondition = new SessionCondition(GlobalStatus.AsyncCommitting); - Collection asyncCommittingSessions = SessionHolder.getRootSessionManager() - .findGlobalSessions(sessionCondition); - if (CollectionUtils.isEmpty(asyncCommittingSessions)) { - return; - } - SessionHelper.forEach(asyncCommittingSessions, asyncCommittingSession -> { - try { - core.doGlobalCommit(asyncCommittingSession, true); - } - catch (TransactionException ex) { - LOGGER.error("Failed to async committing [{}] {} {}", asyncCommittingSession.getXid(), ex.getCode(), - ex.getMessage(), ex); - } - }); - } - - /** - * Undo log delete. - */ - protected void undoLogDelete() { - Map rmChannels = ChannelManager.getRmChannels(); - if (rmChannels == null || rmChannels.isEmpty()) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("no active rm channels to delete undo log"); - } - return; - } - short saveDays = CONFIG.getShort(ConfigurationKeys.TRANSACTION_UNDO_LOG_SAVE_DAYS, - UndoLogDeleteRequest.DEFAULT_SAVE_DAYS); - for (Map.Entry channelEntry : rmChannels.entrySet()) { - String resourceId = channelEntry.getKey(); - UndoLogDeleteRequest deleteRequest = new UndoLogDeleteRequest(); - deleteRequest.setResourceId(resourceId); - deleteRequest.setSaveDays(saveDays > 0 ? saveDays : UndoLogDeleteRequest.DEFAULT_SAVE_DAYS); - try { - remotingServer.sendAsyncRequest(channelEntry.getValue(), deleteRequest); - } - catch (Exception e) { - LOGGER.error("Failed to async delete undo log resourceId = {}, exception: {}", resourceId, - e.getMessage()); - } - } - } - - private boolean isRetryTimeout(long now, long timeout, long beginTime) { - return timeout >= ALWAYS_RETRY_BOUNDARY && now - beginTime > timeout; - } - - /** - * Init. - */ - public void init() { - retryRollbacking.scheduleAtFixedRate( - () -> SessionHolder.distributedLockAndExecute(RETRY_ROLLBACKING, this::handleRetryRollbacking), 0, - ROLLBACKING_RETRY_PERIOD, TimeUnit.MILLISECONDS); - - retryCommitting.scheduleAtFixedRate( - () -> SessionHolder.distributedLockAndExecute(RETRY_COMMITTING, this::handleRetryCommitting), 0, - COMMITTING_RETRY_PERIOD, TimeUnit.MILLISECONDS); - - asyncCommitting.scheduleAtFixedRate( - () -> SessionHolder.distributedLockAndExecute(ASYNC_COMMITTING, this::handleAsyncCommitting), 0, - ASYNC_COMMITTING_RETRY_PERIOD, TimeUnit.MILLISECONDS); - - timeoutCheck.scheduleAtFixedRate( - () -> SessionHolder.distributedLockAndExecute(TX_TIMEOUT_CHECK, this::timeoutCheck), 0, - TIMEOUT_RETRY_PERIOD, TimeUnit.MILLISECONDS); - - undoLogDelete.scheduleAtFixedRate( - () -> SessionHolder.distributedLockAndExecute(UNDOLOG_DELETE, this::undoLogDelete), - UNDO_LOG_DELAY_DELETE_PERIOD, UNDO_LOG_DELETE_PERIOD, TimeUnit.MILLISECONDS); - } - - @Override - public AbstractResultMessage onRequest(AbstractMessage request, RpcContext context) { - if (!(request instanceof AbstractTransactionRequestToTC)) { - throw new IllegalArgumentException(); - } - AbstractTransactionRequestToTC transactionRequest = (AbstractTransactionRequestToTC) request; - transactionRequest.setTCInboundHandler(this); - - return transactionRequest.handle(context); - } - - @Override - public void onResponse(AbstractResultMessage response, RpcContext context) { - if (!(response instanceof AbstractTransactionResponse)) { - throw new IllegalArgumentException(); - } - - } - - @Override - public void destroy() { - // 1. first shutdown timed task - retryRollbacking.shutdown(); - retryCommitting.shutdown(); - asyncCommitting.shutdown(); - timeoutCheck.shutdown(); - undoLogDelete.shutdown(); - if (branchRemoveExecutor != null) { - branchRemoveExecutor.shutdown(); - } - try { - retryRollbacking.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - retryCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - asyncCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - timeoutCheck.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - undoLogDelete.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - if (branchRemoveExecutor != null) { - branchRemoveExecutor.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - } - } - catch (InterruptedException ignore) { - - } - // 2. second close netty flow - if (remotingServer instanceof NettyRemotingServer) { - ((NettyRemotingServer) remotingServer).destroy(); - } - // 3. third destroy SessionHolder - SessionHolder.destroy(); - instance = null; - } - - /** - * only used for mock test. - * @param remotingServer 远程服务 - */ - public void setRemotingServer(RemotingServer remotingServer) { - this.remotingServer = remotingServer; - } - - /** - * the task to remove branchSession. - */ - static class BranchRemoveTask implements Runnable { - - /** - * the globalSession. - */ - private final GlobalSession globalSession; - - /** - * the branchSession. - */ - private final BranchSession branchSession; - - /** - * If you use this construct, the task will remove the branchSession provided by - * the parameter. - * @param globalSession the globalSession - */ - BranchRemoveTask(GlobalSession globalSession, BranchSession branchSession) { - this.globalSession = globalSession; - if (branchSession == null) { - throw new IllegalArgumentException("BranchSession can`t be null!"); - } - this.branchSession = branchSession; - } - - /** - * If you use this construct, the task will remove all branchSession. - * @param globalSession the globalSession - */ - BranchRemoveTask(GlobalSession globalSession) { - this.globalSession = globalSession; - this.branchSession = null; - } - - @Override - public void run() { - if (globalSession == null) { - return; - } - try { - MDC.put(RootContext.MDC_KEY_XID, globalSession.getXid()); - if (branchSession != null) { - doRemove(branchSession); - } - else { - globalSession.getSortedBranches().parallelStream().forEach(this::doRemove); - } - } - catch (Exception unKnowException) { - LOGGER.error("Asynchronous delete branchSession error, xid = {}", globalSession.getXid(), - unKnowException); - } - finally { - MDC.remove(RootContext.MDC_KEY_XID); - } - } - - private void doRemove(BranchSession bt) { - try { - MDC.put(RootContext.MDC_KEY_BRANCH_ID, String.valueOf(bt.getBranchId())); - globalSession.removeBranch(bt); - LOGGER.info("Asynchronous delete branchSession successfully, xid = {}, branchId = {}", - globalSession.getXid(), bt.getBranchId()); - } - catch (TransactionException transactionException) { - LOGGER.error("Asynchronous delete branchSession error, xid = {}, branchId = {}", globalSession.getXid(), - bt.getBranchId(), transactionException); - } - finally { - MDC.remove(RootContext.MDC_KEY_BRANCH_ID); - } - } - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/DefaultCore.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/DefaultCore.java deleted file mode 100644 index 1d577d42c8..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/DefaultCore.java +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import io.seata.common.DefaultValues; -import io.seata.common.exception.NotSupportYetException; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.util.CollectionUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.core.context.RootContext; -import io.seata.core.exception.TransactionException; -import io.seata.core.logger.StackTraceLogger; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.core.rpc.RemotingServer; -import io.seata.server.metrics.MetricsPublisher; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHelper; -import io.seata.server.session.SessionHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import static io.seata.common.ConfigurationKeys.ENABLE_PARALLEL_HANDLE_BRANCH_KEY; -import static io.seata.common.ConfigurationKeys.XAER_NOTA_RETRY_TIMEOUT; -import static io.seata.server.session.BranchSessionHandler.CONTINUE; - -/** - * The type Default core. - * - * @author sharajava - */ -public class DefaultCore implements Core { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCore.class); - - private static final int RETRY_XAER_NOTA_TIMEOUT = ConfigurationFactory.getInstance() - .getInt(XAER_NOTA_RETRY_TIMEOUT, DefaultValues.DEFAULT_XAER_NOTA_RETRY_TIMEOUT); - - private static Map coreMap = new ConcurrentHashMap<>(); - - private static final boolean PARALLEL_HANDLE_BRANCH = ConfigurationFactory.getInstance() - .getBoolean(ENABLE_PARALLEL_HANDLE_BRANCH_KEY, false); - - /** - * get the Default core. - * @param remotingServer the remoting server - */ - public DefaultCore(RemotingServer remotingServer) { - List allCore = EnhancedServiceLoader.loadAll(AbstractCore.class, - new Class[] { RemotingServer.class }, new Object[] { remotingServer }); - if (CollectionUtils.isNotEmpty(allCore)) { - for (AbstractCore core : allCore) { - coreMap.put(core.getHandleBranchType(), core); - } - } - } - - /** - * get core. - * @param branchType the branchType - * @return the core - */ - public AbstractCore getCore(BranchType branchType) { - AbstractCore core = coreMap.get(branchType); - if (core == null) { - throw new NotSupportYetException("unsupported type:" + branchType.name()); - } - return core; - } - - /** - * only for mock. - * @param branchType the branchType - * @param core the core - */ - public void mockCore(BranchType branchType, AbstractCore core) { - coreMap.put(branchType, core); - } - - @Override - public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, - String applicationData, String lockKeys) throws TransactionException { - return getCore(branchType).branchRegister(branchType, resourceId, clientId, xid, applicationData, lockKeys); - } - - @Override - public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status, - String applicationData) throws TransactionException { - getCore(branchType).branchReport(branchType, xid, branchId, status, applicationData); - } - - @Override - public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys) - throws TransactionException { - return getCore(branchType).lockQuery(branchType, resourceId, xid, lockKeys); - } - - @Override - public BranchStatus branchCommit(GlobalSession globalSession, BranchSession branchSession) - throws TransactionException { - return getCore(branchSession.getBranchType()).branchCommit(globalSession, branchSession); - } - - @Override - public BranchStatus branchRollback(GlobalSession globalSession, BranchSession branchSession) - throws TransactionException { - return getCore(branchSession.getBranchType()).branchRollback(globalSession, branchSession); - } - - @Override - public String begin(String applicationId, String transactionServiceGroup, String name, int timeout) - throws TransactionException { - GlobalSession session = GlobalSession.createGlobalSession(applicationId, transactionServiceGroup, name, - timeout); - MDC.put(RootContext.MDC_KEY_XID, session.getXid()); - - session.begin(); - - // transaction start event - MetricsPublisher.postSessionDoingEvent(session, false); - - return session.getXid(); - } - - @Override - public GlobalStatus commit(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - if (globalSession == null) { - return GlobalStatus.Finished; - } - - if (globalSession.isTimeout()) { - LOGGER.info("TC detected timeout, xid = {}", globalSession.getXid()); - return GlobalStatus.TimeoutRollbacking; - } - - // just lock changeStatus - boolean shouldCommit = SessionHolder.lockAndExecute(globalSession, () -> { - boolean shouldCommitNow = false; - if (globalSession.getStatus() == GlobalStatus.Begin) { - // Highlight: Firstly, close the session, then no more branch can be - // registered. - globalSession.close(); - if (globalSession.canBeCommittedAsync()) { - globalSession.asyncCommit(); - MetricsPublisher.postSessionDoneEvent(globalSession, GlobalStatus.Committed, false, false); - } - else { - globalSession.changeGlobalStatus(GlobalStatus.Committing); - shouldCommitNow = true; - } - // clean session after changing status successfully. - globalSession.clean(); - } - return shouldCommitNow; - }); - - if (shouldCommit) { - boolean success = doGlobalCommit(globalSession, false); - // If successful and all remaining branches can be committed asynchronously, - // do async commit. - if (success && globalSession.hasBranch() && globalSession.canBeCommittedAsync()) { - globalSession.asyncCommit(); - return GlobalStatus.Committed; - } - else { - return globalSession.getStatus(); - } - } - else { - return globalSession.getStatus() == GlobalStatus.AsyncCommitting ? GlobalStatus.Committed - : globalSession.getStatus(); - } - } - - @Override - public boolean doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException { - boolean success = true; - // start committing event - MetricsPublisher.postSessionDoingEvent(globalSession, retrying); - - if (globalSession.isSaga()) { - success = getCore(BranchType.SAGA).doGlobalCommit(globalSession, retrying); - } - else { - List branchSessions = globalSession.getSortedBranches(); - Boolean result = SessionHelper.forEach(branchSessions, branchSession -> { - // if not retrying, skip the canBeCommittedAsync branches - if (!retrying && branchSession.canBeCommittedAsync()) { - return CONTINUE; - } - - BranchStatus currentStatus = branchSession.getStatus(); - if (currentStatus == BranchStatus.PhaseOne_Failed) { - SessionHelper.removeBranch(globalSession, branchSession, !retrying); - return CONTINUE; - } - try { - BranchStatus branchStatus = getCore(branchSession.getBranchType()).branchCommit(globalSession, - branchSession); - if (isXaerNotaTimeout(globalSession, branchStatus)) { - LOGGER.info("Commit branch XAER_NOTA retry timeout, xid = {} branchId = {}", - globalSession.getXid(), branchSession.getBranchId()); - branchStatus = BranchStatus.PhaseTwo_Committed; - } - switch (branchStatus) { - case PhaseTwo_Committed: - SessionHelper.removeBranch(globalSession, branchSession, !retrying); - LOGGER.info("Commit branch transaction successfully, xid = {} branchId = {}", - globalSession.getXid(), branchSession.getBranchId()); - return CONTINUE; - case PhaseTwo_CommitFailed_Unretryable: - // not at branch - SessionHelper.endCommitFailed(globalSession, retrying); - LOGGER.error( - "Committing global transaction[{}] finally failed, caused by branch transaction[{}] commit failed.", - globalSession.getXid(), branchSession.getBranchId()); - return false; - - default: - if (!retrying) { - globalSession.queueToRetryCommit(); - return false; - } - if (globalSession.canBeCommittedAsync()) { - LOGGER.error("Committing branch transaction[{}], status:{} and will retry later", - branchSession.getBranchId(), branchStatus); - return CONTINUE; - } - else { - LOGGER.error( - "Committing global transaction[{}] failed, caused by branch transaction[{}] commit failed, will retry later.", - globalSession.getXid(), branchSession.getBranchId()); - return false; - } - } - } - catch (Exception ex) { - String commitInfo = retrying ? "Global commit continue" : "Global commit failed"; - StackTraceLogger.error(LOGGER, ex, "Committing branch transaction exception:retrying={}, {}, {}", - new String[] { String.valueOf(retrying), branchSession.toString(), commitInfo }); - if (!retrying) { - globalSession.queueToRetryCommit(); - throw new TransactionException(ex); - } - } - return CONTINUE; - }, PARALLEL_HANDLE_BRANCH && branchSessions.size() >= 2); - // Return if the result is not null - if (result != null) { - return result; - } - // If has branch and not all remaining branches can be committed - // asynchronously, - // do print log and return false - if (globalSession.hasBranch() && !globalSession.canBeCommittedAsync()) { - LOGGER.info("Committing global transaction is NOT done, xid = {}.", globalSession.getXid()); - return false; - } - } - // if it succeeds and there is no branch, retrying=true is the asynchronous state - // when retrying. EndCommitted is - // executed to improve concurrency performance, and the global transaction ends.. - if (success && globalSession.getBranchSessions().isEmpty()) { - SessionHelper.endCommitted(globalSession, retrying); - LOGGER.info("Committing global transaction is successfully done, xid = {}.", globalSession.getXid()); - } - return success; - } - - @Override - public GlobalStatus rollback(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - if (globalSession == null) { - return GlobalStatus.Finished; - } - // just lock changeStatus - boolean shouldRollBack = SessionHolder.lockAndExecute(globalSession, () -> { - globalSession.close(); // Highlight: Firstly, close the session, then no more - // branch can be registered. - if (globalSession.getStatus() == GlobalStatus.Begin) { - globalSession.changeGlobalStatus(GlobalStatus.Rollbacking); - return true; - } - return false; - }); - if (!shouldRollBack) { - return globalSession.getStatus(); - } - - boolean rollbackSuccess = doGlobalRollback(globalSession, false); - return rollbackSuccess ? GlobalStatus.Rollbacked : globalSession.getStatus(); - } - - @Override - public boolean doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException { - boolean success = true; - // start rollback event - MetricsPublisher.postSessionDoingEvent(globalSession, retrying); - - if (globalSession.isSaga()) { - success = getCore(BranchType.SAGA).doGlobalRollback(globalSession, retrying); - } - else { - List branchSessions = globalSession.getSortedBranches(); - Boolean result = SessionHelper.forEach(branchSessions, branchSession -> { - BranchStatus currentBranchStatus = branchSession.getStatus(); - if (currentBranchStatus == BranchStatus.PhaseOne_Failed) { - SessionHelper.removeBranch(globalSession, branchSession, !retrying); - return CONTINUE; - } - try { - BranchStatus branchStatus = branchRollback(globalSession, branchSession); - if (isXaerNotaTimeout(globalSession, branchStatus)) { - LOGGER.info("Rollback branch XAER_NOTA retry timeout, xid = {} branchId = {}", - globalSession.getXid(), branchSession.getBranchId()); - branchStatus = BranchStatus.PhaseTwo_Rollbacked; - } - switch (branchStatus) { - case PhaseTwo_Rollbacked: - SessionHelper.removeBranch(globalSession, branchSession, !retrying); - LOGGER.info("Rollback branch transaction successfully, xid = {} branchId = {}", - globalSession.getXid(), branchSession.getBranchId()); - return CONTINUE; - case PhaseTwo_RollbackFailed_Unretryable: - SessionHelper.endRollbackFailed(globalSession, retrying); - LOGGER.error("Rollback branch transaction fail and stop retry, xid = {} branchId = {}", - globalSession.getXid(), branchSession.getBranchId()); - return false; - default: - LOGGER.error("Rollback branch transaction fail and will retry, xid = {} branchId = {}", - globalSession.getXid(), branchSession.getBranchId()); - if (!retrying) { - globalSession.queueToRetryRollback(); - } - return false; - } - } - catch (Exception ex) { - StackTraceLogger.error(LOGGER, ex, - "Rollback branch transaction exception, xid = {} ,branchId = {} ,retrying={} ,exception = {}, global rollback failed", - new String[] { globalSession.getXid(), String.valueOf(branchSession.getBranchId()), - String.valueOf(retrying), ex.getMessage() }); - if (!retrying) { - globalSession.queueToRetryRollback(); - } - throw new TransactionException(ex); - } - }, PARALLEL_HANDLE_BRANCH && branchSessions.size() >= 2); - // Return if the result is not null - if (result != null) { - return result; - } - } - - // In db mode, lock and branch data residual problems may occur. - // Therefore, execution needs to be delayed here and cannot be executed - // synchronously. - if (success) { - SessionHelper.endRollbacked(globalSession, retrying); - LOGGER.info("Rollback global transaction successfully, xid = {}.", globalSession.getXid()); - } - return success; - } - - @Override - public GlobalStatus getStatus(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid, false); - if (globalSession == null) { - return GlobalStatus.Finished; - } - else { - return globalSession.getStatus(); - } - } - - @Override - public GlobalStatus globalReport(String xid, GlobalStatus globalStatus) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - if (globalSession == null) { - return globalStatus; - } - doGlobalReport(globalSession, xid, globalStatus); - return globalSession.getStatus(); - } - - @Override - public void doGlobalReport(GlobalSession globalSession, String xid, GlobalStatus globalStatus) - throws TransactionException { - if (globalSession.isSaga()) { - getCore(BranchType.SAGA).doGlobalReport(globalSession, xid, globalStatus); - } - } - - private boolean isXaerNotaTimeout(GlobalSession globalSession, BranchStatus branchStatus) { - if (BranchStatus.PhaseTwo_CommitFailed_XAER_NOTA_Retryable.equals(branchStatus) - || BranchStatus.PhaseTwo_RollbackFailed_XAER_NOTA_Retryable.equals(branchStatus)) { - return System.currentTimeMillis() > globalSession.getBeginTime() + globalSession.getTimeout() - + Math.max(RETRY_XAER_NOTA_TIMEOUT, globalSession.getTimeout()); - } - else { - return false; - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/RaftCoordinator.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/RaftCoordinator.java deleted file mode 100644 index 7205c037cc..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/RaftCoordinator.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.protocol.transaction.AbstractTransactionRequest; -import io.seata.core.protocol.transaction.AbstractTransactionResponse; -import io.seata.core.rpc.RemotingServer; -import io.seata.server.cluster.listener.ClusterChangeEvent; -import io.seata.server.cluster.raft.context.SeataClusterContext; -import io.seata.server.store.StoreConfig; -import org.springframework.context.ApplicationListener; - -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; - -/** - * The type raft tx coordinator. - * - * @author funkye - */ -public class RaftCoordinator extends DefaultCoordinator implements ApplicationListener { - - protected static final Map GROUP_PREVENT = new ConcurrentHashMap<>(); - - public RaftCoordinator(RemotingServer remotingServer) { - super(remotingServer); - } - - @Override - public void exceptionHandleTemplate( - Callback callback, T request, S response) { - String group = SeataClusterContext.bindGroup(); - try { - if (!isPass(group)) { - throw new TransactionException(TransactionExceptionCode.NotRaftLeader, - " The current TC is not a leader node, interrupt processing !"); - } - super.exceptionHandleTemplate(callback, request, response); - } - catch (TransactionException tex) { - LOGGER.error("Catch TransactionException while do RPC, request: {}", request, tex); - callback.onTransactionException(request, response, tex); - } - finally { - SeataClusterContext.unbindGroup(); - } - } - - private boolean isPass(String group) { - // Non-raft mode always allows requests - return Optional.ofNullable(GROUP_PREVENT.get(group)).orElse(false); - } - - public static void setPrevent(String group, boolean prevent) { - if (StoreConfig.getSessionMode() == StoreConfig.SessionMode.RAFT) { - GROUP_PREVENT.put(group, prevent); - } - } - - @Override - public void onApplicationEvent(ClusterChangeEvent event) { - setPrevent(event.getGroup(), event.isLeader()); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/TransactionCoordinatorInbound.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/TransactionCoordinatorInbound.java deleted file mode 100644 index d8c9932b10..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/TransactionCoordinatorInbound.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import io.seata.core.model.ResourceManagerOutbound; -import io.seata.core.model.TransactionManager; - -/** - * receive inbound request from RM or TM. - * - * @author zhangchenghui.dev@gmail.com - * @since 1.1.0 - */ -public interface TransactionCoordinatorInbound extends ResourceManagerOutbound, TransactionManager { - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/TransactionCoordinatorOutbound.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/TransactionCoordinatorOutbound.java deleted file mode 100644 index 042e0d955e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/coordinator/TransactionCoordinatorOutbound.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; - -/** - * send outbound request to RM. - * - * @author zhangchenghui.dev@gmail.com - * @since 1.1.0 - */ -public interface TransactionCoordinatorOutbound { - - /** - * Commit a branch transaction. - * @param globalSession the global session - * @param branchSession the branch session - * @return Status of the branch after committing. - * @throws TransactionException Any exception that fails this will be wrapped with - * TransactionException and thrown out. - */ - BranchStatus branchCommit(GlobalSession globalSession, BranchSession branchSession) throws TransactionException; - - /** - * Rollback a branch transaction. - * @param globalSession the global session - * @param branchSession the branch session - * @return Status of the branch after rollbacking. - * @throws TransactionException Any exception that fails this will be wrapped with - * TransactionException and thrown out. - */ - BranchStatus branchRollback(GlobalSession globalSession, BranchSession branchSession) throws TransactionException; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/env/ContainerHelper.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/env/ContainerHelper.java deleted file mode 100644 index 457d88e8f8..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/env/ContainerHelper.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.env; - -import io.seata.common.util.NumberUtils; -import io.seata.common.util.StringUtils; - -import static io.seata.core.constants.ConfigurationKeys.ENV_SEATA_PORT_KEY; - -/** - * @author xingfudeshi@gmail.com - * @author wang.liang - */ -public class ContainerHelper { - - private static final String C_GROUP_PATH = "/proc/1/cgroup"; - - private static final String DOCKER_PATH = "/docker"; - - private static final String KUBEPODS_PATH = "/kubepods"; - - private static final String ENV_SYSTEM_KEY = "SEATA_ENV"; - - private static final String ENV_SEATA_IP_KEY = "SEATA_IP"; - - private static final String ENV_SERVER_NODE_KEY = "SERVER_NODE"; - - private static final String ENV_STORE_MODE_KEY = "STORE_MODE"; - - private static final String ENV_LOCK_STORE_MODE_KEY = "LOCK_STORE_MODE"; - - private static final String ENV_SESSION_STORE_MODE_KEY = "SESSION_STORE_MODE"; - - /** - * Gets env from container. - * @return the env - */ - public static String getEnv() { - return StringUtils.trimToNull(System.getenv(ENV_SYSTEM_KEY)); - } - - /** - * Gets host from container. - * @return the env - */ - public static String getHost() { - return StringUtils.trimToNull(System.getenv(ENV_SEATA_IP_KEY)); - } - - /** - * Gets port from container. - * @return the env - */ - public static int getPort() { - return NumberUtils.toInt(System.getenv(ENV_SEATA_PORT_KEY), 0); - } - - /** - * Gets server node from container. - * @return the env - */ - public static Long getServerNode() { - return NumberUtils.toLong(System.getenv(ENV_SERVER_NODE_KEY)); - } - - /** - * Gets store mode from container. - * @return the env - */ - public static String getStoreMode() { - return StringUtils.trimToNull(System.getenv(ENV_STORE_MODE_KEY)); - } - - /** - * Gets session store mode from container. - * @return the env - */ - public static String getSessionStoreMode() { - return StringUtils.trimToNull(System.getenv(ENV_SESSION_STORE_MODE_KEY)); - } - - /** - * Gets lock store mode from container. - * @return the env - */ - public static String getLockStoreMode() { - return StringUtils.trimToNull(System.getenv(ENV_LOCK_STORE_MODE_KEY)); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/env/PortHelper.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/env/PortHelper.java deleted file mode 100644 index fb774fb5de..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/env/PortHelper.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.env; - -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.MapUtil; -import io.seata.common.util.NumberUtils; -import io.seata.common.util.StringUtils; -import org.springframework.util.ResourceUtils; -import org.yaml.snakeyaml.Yaml; - -import java.io.*; -import java.util.Map; -import java.util.Properties; - -/** - * @author wang.liang - */ -public class PortHelper { - - public static int getPortFromEnvOrStartup(String[] args) { - int port = 0; - if (args != null && args.length >= 2) { - for (int i = 0; i < args.length; ++i) { - if ("-p".equalsIgnoreCase(args[i]) && i < args.length - 1) { - port = NumberUtils.toInt(args[i + 1], 0); - } - } - } - if (port == 0) { - port = ContainerHelper.getPort(); - } - return port; - } - - /** - * get config from configFile -Dspring.config.location > - * classpath:application.properties > classpath:application.yml. - * @return the port - * @throws IOException the io exception - */ - public static int getPortFromConfigFile() throws IOException { - - int port = 8080; - File configFile = null; - File startupConfigFile = getConfigFromStartup(); - if (null != startupConfigFile) { - configFile = startupConfigFile; - } - else { - try { - File propertiesFile = ResourceUtils.getFile("classpath:application.properties"); - configFile = propertiesFile; - } - catch (FileNotFoundException exx) { - File ymlFile = ResourceUtils.getFile("classpath:application.yml"); - configFile = ymlFile; - } - } - InputStream inputStream = null; - try { - inputStream = new FileInputStream(configFile); - String fileName = configFile.getName(); - String portNum = null; - if (fileName.endsWith("yml")) { - Map yamlMap = new Yaml().load(inputStream); - Map configMap = MapUtil.getFlattenedMap(yamlMap); - if (CollectionUtils.isNotEmpty(configMap)) { - Object serverPort = configMap.get("server.port"); - if (null != serverPort) { - portNum = serverPort.toString(); - } - } - } - else { - Properties properties = new Properties(); - properties.load(inputStream); - portNum = properties.getProperty("server.port"); - } - if (null != portNum) { - try { - port = Integer.parseInt(portNum); - } - catch (NumberFormatException exx) { - // ignore - } - } - } - finally { - if (null != inputStream) { - inputStream.close(); - } - } - return port; - - } - - private static File getConfigFromStartup() { - - String configLocation = System.getProperty("spring.config.location"); - if (StringUtils.isNotBlank(configLocation)) { - try { - File configFile = ResourceUtils.getFile(configLocation); - if (!configFile.isFile()) { - return null; - } - String fileName = configFile.getName(); - if (!(fileName.endsWith("yml") || fileName.endsWith("properties"))) { - return null; - } - return configFile; - } - catch (FileNotFoundException e) { - return null; - } - } - return null; - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/event/EventBusManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/event/EventBusManager.java deleted file mode 100644 index 2d1fb627b8..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/event/EventBusManager.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.event; - -import io.seata.core.event.EventBus; -import io.seata.core.event.GuavaEventBus; - -/** - * Manager hold the singleton event bus instance. - * - * @author zhengyangyong - */ -public class EventBusManager { - - public static EventBus get() { - return SingletonHolder.INSTANCE; - } - - private static class SingletonHolder { - - private static final EventBus INSTANCE = new GuavaEventBus("tc", true); - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/AbstractLockManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/AbstractLockManager.java deleted file mode 100644 index 7bfaafd2ad..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/AbstractLockManager.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -import io.seata.common.XID; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.core.exception.TransactionException; -import io.seata.core.lock.Locker; -import io.seata.core.lock.RowLock; -import io.seata.core.model.LockStatus; -import io.seata.server.session.BranchSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * The type Abstract lock manager. - * - * @author zhangsen - */ -public abstract class AbstractLockManager implements LockManager { - - /** - * The constant LOGGER. - */ - protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractLockManager.class); - - @Override - public boolean acquireLock(BranchSession branchSession) throws TransactionException { - return acquireLock(branchSession, true, false); - } - - @Override - public boolean acquireLock(BranchSession branchSession, boolean autoCommit, boolean skipCheckLock) - throws TransactionException { - if (branchSession == null) { - throw new IllegalArgumentException("branchSession can't be null for memory/file locker."); - } - String lockKey = branchSession.getLockKey(); - if (StringUtils.isNullOrEmpty(lockKey)) { - // no lock - return true; - } - // get locks of branch - List locks = collectRowLocks(branchSession); - if (CollectionUtils.isEmpty(locks)) { - // no lock - return true; - } - return getLocker(branchSession).acquireLock(locks, autoCommit, skipCheckLock); - } - - @Override - public boolean releaseLock(BranchSession branchSession) throws TransactionException { - if (branchSession == null) { - throw new IllegalArgumentException("branchSession can't be null for memory/file locker."); - } - List locks = collectRowLocks(branchSession); - try { - return getLocker(branchSession).releaseLock(locks); - } - catch (Exception t) { - LOGGER.error("unLock error, branchSession:{}", branchSession, t); - return false; - } - } - - @Override - public boolean isLockable(String xid, String resourceId, String lockKey) throws TransactionException { - if (StringUtils.isBlank(lockKey)) { - // no lock - return true; - } - List locks = collectRowLocks(lockKey, resourceId, xid); - try { - return getLocker().isLockable(locks); - } - catch (Exception t) { - LOGGER.error("isLockable error, xid:{} resourceId:{}, lockKey:{}", xid, resourceId, lockKey, t); - return false; - } - } - - @Override - public void cleanAllLocks() throws TransactionException { - getLocker().cleanAllLocks(); - } - - /** - * Gets locker. - * @return the locker - */ - protected Locker getLocker() { - return getLocker(null); - } - - /** - * Gets locker. - * @param branchSession the branch session - * @return the locker - */ - protected abstract Locker getLocker(BranchSession branchSession); - - @Override - public List collectRowLocks(BranchSession branchSession) { - if (branchSession == null || StringUtils.isBlank(branchSession.getLockKey())) { - return Collections.emptyList(); - } - - String lockKey = branchSession.getLockKey(); - String resourceId = branchSession.getResourceId(); - String xid = branchSession.getXid(); - long transactionId = branchSession.getTransactionId(); - long branchId = branchSession.getBranchId(); - - return collectRowLocks(lockKey, resourceId, xid, transactionId, branchId); - } - - /** - * Collect row locks list. - * @param lockKey the lock key - * @param resourceId the resource id - * @param xid the xid - * @return the list - */ - protected List collectRowLocks(String lockKey, String resourceId, String xid) { - return collectRowLocks(lockKey, resourceId, xid, XID.getTransactionId(xid), null); - } - - /** - * Collect row locks list. - * @param lockKey the lock key - * @param resourceId the resource id - * @param xid the xid - * @param transactionId the transaction id - * @param branchID the branch id - * @return the list - */ - protected List collectRowLocks(String lockKey, String resourceId, String xid, Long transactionId, - Long branchID) { - List locks = new ArrayList<>(); - - String[] tableGroupedLockKeys = lockKey.split(";"); - for (String tableGroupedLockKey : tableGroupedLockKeys) { - int idx = tableGroupedLockKey.indexOf(':'); - if (idx < 0) { - return locks; - } - String tableName = tableGroupedLockKey.substring(0, idx); - String mergedPKs = tableGroupedLockKey.substring(idx + 1); - if (StringUtils.isBlank(mergedPKs)) { - return locks; - } - String[] pks = mergedPKs.split(","); - if (pks.length == 0) { - return locks; - } - for (String pk : pks) { - if (StringUtils.isNotBlank(pk)) { - RowLock rowLock = new RowLock(); - rowLock.setXid(xid); - rowLock.setTransactionId(transactionId); - rowLock.setBranchId(branchID); - rowLock.setTableName(tableName); - rowLock.setPk(pk); - rowLock.setResourceId(resourceId); - locks.add(rowLock); - } - } - } - return locks; - } - - @Override - public void updateLockStatus(String xid, LockStatus lockStatus) { - this.getLocker().updateLockStatus(xid, lockStatus); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/LockManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/LockManager.java deleted file mode 100644 index 86bcb3a567..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/LockManager.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -import java.util.List; - -import io.seata.core.exception.TransactionException; -import io.seata.core.lock.RowLock; -import io.seata.core.model.LockStatus; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; - -/** - * The interface Lock manager. - * - * @author sharajava - */ -public interface LockManager { - - /** - * Acquire lock boolean. - * @param branchSession the branch session - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean acquireLock(BranchSession branchSession) throws TransactionException; - - /** - * Acquire lock boolean. - * @param branchSession the branch session - * @param autoCommit the auto commit - * @param skipCheckLock whether skip check lock or not - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean acquireLock(BranchSession branchSession, boolean autoCommit, boolean skipCheckLock) - throws TransactionException; - - /** - * Un lock boolean. - * @param branchSession the branch session - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean releaseLock(BranchSession branchSession) throws TransactionException; - - /** - * Un lock boolean. - * @param globalSession the global session - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean releaseGlobalSessionLock(GlobalSession globalSession) throws TransactionException; - - /** - * Is lockable boolean. - * @param xid the xid - * @param resourceId the resource id - * @param lockKey the lock key - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean isLockable(String xid, String resourceId, String lockKey) throws TransactionException; - - /** - * Clean all locks. - * @throws TransactionException the transaction exception - */ - void cleanAllLocks() throws TransactionException; - - /** - * Collect row locks list. - * @param branchSession the branch session - * @return the list - */ - List collectRowLocks(BranchSession branchSession); - - /** - * update lock status. - * @param xid the xid - * @param lockStatus the lock status - * @throws TransactionException the transaction exception - * - */ - void updateLockStatus(String xid, LockStatus lockStatus) throws TransactionException; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/LockerManagerFactory.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/LockerManagerFactory.java deleted file mode 100644 index aaf0f6bf7f..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/LockerManagerFactory.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.server.store.StoreConfig; -import io.seata.server.store.StoreConfig.LockMode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The type Lock manager factory. - * - * @author sharajava - */ -public class LockerManagerFactory { - - private static final Logger LOGGER = LoggerFactory.getLogger(LockerManagerFactory.class); - - private static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * the lock manager. - */ - private static volatile LockManager LOCK_MANAGER; - - /** - * Get lock manager. - * @return the lock manager - */ - public static LockManager getLockManager() { - init(); - return LOCK_MANAGER; - } - - public static void init() { - init(null); - } - - public static void destroy() { - LOCK_MANAGER = null; - } - - public static void init(LockMode lockMode) { - if (LOCK_MANAGER == null) { - synchronized (LockerManagerFactory.class) { - if (LOCK_MANAGER == null) { - if (null == lockMode) { - lockMode = StoreConfig.getLockMode(); - } - LOGGER.info("use lock store mode: {}", lockMode.getName()); - // if not exist the lock mode, throw exception - if (null != StoreConfig.StoreMode.get(lockMode.name())) { - LOCK_MANAGER = EnhancedServiceLoader.load(LockManager.class, lockMode.getName()); - } - } - } - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/distributed/DistributedLockerFactory.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/distributed/DistributedLockerFactory.java deleted file mode 100644 index a9987aee05..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/lock/distributed/DistributedLockerFactory.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock.distributed; - -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.loader.EnhancedServiceNotFoundException; -import io.seata.core.store.DefaultDistributedLocker; -import io.seata.core.store.DistributedLocker; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Distributed locker factory. - * - * @author zhongxiang.wang - */ -public class DistributedLockerFactory { - - /** - * The constant LOGGER. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(DistributedLockerFactory.class); - - private static volatile DistributedLocker DISTRIBUTED_LOCKER = null; - - /** - * Get the distributed locker by lockerType. - * @param lockerType the locker type - * @return the distributed locker - */ - public static DistributedLocker getDistributedLocker(String lockerType) { - if (DISTRIBUTED_LOCKER == null) { - synchronized (DistributedLocker.class) { - if (DISTRIBUTED_LOCKER == null) { - DistributedLocker distributedLocker = null; - try { - if (!"file".equals(lockerType)) { - distributedLocker = EnhancedServiceLoader.load(DistributedLocker.class, lockerType); - } - } - catch (EnhancedServiceNotFoundException ex) { - LOGGER.error("Get distributed locker failed: {}", ex.getMessage(), ex); - } - if (distributedLocker == null) { - distributedLocker = new DefaultDistributedLocker(); - } - DISTRIBUTED_LOCKER = distributedLocker; - } - } - } - return DISTRIBUTED_LOCKER; - } - - public static void cleanLocker() { - DISTRIBUTED_LOCKER = null; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/listener/SystemPropertyLoggerContextListener.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/listener/SystemPropertyLoggerContextListener.java deleted file mode 100644 index 114ccd5d39..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/listener/SystemPropertyLoggerContextListener.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.logging.listener; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.LoggerContextListener; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.spi.LifeCycle; -import io.seata.core.constants.ConfigurationKeys; - -/** - * @author wang.liang - */ -public class SystemPropertyLoggerContextListener extends ContextAwareBase implements LoggerContextListener, LifeCycle { - - private boolean started = false; - - @Override - public void start() { - if (started) { - return; - } - - Context context = getContext(); - context.putProperty("RPC_PORT", System.getProperty(ConfigurationKeys.SERVER_SERVICE_PORT_CAMEL)); - - started = true; - } - - @Override - public void stop() { - } - - @Override - public boolean isStarted() { - return started; - } - - @Override - public boolean isResetResistant() { - return true; - } - - @Override - public void onStart(LoggerContext context) { - } - - @Override - public void onReset(LoggerContext context) { - } - - @Override - public void onStop(LoggerContext context) { - } - - @Override - public void onLevelChange(Logger logger, Level level) { - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/ExtendedWhitespaceThrowableProxyConverter.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/ExtendedWhitespaceThrowableProxyConverter.java deleted file mode 100644 index 9c79cea10b..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/ExtendedWhitespaceThrowableProxyConverter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.logging.logback; - -import ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter; -import ch.qos.logback.classic.spi.IThrowableProxy; -import ch.qos.logback.core.CoreConstants; - -/** - * {@link ExtendedThrowableProxyConverter} that adds some additional whitespace around the - * stack trace. Copied from spring-boot-xxx.jar by wang.liang - * - * @author Phillip Webb - */ -public class ExtendedWhitespaceThrowableProxyConverter extends ExtendedThrowableProxyConverter { - - @Override - protected String throwableProxyToString(IThrowableProxy tp) { - return "==>" + CoreConstants.LINE_SEPARATOR + super.throwableProxyToString(tp) + "<==" - + CoreConstants.LINE_SEPARATOR + CoreConstants.LINE_SEPARATOR; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/appender/EnhancedLogstashEncoder.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/appender/EnhancedLogstashEncoder.java deleted file mode 100644 index 04c611df99..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/appender/EnhancedLogstashEncoder.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.logging.logback.appender; - -import net.logstash.logback.composite.JsonProvider; -import net.logstash.logback.composite.JsonProviders; -import net.logstash.logback.encoder.LogstashEncoder; - -import java.util.ArrayList; - -/** - * The type Enhanced logstash encoder. - * - * @author wang.liang - * @since 1.5.0 - */ -public class EnhancedLogstashEncoder extends LogstashEncoder { - - /** - * set exclude provider. - * @param excludedProviderClassName the excluded provider class name - */ - public void setExcludeProvider(String excludedProviderClassName) { - JsonProviders providers = getFormatter().getProviders(); - for (JsonProvider provider : new ArrayList<>(providers.getProviders())) { - if (provider.getClass().getName().equals(excludedProviderClassName)) { - providers.removeProvider((JsonProvider) provider); - } - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/appender/MetricLogbackAppender.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/appender/MetricLogbackAppender.java deleted file mode 100644 index 5f3e188ef2..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/logging/logback/appender/MetricLogbackAppender.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.logging.logback.appender; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.ThrowableProxy; -import ch.qos.logback.core.AppenderBase; -import ch.qos.logback.core.LogbackException; -import io.seata.core.event.EventBus; -import io.seata.core.event.ExceptionEvent; -import io.seata.server.event.EventBusManager; - -/** - * The type metric logback appender. - * - * @author Bughue - */ -public class MetricLogbackAppender extends AppenderBase { - - private EventBus eventBus = EventBusManager.get(); - - @Override - protected void append(ILoggingEvent event) { - try { - Level level = event.getLevel(); - - if (level.isGreaterOrEqual(Level.ERROR)) { - ThrowableProxy info = (ThrowableProxy) event.getThrowableProxy(); - - if (info != null) { - Throwable throwable = info.getThrowable(); - eventBus.post(new ExceptionEvent(throwable.getClass().getName())); - } - } - } - catch (Exception ex) { - throw new LogbackException(event.getFormattedMessage(), ex); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MeterIdConstants.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MeterIdConstants.java deleted file mode 100644 index 813fc699f0..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MeterIdConstants.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.metrics; - -import io.seata.metrics.IdConstants; -import io.seata.metrics.Id; - -/** - * Constants for meter id in tc. - * - * @author zhengyangyong - */ -public interface MeterIdConstants { - - /** - * 活跃(次数). - */ - Id COUNTER_ACTIVE = new Id(IdConstants.SEATA_TRANSACTION).withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_COUNTER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_ACTIVE); - - /** - * 提交(次数). - */ - Id COUNTER_COMMITTED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_COUNTER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_COMMITTED); - - /** - * 回滚(次数). - */ - Id COUNTER_ROLLBACKED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_COUNTER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_ROLLBACKED); - - /** - * 修改回滚(次数). - */ - Id COUNTER_AFTER_ROLLBACKED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_COUNTER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_AFTER_ROLLBACKED_KEY); - - /** - * 修改提交(次数). - */ - Id COUNTER_AFTER_COMMITTED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_COUNTER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_AFTER_COMMITTED_KEY); - - /** - * 整体提交. - */ - Id SUMMARY_COMMITTED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_SUMMARY) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_COMMITTED); - - /** - * 整体回滚. - */ - Id SUMMARY_ROLLBACKED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_SUMMARY) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_ROLLBACKED); - - /** - * 整体失败. - */ - Id SUMMARY_FAILED = new Id(IdConstants.SEATA_TRANSACTION).withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_SUMMARY) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_FAILED); - - /** - * 两次提交超时. - */ - Id SUMMARY_TWO_PHASE_TIMEOUT = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_SUMMARY) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_TWO_PHASE_TIMEOUT); - - /** - * 整体修改回滚. - */ - Id SUMMARY_AFTER_ROLLBACKED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_SUMMARY) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_AFTER_ROLLBACKED_KEY); - - /** - * 整体修改提交. - */ - Id SUMMARY_AFTER_COMMITTED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_SUMMARY) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_AFTER_COMMITTED_KEY); - - /** - * 提交. - */ - Id TIMER_COMMITTED = new Id(IdConstants.SEATA_TRANSACTION).withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_TIMER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_COMMITTED); - - /** - * 回滚. - */ - Id TIMER_ROLLBACK = new Id(IdConstants.SEATA_TRANSACTION).withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_TIMER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_ROLLBACKED); - - /** - * 失败. - */ - Id TIMER_FAILED = new Id(IdConstants.SEATA_TRANSACTION).withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_TIMER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_FAILED); - - /** - * 修改回滚. - */ - Id TIMER_AFTER_ROLLBACKED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_TIMER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_AFTER_ROLLBACKED_KEY); - - /** - * 修改提交. - */ - Id TIMER_AFTER_COMMITTED = new Id(IdConstants.SEATA_TRANSACTION) - .withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_TIMER) - .withTag(IdConstants.STATUS_KEY, IdConstants.STATUS_VALUE_AFTER_COMMITTED_KEY); - - /** - * 整体异常. - */ - Id SUMMARY_EXP = new Id(IdConstants.SEATA_EXCEPTION).withTag(IdConstants.ROLE_KEY, IdConstants.ROLE_VALUE_TC) - .withTag(IdConstants.METER_KEY, IdConstants.METER_VALUE_SUMMARY); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsManager.java deleted file mode 100644 index ad94d9088e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsManager.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.metrics; - -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.metrics.exporter.Exporter; -import io.seata.metrics.exporter.ExporterFactory; -import io.seata.metrics.registry.Registry; -import io.seata.metrics.registry.RegistryFactory; -import io.seata.server.event.EventBusManager; - -import java.util.List; - -import static io.seata.common.DefaultValues.DEFAULT_METRICS_ENABLED; - -/** - * Metrics manager for init. - * - * @author zhengyangyong - */ -public class MetricsManager { - - private Registry registry; - - public static MetricsManager get() { - return MetricsManager.SingletonHolder.INSTANCE; - } - - public Registry getRegistry() { - return registry; - } - - public void init() { - boolean enabled = ConfigurationFactory.getInstance() - .getBoolean(ConfigurationKeys.METRICS_PREFIX + ConfigurationKeys.METRICS_ENABLED, DEFAULT_METRICS_ENABLED); - if (enabled) { - registry = RegistryFactory.getInstance(); - if (registry != null) { - List exporters = ExporterFactory.getInstanceList(); - // only at least one metrics exporter implement had imported in pom then - // need register MetricsSubscriber - if (exporters.size() != 0) { - exporters.forEach(exporter -> exporter.setRegistry(registry)); - EventBusManager.get().register(new MetricsSubscriber(registry)); - } - } - } - } - - private static class SingletonHolder { - - private static final MetricsManager INSTANCE = new MetricsManager(); - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsPublisher.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsPublisher.java deleted file mode 100644 index 54148826aa..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsPublisher.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.metrics; - -import io.seata.core.event.EventBus; -import io.seata.core.event.GlobalTransactionEvent; -import io.seata.core.model.GlobalStatus; -import io.seata.server.event.EventBusManager; -import io.seata.server.session.GlobalSession; - -/** - * The type Metrics publisher. - * - * @author slievrly - */ -public class MetricsPublisher { - - private static final EventBus EVENT_BUS = EventBusManager.get(); - - /** - * post end event. - * @param globalSession the global session - * @param retryGlobal the retry global - * @param retryBranch the retry branch - */ - public static void postSessionDoneEvent(final GlobalSession globalSession, boolean retryGlobal, - boolean retryBranch) { - postSessionDoneEvent(globalSession, globalSession.getStatus(), retryGlobal, retryBranch); - } - - /** - * post end event (force specified state). - * @param globalSession the global session - * @param status the global status - * @param retryGlobal the retry global - * @param retryBranch the retry branch - */ - public static void postSessionDoneEvent(final GlobalSession globalSession, GlobalStatus status, boolean retryGlobal, - boolean retryBranch) { - postSessionDoneEvent(globalSession, status.name(), retryGlobal, globalSession.getBeginTime(), retryBranch); - } - - /** - * Post session done event. - * @param globalSession the global session - * @param status the status - * @param retryGlobal the retry global - * @param beginTime the begin time - * @param retryBranch the retry branch - */ - public static void postSessionDoneEvent(final GlobalSession globalSession, String status, boolean retryGlobal, - long beginTime, boolean retryBranch) { - EVENT_BUS.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, - globalSession.getTransactionName(), globalSession.getApplicationId(), - globalSession.getTransactionServiceGroup(), beginTime, System.currentTimeMillis(), status, retryGlobal, - retryBranch)); - } - - /** - * Post session doing event. - * @param globalSession the global session - * @param retryGlobal the retry global - */ - public static void postSessionDoingEvent(final GlobalSession globalSession, boolean retryGlobal) { - postSessionDoingEvent(globalSession, globalSession.getStatus().name(), retryGlobal, false); - } - - /** - * Post session doing event. - * @param globalSession the global session - * @param status the status - * @param retryGlobal the retry global - * @param retryBranch the retry branch - */ - public static void postSessionDoingEvent(final GlobalSession globalSession, String status, boolean retryGlobal, - boolean retryBranch) { - EVENT_BUS.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, - globalSession.getTransactionName(), globalSession.getApplicationId(), - globalSession.getTransactionServiceGroup(), globalSession.getBeginTime(), null, status, retryGlobal, - retryBranch)); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsSubscriber.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsSubscriber.java deleted file mode 100644 index f34d3aa738..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/metrics/MetricsSubscriber.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.metrics; - -import com.google.common.eventbus.Subscribe; -import io.seata.core.event.ExceptionEvent; -import io.seata.core.event.GlobalTransactionEvent; -import io.seata.core.model.GlobalStatus; -import io.seata.metrics.registry.Registry; -import io.seata.server.event.EventBusManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -import static io.seata.metrics.IdConstants.*; - -/** - * Event subscriber for metrics. - * - * @author zhengyangyong - */ -public class MetricsSubscriber { - - private static final Logger LOGGER = LoggerFactory.getLogger(MetricsSubscriber.class); - - private final Registry registry; - - private final Map> consumers; - - public MetricsSubscriber(Registry registry) { - this.registry = registry; - consumers = new HashMap<>(); - consumers.put(GlobalStatus.Begin.name(), this::processGlobalStatusBegin); - consumers.put(GlobalStatus.Committed.name(), this::processGlobalStatusCommitted); - consumers.put(GlobalStatus.Rollbacked.name(), this::processGlobalStatusRollbacked); - - consumers.put(GlobalStatus.CommitFailed.name(), this::processGlobalStatusCommitFailed); - consumers.put(GlobalStatus.RollbackFailed.name(), this::processGlobalStatusRollbackFailed); - consumers.put(GlobalStatus.TimeoutRollbacked.name(), this::processGlobalStatusTimeoutRollbacked); - consumers.put(GlobalStatus.TimeoutRollbackFailed.name(), this::processGlobalStatusTimeoutRollbackFailed); - - consumers.put(GlobalStatus.CommitRetryTimeout.name(), this::processGlobalStatusCommitRetryTimeout); - consumers.put(GlobalStatus.RollbackRetryTimeout.name(), this::processGlobalStatusTimeoutRollbackRetryTimeout); - - consumers.put(STATUS_VALUE_AFTER_COMMITTED_KEY, this::processAfterGlobalCommitted); - consumers.put(STATUS_VALUE_AFTER_ROLLBACKED_KEY, this::processAfterGlobalRollbacked); - } - - private void processGlobalStatusBegin(GlobalTransactionEvent event) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("accept new event,xid:{},event:{}", event.getId(), event); - for (Object object : EventBusManager.get().getSubscribers()) { - LOGGER.debug("subscribe:{},threadName:{}", object.toString(), Thread.currentThread().getName()); - } - } - registry - .getCounter(MeterIdConstants.COUNTER_ACTIVE.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - } - - private void processGlobalStatusCommitted(GlobalTransactionEvent event) { - if (event.isRetryGlobal()) { - return; - } - decreaseActive(event); - registry - .getCounter(MeterIdConstants.COUNTER_COMMITTED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - registry - .getSummary(MeterIdConstants.SUMMARY_COMMITTED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - registry - .getTimer(MeterIdConstants.TIMER_COMMITTED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .record(event.getEndTime() - event.getBeginTime(), TimeUnit.MILLISECONDS); - } - - private void processGlobalStatusRollbacked(GlobalTransactionEvent event) { - if (event.isRetryGlobal()) { - return; - } - decreaseActive(event); - registry - .getCounter(MeterIdConstants.COUNTER_ROLLBACKED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - registry - .getSummary(MeterIdConstants.SUMMARY_ROLLBACKED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - registry - .getTimer(MeterIdConstants.TIMER_ROLLBACK.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .record(event.getEndTime() - event.getBeginTime(), TimeUnit.MILLISECONDS); - } - - private void processAfterGlobalRollbacked(GlobalTransactionEvent event) { - if (event.isRetryGlobal() && event.isRetryBranch()) { - decreaseActive(event); - } - registry - .getCounter(MeterIdConstants.COUNTER_AFTER_ROLLBACKED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - registry - .getSummary(MeterIdConstants.SUMMARY_AFTER_ROLLBACKED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - registry - .getTimer(MeterIdConstants.TIMER_AFTER_ROLLBACKED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .record(event.getEndTime() - event.getBeginTime(), TimeUnit.MILLISECONDS); - } - - private void processAfterGlobalCommitted(GlobalTransactionEvent event) { - if (event.isRetryGlobal() && event.isRetryBranch()) { - decreaseActive(event); - } - registry - .getCounter(MeterIdConstants.COUNTER_AFTER_COMMITTED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - registry - .getSummary(MeterIdConstants.SUMMARY_AFTER_COMMITTED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - registry - .getTimer(MeterIdConstants.TIMER_AFTER_COMMITTED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .record(event.getEndTime() - event.getBeginTime(), TimeUnit.MILLISECONDS); - } - - private void processGlobalStatusCommitFailed(GlobalTransactionEvent event) { - decreaseActive(event); - reportFailed(event); - } - - private void processGlobalStatusRollbackFailed(GlobalTransactionEvent event) { - decreaseActive(event); - reportFailed(event); - } - - private void processGlobalStatusTimeoutRollbacked(GlobalTransactionEvent event) { - decreaseActive(event); - } - - private void processGlobalStatusTimeoutRollbackFailed(GlobalTransactionEvent event) { - decreaseActive(event); - reportTwoPhaseTimeout(event); - } - - private void processGlobalStatusCommitRetryTimeout(GlobalTransactionEvent event) { - decreaseActive(event); - reportTwoPhaseTimeout(event); - } - - private void processGlobalStatusTimeoutRollbackRetryTimeout(GlobalTransactionEvent event) { - decreaseActive(event); - } - - private void decreaseActive(GlobalTransactionEvent event) { - registry - .getCounter(MeterIdConstants.COUNTER_ACTIVE.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .decrease(1); - } - - private void reportFailed(GlobalTransactionEvent event) { - registry - .getSummary(MeterIdConstants.SUMMARY_FAILED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - registry - .getTimer(MeterIdConstants.TIMER_FAILED.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .record(event.getEndTime() - event.getBeginTime(), TimeUnit.MILLISECONDS); - } - - private void reportTwoPhaseTimeout(GlobalTransactionEvent event) { - registry - .getSummary(MeterIdConstants.SUMMARY_TWO_PHASE_TIMEOUT.withTag(APP_ID_KEY, event.getApplicationId()) - .withTag(GROUP_KEY, event.getGroup())) - .increase(1); - } - - @Subscribe - public void recordGlobalTransactionEventForMetrics(GlobalTransactionEvent event) { - if (registry != null && consumers.containsKey(event.getStatus())) { - consumers.get(event.getStatus()).accept(event); - } - } - - @Subscribe - public void exceptionEventForMetrics(ExceptionEvent event) { - registry.getSummary(MeterIdConstants.SUMMARY_EXP.withTag(APP_ID_KEY, event.getName())).increase(1); - } - - @Override - public boolean equals(Object obj) { - return this.getClass().getName().equals(obj.getClass().getName()); - } - - /** - * PMD check SuppressWarnings("checkstyle:EqualsHashCode"). - * @return the hash code - */ - @Override - public int hashCode() { - return super.hashCode(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/AbstractSessionManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/AbstractSessionManager.java deleted file mode 100644 index 4b1563ab2d..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/AbstractSessionManager.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.BranchTransactionException; -import io.seata.core.exception.GlobalTransactionException; -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; -import io.seata.core.model.LockStatus; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager; -import io.seata.server.store.TransactionStoreManager.LogOperation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The type Abstract session manager. - */ -public abstract class AbstractSessionManager implements SessionManager { - - /** - * The constant LOGGER. - */ - protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractSessionManager.class); - - /** - * The Transaction store manager. - */ - protected TransactionStoreManager transactionStoreManager; - - /** - * The Name. - */ - protected String name; - - /** - * Instantiates a new Abstract session manager. - */ - public AbstractSessionManager() { - } - - /** - * Instantiates a new Abstract session manager. - * @param name the name - */ - public AbstractSessionManager(String name) { - this.name = name; - } - - @Override - public void addGlobalSession(GlobalSession session) throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[{}] SESSION[{}] {}", name, session, LogOperation.GLOBAL_ADD); - } - writeSession(LogOperation.GLOBAL_ADD, session); - } - - @Override - public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[{}] SESSION[{}] {}", name, session, LogOperation.GLOBAL_UPDATE); - } - if (GlobalStatus.Rollbacking == status || GlobalStatus.TimeoutRollbacking == status) { - session.getBranchSessions().forEach(i -> i.setLockStatus(LockStatus.Rollbacking)); - } - session.setStatus(status); - writeSession(LogOperation.GLOBAL_UPDATE, session); - } - - @Override - public void removeGlobalSession(GlobalSession session) throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[{}] SESSION[{}] {}", name, session, LogOperation.GLOBAL_REMOVE); - } - writeSession(LogOperation.GLOBAL_REMOVE, session); - } - - @Override - public void addBranchSession(GlobalSession session, BranchSession branchSession) throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[{}] SESSION[{}] {}", name, branchSession, LogOperation.BRANCH_ADD); - } - writeSession(LogOperation.BRANCH_ADD, branchSession); - } - - @Override - public void updateBranchSessionStatus(BranchSession branchSession, BranchStatus status) - throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[{}] SESSION[{}] {}", name, branchSession, LogOperation.BRANCH_UPDATE); - } - writeSession(LogOperation.BRANCH_UPDATE, branchSession); - } - - @Override - public void removeBranchSession(GlobalSession globalSession, BranchSession branchSession) - throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[{}] SESSION[{}] {}", name, branchSession, LogOperation.BRANCH_REMOVE); - } - writeSession(LogOperation.BRANCH_REMOVE, branchSession); - } - - @Override - public void onBegin(GlobalSession globalSession) throws TransactionException { - addGlobalSession(globalSession); - } - - @Override - public void onStatusChange(GlobalSession globalSession, GlobalStatus status) throws TransactionException { - updateGlobalSessionStatus(globalSession, status); - } - - @Override - public void onBranchStatusChange(GlobalSession globalSession, BranchSession branchSession, BranchStatus status) - throws TransactionException { - branchSession.setStatus(status); - updateBranchSessionStatus(branchSession, status); - } - - @Override - public void onAddBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException { - addBranchSession(globalSession, branchSession); - } - - @Override - public void onRemoveBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException { - removeBranchSession(globalSession, branchSession); - } - - @Override - public void onClose(GlobalSession globalSession) throws TransactionException { - globalSession.setActive(false); - } - - @Override - public void onSuccessEnd(GlobalSession globalSession) throws TransactionException { - removeGlobalSession(globalSession); - } - - @Override - public void onFailEnd(GlobalSession globalSession) throws TransactionException { - LOGGER.info("xid:{} fail end, transaction:{}", globalSession.getXid(), globalSession); - } - - private void writeSession(LogOperation logOperation, SessionStorable sessionStorable) throws TransactionException { - if (!transactionStoreManager.writeSession(logOperation, sessionStorable)) { - if (LogOperation.GLOBAL_ADD.equals(logOperation)) { - throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession, - "Fail to store global session"); - } - else if (LogOperation.GLOBAL_UPDATE.equals(logOperation)) { - throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession, - "Fail to update global session"); - } - else if (LogOperation.GLOBAL_REMOVE.equals(logOperation)) { - throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession, - "Fail to remove global session"); - } - else if (LogOperation.BRANCH_ADD.equals(logOperation)) { - throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession, - "Fail to store branch session"); - } - else if (LogOperation.BRANCH_UPDATE.equals(logOperation)) { - throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession, - "Fail to update branch session"); - } - else if (LogOperation.BRANCH_REMOVE.equals(logOperation)) { - throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession, - "Fail to remove branch session"); - } - else { - throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession, - "Unknown LogOperation:" + logOperation.name()); - } - } - } - - @Override - public void destroy() { - } - - /** - * Sets transaction store manager. - * @param transactionStoreManager the transaction store manager - */ - public void setTransactionStoreManager(TransactionStoreManager transactionStoreManager) { - this.transactionStoreManager = transactionStoreManager; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/BranchSession.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/BranchSession.java deleted file mode 100644 index 33ad6ba936..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/BranchSession.java +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import com.alipay.sofa.jraft.util.BufferUtils; -import io.seata.common.util.CompressUtil; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.LockStatus; -import io.seata.server.lock.LockManager; -import io.seata.server.lock.LockerManagerFactory; -import io.seata.server.storage.file.lock.FileLocker; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.StoreConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import static io.seata.core.model.LockStatus.Locked; - -/** - * The type Branch session. - * - * @author sharajava - */ -public class BranchSession implements Lockable, Comparable, SessionStorable { - - private static final Logger LOGGER = LoggerFactory.getLogger(BranchSession.class); - - private static final int MAX_BRANCH_SESSION_SIZE = StoreConfig.getMaxBranchSessionSize(); - - private static ThreadLocal byteBufferThreadLocal = ThreadLocal - .withInitial(() -> ByteBuffer.allocate(MAX_BRANCH_SESSION_SIZE)); - - private String xid; - - private long transactionId; - - private long branchId; - - private String resourceGroupId; - - private String resourceId; - - private String lockKey; - - private BranchType branchType; - - private BranchStatus status = BranchStatus.Unknown; - - private String clientId; - - private String applicationData; - - private LockStatus lockStatus = Locked; - - private final Map> lockHolder; - - private final LockManager lockManager = LockerManagerFactory.getLockManager(); - - public BranchSession() { - lockHolder = new ConcurrentHashMap<>(2); - } - - public BranchSession(BranchType branchType) { - this.branchType = branchType; - this.lockHolder = branchType == BranchType.AT ? new ConcurrentHashMap<>(8) : Collections.emptyMap(); - } - - /** - * Gets application data. - * @return the application data - */ - public String getApplicationData() { - return applicationData; - } - - /** - * Sets application data. - * @param applicationData the application data - */ - public void setApplicationData(String applicationData) { - this.applicationData = applicationData; - } - - /** - * Gets resource group id. - * @return the resource group id - */ - public String getResourceGroupId() { - return resourceGroupId; - } - - /** - * Sets resource group id. - * @param resourceGroupId the resource group id - */ - public void setResourceGroupId(String resourceGroupId) { - this.resourceGroupId = resourceGroupId; - } - - /** - * Gets client id. - * @return the client id - */ - public String getClientId() { - return clientId; - } - - /** - * Sets client id. - * @param clientId the client id - */ - public void setClientId(String clientId) { - this.clientId = clientId; - } - - /** - * Gets resource id. - * @return the resource id - */ - public String getResourceId() { - return resourceId; - } - - /** - * Sets resource id. - * @param resourceId the resource id - */ - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - /** - * Gets lock key. - * @return the lock key - */ - public String getLockKey() { - return lockKey; - } - - /** - * Sets lock key. - * @param lockKey the lock key - */ - public void setLockKey(String lockKey) { - this.lockKey = lockKey; - } - - /** - * Gets branch type. - * @return the branch type - */ - public BranchType getBranchType() { - return branchType; - } - - /** - * Sets branch type. - * @param branchType the branch type - */ - public void setBranchType(BranchType branchType) { - this.branchType = branchType; - } - - /** - * Gets status. - * @return the status - */ - public BranchStatus getStatus() { - return status; - } - - /** - * Sets status. - * @param status the status - */ - public void setStatus(BranchStatus status) { - this.status = status; - } - - /** - * Gets transaction id. - * @return the transaction id - */ - public long getTransactionId() { - return transactionId; - } - - /** - * Sets transaction id. - * @param transactionId the transaction id - */ - public void setTransactionId(long transactionId) { - this.transactionId = transactionId; - } - - /** - * Gets branch id. - * @return the branch id - */ - public long getBranchId() { - return branchId; - } - - /** - * Sets branch id. - * @param branchId the branch id - */ - public void setBranchId(long branchId) { - this.branchId = branchId; - } - - /** - * Gets xid. - * @return the xid - */ - public String getXid() { - return xid; - } - - /** - * Sets xid. - * @param xid the xid - */ - public void setXid(String xid) { - this.xid = xid; - } - - @Override - public String toString() { - return "BR:" + branchId + "/" + transactionId; - } - - @Override - public int compareTo(BranchSession o) { - return Long.compare(this.branchId, o.branchId); - } - - public boolean canBeCommittedAsync() { - return branchType == BranchType.AT || status == BranchStatus.PhaseOne_Failed; - } - - /** - * Gets lock holder. - * @return the lock holder - */ - public Map> getLockHolder() { - return lockHolder; - } - - @Override - public boolean lock() throws TransactionException { - return this.lock(true, false); - } - - public boolean lock(boolean autoCommit, boolean skipCheckLock) throws TransactionException { - if (this.branchType.equals(BranchType.AT)) { - return lockManager.acquireLock(this, autoCommit, skipCheckLock); - } - return true; - } - - @Override - public boolean unlock() throws TransactionException { - if (this.branchType == BranchType.AT) { - return lockManager.releaseLock(this); - } - return true; - } - - public boolean isAT() { - return this.getBranchType() == BranchType.AT; - } - - public LockStatus getLockStatus() { - return lockStatus; - } - - public void setLockStatus(LockStatus lockStatus) { - this.lockStatus = lockStatus; - } - - @Override - public byte[] encode() { - - byte[] resourceIdBytes = resourceId != null ? resourceId.getBytes() : null; - - byte[] lockKeyBytes = lockKey != null ? lockKey.getBytes() : null; - - byte[] clientIdBytes = clientId != null ? clientId.getBytes() : null; - - byte[] applicationDataBytes = applicationData != null ? applicationData.getBytes() : null; - - byte[] xidBytes = xid != null ? xid.getBytes() : null; - - byte branchTypeByte = branchType != null ? (byte) branchType.ordinal() : -1; - - int size = calBranchSessionSize(resourceIdBytes, lockKeyBytes, clientIdBytes, applicationDataBytes, xidBytes); - - if (size > MAX_BRANCH_SESSION_SIZE) { - if (lockKeyBytes == null) { - throw new RuntimeException("branch session size exceeded, size : " + size + " maxBranchSessionSize : " - + MAX_BRANCH_SESSION_SIZE); - } - // try compress lockkey - try { - size -= lockKeyBytes.length; - lockKeyBytes = CompressUtil.compress(lockKeyBytes); - } - catch (IOException e) { - LOGGER.error("compress lockKey error", e); - } - finally { - size += lockKeyBytes.length; - } - - if (size > MAX_BRANCH_SESSION_SIZE) { - throw new RuntimeException("compress branch session size exceeded, compressSize : " + size - + " maxBranchSessionSize : " + MAX_BRANCH_SESSION_SIZE); - } - } - - ByteBuffer byteBuffer = byteBufferThreadLocal.get(); - // recycle - byteBuffer.clear(); - - byteBuffer.putLong(transactionId); - byteBuffer.putLong(branchId); - - if (resourceIdBytes != null) { - byteBuffer.putInt(resourceIdBytes.length); - byteBuffer.put(resourceIdBytes); - } - else { - byteBuffer.putInt(0); - } - - if (lockKeyBytes != null) { - byteBuffer.putInt(lockKeyBytes.length); - byteBuffer.put(lockKeyBytes); - } - else { - byteBuffer.putInt(0); - } - - if (clientIdBytes != null) { - byteBuffer.putShort((short) clientIdBytes.length); - byteBuffer.put(clientIdBytes); - } - else { - byteBuffer.putShort((short) 0); - } - - if (applicationDataBytes != null) { - byteBuffer.putInt(applicationDataBytes.length); - byteBuffer.put(applicationDataBytes); - } - else { - byteBuffer.putInt(0); - } - - if (xidBytes != null) { - byteBuffer.putInt(xidBytes.length); - byteBuffer.put(xidBytes); - } - else { - byteBuffer.putInt(0); - } - - byteBuffer.put(branchTypeByte); - - byteBuffer.put((byte) status.getCode()); - byteBuffer.put((byte) lockStatus.getCode()); - BufferUtils.flip(byteBuffer); - byte[] result = new byte[byteBuffer.limit()]; - byteBuffer.get(result); - return result; - } - - private int calBranchSessionSize(byte[] resourceIdBytes, byte[] lockKeyBytes, byte[] clientIdBytes, - byte[] applicationDataBytes, byte[] xidBytes) { - final int size = 8 // trascationId - + 8 // branchId - + 4 // resourceIdBytes.length - + 4 // lockKeyBytes.length - + 2 // clientIdBytes.length - + 4 // applicationDataBytes.length - + 4 // xidBytes.size - + 1 // statusCode - + (resourceIdBytes == null ? 0 : resourceIdBytes.length) - + (lockKeyBytes == null ? 0 : lockKeyBytes.length) + (clientIdBytes == null ? 0 : clientIdBytes.length) - + (applicationDataBytes == null ? 0 : applicationDataBytes.length) - + (xidBytes == null ? 0 : xidBytes.length) + 1; // branchType - return size; - } - - @Override - public void decode(byte[] a) { - ByteBuffer byteBuffer = ByteBuffer.wrap(a); - this.transactionId = byteBuffer.getLong(); - this.branchId = byteBuffer.getLong(); - int resourceLen = byteBuffer.getInt(); - if (resourceLen > 0) { - byte[] byResource = new byte[resourceLen]; - byteBuffer.get(byResource); - this.resourceId = new String(byResource); - } - int lockKeyLen = byteBuffer.getInt(); - if (lockKeyLen > 0) { - byte[] byLockKey = new byte[lockKeyLen]; - byteBuffer.get(byLockKey); - if (CompressUtil.isCompressData(byLockKey)) { - try { - this.lockKey = new String(CompressUtil.uncompress(byLockKey)); - } - catch (IOException e) { - throw new RuntimeException("decompress lockKey error", e); - } - } - else { - this.lockKey = new String(byLockKey); - } - - } - short clientIdLen = byteBuffer.getShort(); - if (clientIdLen > 0) { - byte[] byClientId = new byte[clientIdLen]; - byteBuffer.get(byClientId); - this.clientId = new String(byClientId); - } - int applicationDataLen = byteBuffer.getInt(); - if (applicationDataLen > 0) { - byte[] byApplicationData = new byte[applicationDataLen]; - byteBuffer.get(byApplicationData); - this.applicationData = new String(byApplicationData); - } - int xidLen = byteBuffer.getInt(); - if (xidLen > 0) { - byte[] xidBytes = new byte[xidLen]; - byteBuffer.get(xidBytes); - this.xid = new String(xidBytes); - } - int branchTypeId = byteBuffer.get(); - if (branchTypeId >= 0) { - this.branchType = BranchType.values()[branchTypeId]; - } - this.status = BranchStatus.get(byteBuffer.get()); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/BranchSessionHandler.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/BranchSessionHandler.java deleted file mode 100644 index 0c14ff1722..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/BranchSessionHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; - -/** - * The Functional Interface Branch session handler. - * - * @author wang.liang - * @since 1.5.0 - */ -@FunctionalInterface -public interface BranchSessionHandler { - - /** - * 继续. - */ - Boolean CONTINUE = null; - - /** - * Handle branch session. - * @param branchSession the branch session - * @return the handle result - * @throws TransactionException the transaction exception - */ - Boolean handle(BranchSession branchSession) throws TransactionException; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/GlobalSession.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/GlobalSession.java deleted file mode 100644 index 776a6108ee..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/GlobalSession.java +++ /dev/null @@ -1,795 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import com.alipay.sofa.jraft.util.BufferUtils; -import io.seata.common.ConfigurationKeys; -import io.seata.common.Constants; -import io.seata.common.DefaultValues; -import io.seata.common.XID; -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.core.exception.GlobalTransactionException; -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.core.model.LockStatus; -import io.seata.server.UUIDGenerator; -import io.seata.server.cluster.raft.RaftServerFactory; -import io.seata.server.lock.LockerManagerFactory; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.StoreConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.ByteBuffer; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import static io.seata.core.model.GlobalStatus.*; - -/** - * The type Global session. - * - * @author sharajava - */ -public class GlobalSession implements SessionLifecycle, SessionStorable { - - private static final Logger LOGGER = LoggerFactory.getLogger(GlobalSession.class); - - private static final int MAX_GLOBAL_SESSION_SIZE = StoreConfig.getMaxGlobalSessionSize(); - - private static ThreadLocal byteBufferThreadLocal = ThreadLocal - .withInitial(() -> ByteBuffer.allocate(MAX_GLOBAL_SESSION_SIZE)); - - /** - * ThreadLocal should be optimize. It is tied to the current threading model. - * threadlocal's public set method does nothing to protect it from abuse. - */ - private static final ThreadLocal EXPECTED_STATUS_THREAD_LOCAL = new ThreadLocal<>(); - - /** - * If the global session's status is (Rollbacking or Committing) and currentTime - - * createTime >= RETRY_DEAD_THRESHOLD then the tx will be remand as need to retry - * rollback. - */ - private static final int RETRY_DEAD_THRESHOLD = ConfigurationFactory.getInstance() - .getInt(ConfigurationKeys.RETRY_DEAD_THRESHOLD, DefaultValues.DEFAULT_RETRY_DEAD_THRESHOLD); - - private String xid; - - private long transactionId; - - private volatile GlobalStatus status; - - private String applicationId; - - private String transactionServiceGroup; - - private String transactionName; - - private int timeout; - - private long beginTime; - - private String applicationData; - - private final boolean lazyLoadBranch; - - private volatile boolean active = true; - - private List branchSessions; - - private GlobalSessionLock globalSessionLock = new GlobalSessionLock(); - - private Set lifecycleListeners = new HashSet<>(2); - - /** - * Add boolean. - * @param branchSession the branch session - * @return the boolean - */ - public boolean add(BranchSession branchSession) { - if (null != branchSessions) { - return branchSessions.add(branchSession); - } - else { - // db and redis no need to deal with - return true; - } - } - - /** - * Remove boolean. - * @param branchSession the branch session - * @return the boolean - */ - public boolean remove(BranchSession branchSession) { - synchronized (this) { - return branchSessions.remove(branchSession); - } - } - - /** - * Remove boolean. - * @param branchId the long - * @return the boolean - */ - public boolean remove(Long branchId) { - return this.remove(this.getBranch(branchId)); - } - - /** - * Can be committed async boolean. - * @return the boolean - */ - public boolean canBeCommittedAsync() { - List branchSessions = getBranchSessions(); - for (BranchSession branchSession : branchSessions) { - if (!branchSession.canBeCommittedAsync()) { - return false; - } - } - return true; - } - - /** - * Has AT branch. - * @return the boolean - */ - public boolean hasATBranch() { - List branchSessions = getBranchSessions(); - for (BranchSession branchSession : branchSessions) { - if (branchSession.getBranchType() == BranchType.AT) { - return true; - } - } - return false; - } - - /** - * Is saga type transaction. - * @return is saga - */ - public boolean isSaga() { - List branchSessions = getBranchSessions(); - if (branchSessions.size() > 0) { - return BranchType.SAGA == branchSessions.get(0).getBranchType(); - } - else { - return StringUtils.isNotBlank(transactionName) - && transactionName.startsWith(Constants.SAGA_TRANS_NAME_PREFIX); - } - } - - /** - * Is timeout boolean. - * @return the boolean - */ - public boolean isTimeout() { - return (System.currentTimeMillis() - beginTime) > timeout; - } - - /** - * prevent could not handle committing and rollbacking transaction. - * @return if true retry commit or roll back - */ - public boolean isDeadSession() { - return (System.currentTimeMillis() - beginTime) > RETRY_DEAD_THRESHOLD; - } - - @Override - public void begin() throws TransactionException { - this.status = GlobalStatus.Begin; - this.beginTime = System.currentTimeMillis(); - this.active = true; - SessionHolder.getRootSessionManager().onBegin(this); - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onBegin(this); - } - } - - @Override - public void changeGlobalStatus(GlobalStatus status) throws TransactionException { - if (GlobalStatus.Rollbacking == status || GlobalStatus.TimeoutRollbacking == status) { - LockerManagerFactory.getLockManager().updateLockStatus(xid, LockStatus.Rollbacking); - } - SessionHolder.getRootSessionManager().onStatusChange(this, status); - // set session status after update successfully - this.status = status; - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onStatusChange(this, status); - } - } - - @Override - public void changeBranchStatus(BranchSession branchSession, BranchStatus status) throws TransactionException { - SessionHolder.getRootSessionManager().onBranchStatusChange(this, branchSession, status); - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onBranchStatusChange(this, branchSession, status); - } - } - - @Override - public boolean isActive() { - return active; - } - - @Override - public void close() throws TransactionException { - if (active) { - SessionHolder.getRootSessionManager().onClose(this); - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onClose(this); - } - } - } - - @Override - public void end() throws TransactionException { - if (GlobalStatus.isTwoPhaseSuccess(status)) { - // TODO: Non AT mode does not need to be unlocked - // Clean locks first - clean(); - SessionHolder.getRootSessionManager().onSuccessEnd(this); - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onSuccessEnd(this); - } - } - else { - SessionHolder.getRootSessionManager().onFailEnd(this); - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onFailEnd(this); - } - } - } - - public void clean() throws TransactionException { - if (!LockerManagerFactory.getLockManager().releaseGlobalSessionLock(this)) { - throw new TransactionException("UnLock globalSession error, xid = " + this.xid); - } - } - - /** - * Close and clean. - * @throws TransactionException the transaction exception - */ - public void closeAndClean() throws TransactionException { - close(); - if (this.hasATBranch()) { - clean(); - } - } - - /** - * Add session lifecycle listener. - * @param sessionLifecycleListener the session lifecycle listener - */ - public void addSessionLifecycleListener(SessionLifecycleListener sessionLifecycleListener) { - lifecycleListeners.add(sessionLifecycleListener); - } - - /** - * Remove session lifecycle listener. - * @param sessionLifecycleListener the session lifecycle listener - */ - public void removeSessionLifecycleListener(SessionLifecycleListener sessionLifecycleListener) { - lifecycleListeners.remove(sessionLifecycleListener); - } - - @Override - public void addBranch(BranchSession branchSession) throws TransactionException { - SessionHolder.getRootSessionManager().onAddBranch(this, branchSession); - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onAddBranch(this, branchSession); - } - if (!RaftServerFactory.getInstance().isRaftMode()) { - add(branchSession); - } - } - - public void loadBranchs() { - if (branchSessions == null && isLazyLoadBranch()) { - synchronized (this) { - if (branchSessions == null && isLazyLoadBranch()) { - branchSessions = new ArrayList<>(); - Optional.ofNullable(SessionHolder.getRootSessionManager().findGlobalSession(xid, true)) - .ifPresent(globalSession -> branchSessions.addAll(globalSession.getBranchSessions())); - } - } - } - } - - @Override - public void unlockBranch(BranchSession branchSession) throws TransactionException { - // do not unlock if global status in (Committing, CommitRetrying, - // AsyncCommitting), - // because it's already unlocked in 'DefaultCore.commit()' - if (this.status != Committing && this.status != CommitRetrying && this.status != AsyncCommitting) { - if (!branchSession.unlock()) { - throw new TransactionException( - "Unlock branch lock failed, xid = " + this.xid + ", branchId = " + branchSession.getBranchId()); - } - } - } - - @Override - public void removeBranch(BranchSession branchSession) throws TransactionException { - SessionHolder.getRootSessionManager().onRemoveBranch(this, branchSession); - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onRemoveBranch(this, branchSession); - } - - if (!RaftServerFactory.getInstance().isRaftMode()) { - this.remove(branchSession); - } - - } - - @Override - public void removeAndUnlockBranch(BranchSession branchSession) throws TransactionException { - unlockBranch(branchSession); - removeBranch(branchSession); - } - - /** - * Gets branch. - * @param branchId the branch id - * @return the branch - */ - public BranchSession getBranch(long branchId) { - synchronized (this) { - List branchSessions = getBranchSessions(); - for (BranchSession branchSession : branchSessions) { - if (branchSession.getBranchId() == branchId) { - return branchSession; - } - } - - return null; - } - } - - /** - * Gets sorted branches. - * @return the sorted branches - */ - public List getSortedBranches() { - return new ArrayList<>(getBranchSessions()); - } - - /** - * Gets reverse sorted branches. - * @return the reverse sorted branches - */ - public List getReverseSortedBranches() { - List reversed = new ArrayList<>(getBranchSessions()); - Collections.reverse(reversed); - return reversed; - } - - /** - * Instantiates a new Global session. - */ - public GlobalSession() { - this.lazyLoadBranch = false; - } - - /** - * Instantiates a new Global session. - * @param applicationId the application id - * @param transactionServiceGroup the transaction service group - * @param transactionName the transaction name - * @param timeout the timeout - * @param lazyLoadBranch the lazy load branch - */ - public GlobalSession(String applicationId, String transactionServiceGroup, String transactionName, int timeout, - boolean lazyLoadBranch) { - this.transactionId = UUIDGenerator.generateUUID(); - this.status = GlobalStatus.Begin; - this.lazyLoadBranch = lazyLoadBranch; - if (!lazyLoadBranch) { - this.branchSessions = new ArrayList<>(); - } - this.applicationId = applicationId; - this.transactionServiceGroup = transactionServiceGroup; - this.transactionName = transactionName; - this.timeout = timeout; - this.xid = XID.generateXID(transactionId); - } - - /** - * Instantiates a new Global session. - * @param applicationId the application id - * @param transactionServiceGroup the transaction service group - * @param transactionName the transaction name - * @param timeout the timeout - */ - public GlobalSession(String applicationId, String transactionServiceGroup, String transactionName, int timeout) { - this(applicationId, transactionServiceGroup, transactionName, timeout, false); - } - - /** - * Gets transaction id. - * @return the transaction id - */ - public long getTransactionId() { - return transactionId; - } - - /** - * Sets transaction id. - * @param transactionId the transaction id - */ - public void setTransactionId(long transactionId) { - this.transactionId = transactionId; - } - - /** - * Gets status. - * @return the status - */ - public GlobalStatus getStatus() { - return status; - } - - /** - * Sets status. - * @param status the status - */ - public void setStatus(GlobalStatus status) { - this.status = status; - } - - /** - * Gets xid. - * @return the xid - */ - public String getXid() { - return xid; - } - - /** - * Sets xid. - * @param xid the xid - */ - public void setXid(String xid) { - this.xid = xid; - } - - /** - * Gets application id. - * @return the application id - */ - public String getApplicationId() { - return applicationId; - } - - /** - * Gets transaction service group. - * @return the transaction service group - */ - public String getTransactionServiceGroup() { - return transactionServiceGroup; - } - - /** - * Gets transaction name. - * @return the transaction name - */ - public String getTransactionName() { - return transactionName; - } - - /** - * Gets timeout. - * @return the timeout - */ - public int getTimeout() { - return timeout; - } - - /** - * Gets begin time. - * @return the begin time - */ - public long getBeginTime() { - return beginTime; - } - - /** - * Sets begin time. - * @param beginTime the begin time - */ - public void setBeginTime(long beginTime) { - this.beginTime = beginTime; - } - - /** - * Gets application data. - * @return the application data - */ - public String getApplicationData() { - return applicationData; - } - - /** - * Sets application data. - * @param applicationData the application data - */ - public void setApplicationData(String applicationData) { - this.applicationData = applicationData; - } - - public boolean isLazyLoadBranch() { - return lazyLoadBranch; - } - - /** - * Create global session global session. - * @param applicationId the application id - * @param txServiceGroup the tx service group - * @param txName the tx name - * @param timeout the timeout - * @return the global session - */ - public static GlobalSession createGlobalSession(String applicationId, String txServiceGroup, String txName, - int timeout) { - GlobalSession session = new GlobalSession(applicationId, txServiceGroup, txName, timeout, false); - return session; - } - - /** - * Sets active. - * @param active the active - */ - public void setActive(boolean active) { - this.active = active; - } - - @Override - public byte[] encode() { - byte[] byApplicationIdBytes = applicationId != null ? applicationId.getBytes() : null; - - byte[] byServiceGroupBytes = transactionServiceGroup != null ? transactionServiceGroup.getBytes() : null; - - byte[] byTxNameBytes = transactionName != null ? transactionName.getBytes() : null; - - byte[] xidBytes = xid != null ? xid.getBytes() : null; - - byte[] applicationDataBytes = applicationData != null ? applicationData.getBytes() : null; - - int size = calGlobalSessionSize(byApplicationIdBytes, byServiceGroupBytes, byTxNameBytes, xidBytes, - applicationDataBytes); - - if (size > MAX_GLOBAL_SESSION_SIZE) { - throw new RuntimeException("global session size exceeded, size : " + size + " maxBranchSessionSize : " - + MAX_GLOBAL_SESSION_SIZE); - } - ByteBuffer byteBuffer = byteBufferThreadLocal.get(); - // recycle - byteBuffer.clear(); - - byteBuffer.putLong(transactionId); - byteBuffer.putInt(timeout); - if (byApplicationIdBytes != null) { - byteBuffer.putShort((short) byApplicationIdBytes.length); - byteBuffer.put(byApplicationIdBytes); - } - else { - byteBuffer.putShort((short) 0); - } - if (byServiceGroupBytes != null) { - byteBuffer.putShort((short) byServiceGroupBytes.length); - byteBuffer.put(byServiceGroupBytes); - } - else { - byteBuffer.putShort((short) 0); - } - if (byTxNameBytes != null) { - byteBuffer.putShort((short) byTxNameBytes.length); - byteBuffer.put(byTxNameBytes); - } - else { - byteBuffer.putShort((short) 0); - } - if (xidBytes != null) { - byteBuffer.putInt(xidBytes.length); - byteBuffer.put(xidBytes); - } - else { - byteBuffer.putInt(0); - } - if (applicationDataBytes != null) { - byteBuffer.putInt(applicationDataBytes.length); - byteBuffer.put(applicationDataBytes); - } - else { - byteBuffer.putInt(0); - } - byteBuffer.putLong(beginTime); - byteBuffer.put((byte) status.getCode()); - BufferUtils.flip(byteBuffer); - byte[] result = new byte[byteBuffer.limit()]; - byteBuffer.get(result); - return result; - } - - private int calGlobalSessionSize(byte[] byApplicationIdBytes, byte[] byServiceGroupBytes, byte[] byTxNameBytes, - byte[] xidBytes, byte[] applicationDataBytes) { - return 8 // transactionId - + 4 // timeout - + 2 // byApplicationIdBytes.length - + 2 // byServiceGroupBytes.length - + 2 // byTxNameBytes.length - + 4 // xidBytes.length - + 4 // applicationDataBytes.length - + 8 // beginTime - + 1 // statusCode - + (byApplicationIdBytes == null ? 0 : byApplicationIdBytes.length) - + (byServiceGroupBytes == null ? 0 : byServiceGroupBytes.length) - + (byTxNameBytes == null ? 0 : byTxNameBytes.length) + (xidBytes == null ? 0 : xidBytes.length) - + (applicationDataBytes == null ? 0 : applicationDataBytes.length); - } - - @Override - public void decode(byte[] a) { - this.branchSessions = new ArrayList<>(); - ByteBuffer byteBuffer = ByteBuffer.wrap(a); - this.transactionId = byteBuffer.getLong(); - this.timeout = byteBuffer.getInt(); - short applicationIdLen = byteBuffer.getShort(); - if (applicationIdLen > 0) { - byte[] byApplicationId = new byte[applicationIdLen]; - byteBuffer.get(byApplicationId); - this.applicationId = new String(byApplicationId); - } - short serviceGroupLen = byteBuffer.getShort(); - if (serviceGroupLen > 0) { - byte[] byServiceGroup = new byte[serviceGroupLen]; - byteBuffer.get(byServiceGroup); - this.transactionServiceGroup = new String(byServiceGroup); - } - short txNameLen = byteBuffer.getShort(); - if (txNameLen > 0) { - byte[] byTxName = new byte[txNameLen]; - byteBuffer.get(byTxName); - this.transactionName = new String(byTxName); - } - int xidLen = byteBuffer.getInt(); - if (xidLen > 0) { - byte[] xidBytes = new byte[xidLen]; - byteBuffer.get(xidBytes); - this.xid = new String(xidBytes); - } - int applicationDataLen = byteBuffer.getInt(); - if (applicationDataLen > 0) { - byte[] applicationDataLenBytes = new byte[applicationDataLen]; - byteBuffer.get(applicationDataLenBytes); - this.applicationData = new String(applicationDataLenBytes); - } - - this.beginTime = byteBuffer.getLong(); - this.status = GlobalStatus.get(byteBuffer.get()); - } - - /** - * Has branch boolean. - * @return the boolean - */ - public boolean hasBranch() { - return getBranchSessions().size() > 0; - } - - public void lock() throws TransactionException { - globalSessionLock.lock(); - } - - public void unlock() { - globalSessionLock.unlock(); - } - - public List getBranchSessions() { - loadBranchs(); - return branchSessions; - } - - public void asyncCommit() throws TransactionException { - changeGlobalStatus(GlobalStatus.AsyncCommitting); - } - - public void queueToRetryCommit() throws TransactionException { - changeGlobalStatus(GlobalStatus.CommitRetrying); - } - - public void queueToRetryRollback() throws TransactionException { - GlobalStatus currentStatus = this.getStatus(); - GlobalStatus newStatus; - if (SessionStatusValidator.isTimeoutGlobalStatus(currentStatus)) { - newStatus = GlobalStatus.TimeoutRollbackRetrying; - } - else { - newStatus = GlobalStatus.RollbackRetrying; - } - changeGlobalStatus(newStatus); - } - - public void setExpectedStatusFromCurrent() { - EXPECTED_STATUS_THREAD_LOCAL.set(this.status); - } - - public void cleanExpectedStatus() { - EXPECTED_STATUS_THREAD_LOCAL.remove(); - } - - public GlobalStatus getExpectedStatus() { - return EXPECTED_STATUS_THREAD_LOCAL.get(); - } - - @Override - public String toString() { - return "GlobalSession{" + "xid='" + xid + '\'' + ", transactionId=" + transactionId + ", status=" + status - + ", applicationId='" + applicationId + '\'' + ", transactionServiceGroup='" + transactionServiceGroup - + '\'' + ", transactionName='" + transactionName + '\'' + ", timeout=" + timeout + ", beginTime=" - + beginTime + ", applicationData='" + applicationData + '\'' + ", lazyLoadBranch=" + lazyLoadBranch - + ", active=" + active + ", branchSessions=" + branchSessions + ", globalSessionLock=" - + globalSessionLock + ", lifecycleListeners=" + lifecycleListeners + '}'; - } - - private static class GlobalSessionLock { - - private final Lock globalSessionLock = new ReentrantLock(); - - private static final int GLOBAL_SESSION_LOCK_TIME_OUT_MILLS = 2 * 1000; - - public void lock() throws TransactionException { - try { - if (globalSessionLock.tryLock(GLOBAL_SESSION_LOCK_TIME_OUT_MILLS, TimeUnit.MILLISECONDS)) { - return; - } - } - catch (InterruptedException e) { - LOGGER.error("Interrupted error", e); - } - throw new GlobalTransactionException(TransactionExceptionCode.FailedLockGlobalTranscation, - "Lock global session failed"); - } - - public void unlock() { - globalSessionLock.unlock(); - } - - } - - @FunctionalInterface - public interface LockRunnable { - - void run() throws TransactionException; - - } - - @FunctionalInterface - public interface LockCallable { - - V call() throws TransactionException; - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/GlobalSessionHandler.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/GlobalSessionHandler.java deleted file mode 100644 index f4c6f0f4ff..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/GlobalSessionHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; - -/** - * The Functional Interface Global session handler. - * - * @author wang.liang - * @since 1.5.0 - */ -@FunctionalInterface -public interface GlobalSessionHandler { - - /** - * Handle global session. - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - void handle(GlobalSession globalSession) throws TransactionException; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/Lockable.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/Lockable.java deleted file mode 100644 index 71205a9e22..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/Lockable.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; - -/** - * The interface Lockable. - * - * @author sharajava - */ -public interface Lockable { - - /** - * Lock boolean. - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean lock() throws TransactionException; - - /** - * Unlock boolean. - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean unlock() throws TransactionException; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/Reloadable.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/Reloadable.java deleted file mode 100644 index 74f87de197..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/Reloadable.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -/** - * Service contains states which can be reloaded. - * - * @author sharajava - */ -public interface Reloadable { - - /** - * Reload states. - */ - void reload(); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionCondition.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionCondition.java deleted file mode 100644 index 289d94f09e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionCondition.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.model.GlobalStatus; - -/** - * The type Session condition. - * - * @author slievrly - */ -public class SessionCondition { - - private Long transactionId; - - private String xid; - - private GlobalStatus status; - - private GlobalStatus[] statuses; - - private Long overTimeAliveMills; - - private boolean lazyLoadBranch; - - /** - * Instantiates a new Session condition. - */ - public SessionCondition() { - } - - /** - * Instantiates a new Session condition. - * @param xid the xid - */ - public SessionCondition(String xid) { - this.xid = xid; - } - - /** - * Instantiates a new Session condition. - * @param status the status - */ - public SessionCondition(GlobalStatus status) { - this.status = status; - this.statuses = new GlobalStatus[] { status }; - } - - /** - * Instantiates a new Session condition. - * @param statuses the statuses - */ - public SessionCondition(GlobalStatus... statuses) { - this.statuses = statuses; - } - - /** - * Instantiates a new Session condition. - * @param overTimeAliveMills the over time alive mills - */ - public SessionCondition(long overTimeAliveMills) { - this.overTimeAliveMills = overTimeAliveMills; - } - - /** - * Gets status. - * @return the status - */ - public GlobalStatus getStatus() { - return status; - } - - /** - * Sets status. - * @param status the status - */ - public void setStatus(GlobalStatus status) { - this.status = status; - this.statuses = new GlobalStatus[] { status }; - } - - /** - * Gets over time alive mills. - * @return the over time alive mills - */ - public Long getOverTimeAliveMills() { - return overTimeAliveMills; - } - - /** - * Sets over time alive mills. - * @param overTimeAliveMills the over time alive mills - */ - public void setOverTimeAliveMills(Long overTimeAliveMills) { - this.overTimeAliveMills = overTimeAliveMills; - } - - public Long getTransactionId() { - return transactionId; - } - - public void setTransactionId(Long transactionId) { - this.transactionId = transactionId; - } - - public String getXid() { - return xid; - } - - public void setXid(String xid) { - this.xid = xid; - } - - public GlobalStatus[] getStatuses() { - return statuses; - } - - public void setStatuses(GlobalStatus... statuses) { - this.statuses = statuses; - } - - public boolean isLazyLoadBranch() { - return lazyLoadBranch; - } - - public void setLazyLoadBranch(boolean lazyLoadBranch) { - this.lazyLoadBranch = lazyLoadBranch; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionHelper.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionHelper.java deleted file mode 100644 index 1cfea617e6..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionHelper.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.common.ConfigurationKeys; -import io.seata.common.util.CollectionUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.context.RootContext; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.metrics.IdConstants; -import io.seata.server.UUIDGenerator; -import io.seata.server.cluster.raft.context.SeataClusterContext; -import io.seata.server.coordinator.DefaultCoordinator; -import io.seata.server.metrics.MetricsPublisher; -import io.seata.server.store.StoreConfig; -import io.seata.server.store.StoreConfig.SessionMode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -import static io.seata.common.DefaultValues.DEFAULT_ENABLE_BRANCH_ASYNC_REMOVE; -import static io.seata.common.DefaultValues.DEFAULT_SEATA_GROUP; - -/** - * The type Session helper. - * - * @author sharajava - */ -public final class SessionHelper { - - private static final Logger LOGGER = LoggerFactory.getLogger(SessionHelper.class); - - /** - * The constant CONFIG. - */ - private static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - private static final Boolean ENABLE_BRANCH_ASYNC_REMOVE = CONFIG - .getBoolean(ConfigurationKeys.ENABLE_BRANCH_ASYNC_REMOVE, DEFAULT_ENABLE_BRANCH_ASYNC_REMOVE); - - private static final String GROUP = CONFIG.getConfig(ConfigurationKeys.SERVER_RAFT_GROUP, DEFAULT_SEATA_GROUP); - - /** - * The instance of DefaultCoordinator. - */ - private static final DefaultCoordinator COORDINATOR = DefaultCoordinator.getInstance(); - - /** - * delay handle session. - */ - private static final boolean DELAY_HANDLE_SESSION = !(Objects.equals(StoreConfig.getSessionMode(), SessionMode.FILE) - || Objects.equals(StoreConfig.getSessionMode(), SessionMode.RAFT)); - - private SessionHelper() { - } - - public static BranchSession newBranchByGlobal(GlobalSession globalSession, BranchType branchType, String resourceId, - String lockKeys, String clientId) { - return newBranchByGlobal(globalSession, branchType, resourceId, null, lockKeys, clientId); - } - - /** - * New branch by global branch session. - * @param globalSession the global session - * @param branchType the branch type - * @param resourceId the resource id - * @param lockKeys the lock keys - * @param clientId the client id - * @return the branch session - */ - public static BranchSession newBranchByGlobal(GlobalSession globalSession, BranchType branchType, String resourceId, - String applicationData, String lockKeys, String clientId) { - BranchSession branchSession = new BranchSession(branchType); - - branchSession.setXid(globalSession.getXid()); - branchSession.setTransactionId(globalSession.getTransactionId()); - branchSession.setBranchId(UUIDGenerator.generateUUID()); - branchSession.setResourceId(resourceId); - branchSession.setLockKey(lockKeys); - branchSession.setClientId(clientId); - branchSession.setApplicationData(applicationData); - branchSession.setStatus(BranchStatus.Registered); - - return branchSession; - } - - /** - * New branch. - * @param branchType the branch type - * @param xid Transaction id. - * @param branchId Branch id. - * @param resourceId Resource id. - * @param applicationData Application data bind with this branch. - * @return the branch session - */ - public static BranchSession newBranch(BranchType branchType, String xid, long branchId, String resourceId, - String applicationData) { - BranchSession branchSession = new BranchSession(); - branchSession.setXid(xid); - branchSession.setBranchId(branchId); - branchSession.setBranchType(branchType); - branchSession.setResourceId(resourceId); - branchSession.setApplicationData(applicationData); - return branchSession; - } - - /** - * End committed. - * @param globalSession the global session - * @param retryGlobal the retry global - * @throws TransactionException the transaction exception - */ - public static void endCommitted(GlobalSession globalSession, boolean retryGlobal) throws TransactionException { - if (retryGlobal || !DELAY_HANDLE_SESSION) { - long beginTime = System.currentTimeMillis(); - boolean retryBranch = globalSession.getStatus() == GlobalStatus.CommitRetrying; - if (!globalSession.getStatus().equals(GlobalStatus.Committed)) { - // TODO: If the globalSession status in the database is Committed, don't - // set status again - globalSession.changeGlobalStatus(GlobalStatus.Committed); - } - globalSession.end(); - if (!DELAY_HANDLE_SESSION) { - MetricsPublisher.postSessionDoneEvent(globalSession, retryGlobal, false); - } - MetricsPublisher.postSessionDoneEvent(globalSession, IdConstants.STATUS_VALUE_AFTER_COMMITTED_KEY, true, - beginTime, retryBranch); - } - else { - globalSession.setStatus(GlobalStatus.Committed); - if (globalSession.isSaga()) { - globalSession.end(); - } - MetricsPublisher.postSessionDoneEvent(globalSession, false, false); - } - } - - /** - * End commit failed. - * @param globalSession the global session - * @param retryGlobal the retry global - * @throws TransactionException the transaction exception - */ - public static void endCommitFailed(GlobalSession globalSession, boolean retryGlobal) throws TransactionException { - endCommitFailed(globalSession, retryGlobal, false); - } - - /** - * End commit failed. - * @param globalSession the global session - * @param retryGlobal the retry global - * @param isRetryTimeout is retry timeout - * @throws TransactionException the transaction exception - */ - public static void endCommitFailed(GlobalSession globalSession, boolean retryGlobal, boolean isRetryTimeout) - throws TransactionException { - if (isRetryTimeout) { - globalSession.changeGlobalStatus(GlobalStatus.CommitRetryTimeout); - } - else { - globalSession.changeGlobalStatus(GlobalStatus.CommitFailed); - } - LOGGER.error("The Global session {} has changed the status to {}, need to be handled it manually.", - globalSession.getXid(), globalSession.getStatus()); - - globalSession.end(); - MetricsPublisher.postSessionDoneEvent(globalSession, retryGlobal, false); - } - - /** - * End rollbacked. - * @param globalSession the global session - * @param retryGlobal the retry global - * @throws TransactionException the transaction exception - */ - public static void endRollbacked(GlobalSession globalSession, boolean retryGlobal) throws TransactionException { - if (retryGlobal || !DELAY_HANDLE_SESSION) { - long beginTime = System.currentTimeMillis(); - boolean timeoutDone = false; - GlobalStatus currentStatus = globalSession.getStatus(); - if (currentStatus == GlobalStatus.TimeoutRollbacking) { - MetricsPublisher.postSessionDoneEvent(globalSession, GlobalStatus.TimeoutRollbacked, false, false); - timeoutDone = true; - } - boolean retryBranch = currentStatus == GlobalStatus.TimeoutRollbackRetrying - || currentStatus == GlobalStatus.RollbackRetrying; - if (!currentStatus.equals(GlobalStatus.TimeoutRollbacked) - && SessionStatusValidator.isTimeoutGlobalStatus(currentStatus)) { - globalSession.changeGlobalStatus(GlobalStatus.TimeoutRollbacked); - } - else if (!globalSession.getStatus().equals(GlobalStatus.Rollbacked)) { - globalSession.changeGlobalStatus(GlobalStatus.Rollbacked); - } - globalSession.end(); - if (!DELAY_HANDLE_SESSION && !timeoutDone) { - MetricsPublisher.postSessionDoneEvent(globalSession, retryGlobal, false); - } - MetricsPublisher.postSessionDoneEvent(globalSession, IdConstants.STATUS_VALUE_AFTER_ROLLBACKED_KEY, true, - beginTime, retryBranch); - } - else { - if (globalSession.isSaga()) { - globalSession.setStatus(GlobalStatus.Rollbacked); - globalSession.end(); - } - MetricsPublisher.postSessionDoneEvent(globalSession, GlobalStatus.Rollbacked, false, false); - } - } - - /** - * End rollback failed. - * @param globalSession the global session - * @param retryGlobal the retry global - * @throws TransactionException the transaction exception - */ - public static void endRollbackFailed(GlobalSession globalSession, boolean retryGlobal) throws TransactionException { - endRollbackFailed(globalSession, retryGlobal, false); - } - - /** - * End rollback failed. - * @param globalSession the global session - * @param retryGlobal the retry global - * @param isRetryTimeout is retry timeout - * @throws TransactionException the transaction exception - */ - public static void endRollbackFailed(GlobalSession globalSession, boolean retryGlobal, boolean isRetryTimeout) - throws TransactionException { - GlobalStatus currentStatus = globalSession.getStatus(); - if (isRetryTimeout) { - globalSession.changeGlobalStatus(GlobalStatus.RollbackRetryTimeout); - } - else if (SessionStatusValidator.isTimeoutGlobalStatus(currentStatus)) { - globalSession.changeGlobalStatus(GlobalStatus.TimeoutRollbackFailed); - } - else { - globalSession.changeGlobalStatus(GlobalStatus.RollbackFailed); - } - LOGGER.error("The Global session {} has changed the status to {}, need to be handled it manually.", - globalSession.getXid(), globalSession.getStatus()); - globalSession.end(); - MetricsPublisher.postSessionDoneEvent(globalSession, retryGlobal, false); - } - - /** - * Parallel foreach global sessions. - * @param sessions the global sessions - * @param handler the handler - */ - public static void parallelForEach(Collection sessions, GlobalSessionHandler handler) { - forEach(sessions, handler, true); - } - - /** - * Single foreach global sessions. - * @param sessions the global sessions - * @param handler the handler - */ - public static void singleForEach(Collection sessions, GlobalSessionHandler handler) { - forEach(sessions, handler, false); - } - - /** - * Foreach global sessions. - * @param sessions the global sessions - * @param handler the handler - * @param parallel the parallel - */ - public static void forEach(Collection sessions, GlobalSessionHandler handler, boolean parallel) { - if (CollectionUtils.isEmpty(sessions)) { - return; - } - - Stream stream = StreamSupport.stream(sessions.spliterator(), parallel); - stream.forEach(globalSession -> { - SeataClusterContext.bindGroup(GROUP); - try { - MDC.put(RootContext.MDC_KEY_XID, globalSession.getXid()); - handler.handle(globalSession); - } - catch (Throwable th) { - LOGGER.error("handle global session failed: {}", globalSession.getXid(), th); - } - finally { - SeataClusterContext.unbindGroup(); - MDC.remove(RootContext.MDC_KEY_XID); - } - }); - } - - /** - * Foreach global sessions. - * @param sessions the global sessions - * @param handler the handler - */ - public static void forEach(Collection sessions, GlobalSessionHandler handler) { - forEach(sessions, handler, true); - } - - /** - * Foreach branch sessions. - * @param sessions the branch session - * @param handler the handler - */ - public static Boolean forEach(Collection sessions, BranchSessionHandler handler) - throws TransactionException { - return forEach(sessions, handler, false); - } - - /** - * Foreach branch sessions. - * @param sessions the branch session - * @param handler the handler - */ - public static Boolean forEach(Collection sessions, BranchSessionHandler handler, boolean parallel) - throws TransactionException { - if (CollectionUtils.isNotEmpty(sessions)) { - Boolean result; - if (parallel) { - Map> map = new HashMap<>(4); - for (BranchSession session : sessions) { - map.computeIfAbsent(session.getResourceId(), k -> new ArrayList<>()).add(session); - } - List> completableFutures = new ArrayList<>(map.size()); - map.forEach((k, v) -> completableFutures.add(CompletableFuture.supplyAsync(() -> { - try { - return SessionHelper.forEach(v, handler, false); - } - catch (TransactionException e) { - throw new RuntimeException(e); - } - }))); - try { - for (CompletableFuture completableFuture : completableFutures) { - result = completableFuture.get(); - if (result == null) { - continue; - } - return result; - } - } - catch (InterruptedException e) { - throw new TransactionException(e); - } - catch (ExecutionException e) { - Throwable throwable = e.getCause(); - if (throwable instanceof RuntimeException) { - Throwable cause = throwable.getCause(); - if (cause instanceof TransactionException) { - throw (TransactionException) cause; - } - } - throw new TransactionException(e); - } - } - else { - for (BranchSession branchSession : sessions) { - try { - MDC.put(RootContext.MDC_KEY_BRANCH_ID, String.valueOf(branchSession.getBranchId())); - result = handler.handle(branchSession); - if (result == null) { - continue; - } - return result; - } - finally { - MDC.remove(RootContext.MDC_KEY_BRANCH_ID); - } - } - } - } - return null; - } - - /** - * Single foreach branch sessions. - * @param sessions the branch session - * @param handler the handler - * @since 1.5.0 - */ - public static Boolean singleForEach(Collection sessions, BranchSessionHandler handler) - throws TransactionException { - return SessionHelper.forEach(sessions, handler, false); - } - - /** - * Parallel foreach branch sessions. - * @param sessions the branch session - * @param handler the handler - */ - public static Boolean parallelForEach(Collection sessions, BranchSessionHandler handler) - throws TransactionException { - return SessionHelper.forEach(sessions, handler, true); - } - - /** - * remove branchSession from globalSession. - * @param globalSession the globalSession - * @param branchSession the branchSession - * @param isAsync if asynchronous remove - */ - public static void removeBranch(GlobalSession globalSession, BranchSession branchSession, boolean isAsync) - throws TransactionException { - globalSession.unlockBranch(branchSession); - if (isEnableBranchRemoveAsync() && isAsync) { - COORDINATOR.doBranchRemoveAsync(globalSession, branchSession); - } - else { - globalSession.removeBranch(branchSession); - } - } - - /** - * remove branchSession from globalSession. - * @param globalSession the globalSession - * @param isAsync if asynchronous remove - */ - public static void removeAllBranch(GlobalSession globalSession, boolean isAsync) throws TransactionException { - List branchSessions = globalSession.getSortedBranches(); - if (branchSessions == null || branchSessions.isEmpty()) { - return; - } - boolean isAsyncRemove = isEnableBranchRemoveAsync() && isAsync; - for (BranchSession branchSession : branchSessions) { - if (isAsyncRemove) { - globalSession.unlockBranch(branchSession); - } - else { - globalSession.removeAndUnlockBranch(branchSession); - } - } - if (isAsyncRemove) { - COORDINATOR.doBranchRemoveAllAsync(globalSession); - } - } - - /** - * if true, enable delete the branch asynchronously. - * @return the boolean - */ - private static boolean isEnableBranchRemoveAsync() { - return Objects.equals(Boolean.TRUE, DELAY_HANDLE_SESSION) - && Objects.equals(Boolean.TRUE, ENABLE_BRANCH_ASYNC_REMOVE); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionHolder.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionHolder.java deleted file mode 100644 index 853a01dce3..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionHolder.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.common.ConfigurationKeys; -import io.seata.common.XID; -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.exception.StoreException; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.GlobalStatus; -import io.seata.core.model.LockStatus; -import io.seata.core.store.DistributedLockDO; -import io.seata.core.store.DistributedLocker; -import io.seata.server.cluster.raft.RaftServerFactory; -import io.seata.server.cluster.raft.context.SeataClusterContext; -import io.seata.server.lock.distributed.DistributedLockerFactory; -import io.seata.server.store.StoreConfig; -import io.seata.server.store.StoreConfig.SessionMode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.*; -import java.util.concurrent.CompletableFuture; - -import static io.seata.common.ConfigurationKeys.SERVER_SERVICE_PORT_CAMEL; -import static io.seata.common.DefaultValues.*; -import static java.io.File.separator; - -/** - * The type Session holder. - * - * @author sharajava - */ -public class SessionHolder { - - private static final Logger LOGGER = LoggerFactory.getLogger(SessionHolder.class); - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The constant ROOT_SESSION_MANAGER_NAME. - */ - public static final String ROOT_SESSION_MANAGER_NAME = "root.data"; - - /** - * The redis distributed lock expire time. - */ - private static long DISTRIBUTED_LOCK_EXPIRE_TIME = CONFIG.getLong(ConfigurationKeys.DISTRIBUTED_LOCK_EXPIRE_TIME, - DEFAULT_DISTRIBUTED_LOCK_EXPIRE_TIME); - - private static SessionManager ROOT_SESSION_MANAGER; - - private static volatile Map SESSION_MANAGER_MAP; - - private static DistributedLocker DISTRIBUTED_LOCKER; - - public static void init() { - init(null); - } - - /** - * Init. - * @param sessionMode the store mode: file, db, redis - * @throws IOException the io exception - */ - public static void init(SessionMode sessionMode) { - if (null == sessionMode) { - sessionMode = StoreConfig.getSessionMode(); - } - LOGGER.info("use session store mode: {}", sessionMode.getName()); - DISTRIBUTED_LOCKER = DistributedLockerFactory.getDistributedLocker(sessionMode.getName()); - if (SessionMode.DB.equals(sessionMode)) { - ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, SessionMode.DB.getName()); - reload(sessionMode); - } - else if (SessionMode.RAFT.equals(sessionMode) || SessionMode.FILE.equals(sessionMode)) { - RaftServerFactory.getInstance().init(); - if (CollectionUtils.isNotEmpty(RaftServerFactory.getInstance().getRaftServers())) { - sessionMode = SessionMode.RAFT; - } - if (SessionMode.RAFT.equals(sessionMode)) { - String group = CONFIG.getConfig(ConfigurationKeys.SERVER_RAFT_GROUP, DEFAULT_SEATA_GROUP); - ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, SessionMode.RAFT.getName(), - new Object[] { ROOT_SESSION_MANAGER_NAME }); - SESSION_MANAGER_MAP = new HashMap<>(); - SESSION_MANAGER_MAP.put(group, ROOT_SESSION_MANAGER); - RaftServerFactory.getInstance().start(); - } - else { - String sessionStorePath = CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR, - DEFAULT_SESSION_STORE_FILE_DIR) + separator + System.getProperty(SERVER_SERVICE_PORT_CAMEL); - if (StringUtils.isBlank(sessionStorePath)) { - throw new StoreException("the {store.file.dir} is empty."); - } - ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, SessionMode.FILE.getName(), - new Object[] { ROOT_SESSION_MANAGER_NAME, sessionStorePath }); - reload(sessionMode); - } - } - else if (SessionMode.REDIS.equals(sessionMode)) { - ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, SessionMode.REDIS.getName()); - reload(sessionMode); - } - else { - // unknown store - throw new IllegalArgumentException("unknown store mode:" + sessionMode.getName()); - } - } - - /** - * Reload. - * @param sessionMode the mode of store - */ - protected static void reload(SessionMode sessionMode) { - if (sessionMode == SessionMode.FILE) { - ((Reloadable) ROOT_SESSION_MANAGER).reload(); - reload(ROOT_SESSION_MANAGER.allSessions(), sessionMode); - } - else { - reload(null, sessionMode); - } - } - - public static void reload(Collection allSessions, SessionMode storeMode) { - reload(allSessions, storeMode, true); - } - - public static void reload(Collection allSessions, SessionMode storeMode, boolean acquireLock) { - if ((SessionMode.FILE == storeMode || SessionMode.RAFT == storeMode) - && CollectionUtils.isNotEmpty(allSessions)) { - for (GlobalSession globalSession : allSessions) { - GlobalStatus globalStatus = globalSession.getStatus(); - switch (globalStatus) { - case TimeoutRollbacked: - case Rollbacked: - try { - SessionHelper.endRollbacked(globalSession, true); - } - catch (TransactionException e) { - LOGGER.error("Could not handle the global session, xid: {},error: {}", - globalSession.getXid(), e.getMessage()); - } - break; - case Committed: - try { - SessionHelper.endCommitted(globalSession, true); - } - catch (TransactionException e) { - LOGGER.error("Could not handle the global session, xid: {},error: {}", - globalSession.getXid(), e.getMessage()); - } - break; - case Finished: - case UnKnown: - case CommitFailed: - case RollbackFailed: - case TimeoutRollbackFailed: - removeInErrorState(globalSession); - break; - case AsyncCommitting: - case Committing: - case CommitRetrying: - if (Objects.equals(SessionMode.RAFT, storeMode)) { - // When a state change occurs, re-electing the leader may - // result in the lock not being unlocked yet - // so a COMMIT unlock operation needs to be performed at the - // time of re-election - try { - globalSession.clean(); - } - catch (TransactionException e) { - throw new RuntimeException(e); - } - } - break; - default: { - if (acquireLock) { - lockBranchSessions(globalSession.getSortedBranches()); - if (GlobalStatus.Rollbacking.equals(globalSession.getStatus()) - || GlobalStatus.TimeoutRollbacking.equals(globalSession.getStatus())) { - globalSession.getBranchSessions() - .parallelStream() - .forEach(branchSession -> branchSession.setLockStatus(LockStatus.Rollbacking)); - } - } - switch (globalStatus) { - case Rollbacking: - case RollbackRetrying: - case TimeoutRollbacking: - case TimeoutRollbackRetrying: - break; - case Begin: - if (Objects.equals(storeMode, SessionMode.RAFT)) { - try { - globalSession.changeGlobalStatus(GlobalStatus.RollbackRetrying); - LOGGER.info("change global status: {}, xid: {}", globalSession.getStatus(), - globalSession.getXid()); - } - catch (TransactionException e) { - LOGGER.error("change global status fail: {}", e.getMessage(), e); - } - } - else { - globalSession.setActive(true); - } - break; - default: - LOGGER.error("Could not handle the global session, xid: {}", globalSession.getXid()); - throw new ShouldNeverHappenException("NOT properly handled " + globalStatus); - } - break; - } - } - } - } - else { - // Redis, db and so on - CompletableFuture.runAsync(() -> { - SessionCondition searchCondition = new SessionCondition(GlobalStatus.UnKnown, GlobalStatus.Committed, - GlobalStatus.Rollbacked, GlobalStatus.TimeoutRollbacked, GlobalStatus.Finished); - searchCondition.setLazyLoadBranch(true); - - long now = System.currentTimeMillis(); - List errorStatusGlobalSessions = ROOT_SESSION_MANAGER - .findGlobalSessions(searchCondition); - while (!CollectionUtils.isEmpty(errorStatusGlobalSessions)) { - for (GlobalSession errorStatusGlobalSession : errorStatusGlobalSessions) { - if (errorStatusGlobalSession.getBeginTime() >= now) { - // Exit when the global transaction begin after the instance - // started - return; - } - - removeInErrorState(errorStatusGlobalSession); - } - - // Load the next part - errorStatusGlobalSessions = ROOT_SESSION_MANAGER.findGlobalSessions(searchCondition); - } - }); - } - } - - private static void removeInErrorState(GlobalSession globalSession) { - try { - LOGGER.warn("The global session should NOT be {}, remove it. xid = {}", globalSession.getStatus(), - globalSession.getXid()); - getRootSessionManager().removeGlobalSession(globalSession); - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Remove global session succeed, xid = {}, status = {}", globalSession.getXid(), - globalSession.getStatus()); - } - } - catch (Exception e) { - LOGGER.error("Remove global session failed, xid = {}, status = {}", globalSession.getXid(), - globalSession.getStatus(), e); - } - } - - private static void lockBranchSessions(List branchSessions) { - branchSessions.forEach(branchSession -> { - try { - branchSession.lock(); - } - catch (TransactionException e) { - throw new ShouldNeverHappenException(e); - } - }); - } - - // endregion - - // region get session manager - - /** - * Gets root session manager. - * @return the root session manager - */ - public static SessionManager getRootSessionManager() { - String group = SeataClusterContext.getGroup(); - return getRootSessionManager(group); - } - - public static SessionManager getRootSessionManager(String group) { - return StringUtils.isNotBlank(group) && SESSION_MANAGER_MAP != null - ? SESSION_MANAGER_MAP.computeIfAbsent(group, k -> ROOT_SESSION_MANAGER) : ROOT_SESSION_MANAGER; - } - - // endregion - - /** - * Find global session. - * @param xid the xid - * @return the global session - */ - public static GlobalSession findGlobalSession(String xid) { - return findGlobalSession(xid, true); - } - - /** - * Find global session. - * @param xid the xid - * @param withBranchSessions the withBranchSessions - * @return the global session - */ - public static GlobalSession findGlobalSession(String xid, boolean withBranchSessions) { - return getRootSessionManager().findGlobalSession(xid, withBranchSessions); - } - - /** - * lock and execute - * @param globalSession the global session - * @param lockCallable the lock Callable - * @return the value - */ - public static T lockAndExecute(GlobalSession globalSession, GlobalSession.LockCallable lockCallable) - throws TransactionException { - return getRootSessionManager().lockAndExecute(globalSession, lockCallable); - } - - /** - * acquire lock - * @param lockKey the lock key, should be distinct for each lock - * @return the boolean - */ - public static boolean acquireDistributedLock(String lockKey) { - return DISTRIBUTED_LOCKER - .acquireLock(new DistributedLockDO(lockKey, XID.getIpAddressAndPort(), DISTRIBUTED_LOCK_EXPIRE_TIME)); - } - - /** - * release lock - * @return the boolean - */ - public static boolean releaseDistributedLock(String lockKey) { - return DISTRIBUTED_LOCKER - .releaseLock(new DistributedLockDO(lockKey, XID.getIpAddressAndPort(), DISTRIBUTED_LOCK_EXPIRE_TIME)); - } - - /** - * Execute the function after get the distribute lock - * @param key the distribute lock key - * @param func the function to be call - * @return whether the func be call - */ - public static boolean distributedLockAndExecute(String key, NoArgsFunc func) { - boolean lock = false; - try { - if (lock == acquireDistributedLock(key)) { - func.call(); - } - } - catch (Exception e) { - LOGGER.error("Exception running function with key = {}", key, e); - } - finally { - if (lock) { - try { - SessionHolder.releaseDistributedLock(key); - } - catch (Exception ex) { - LOGGER.warn("release distribute lock failure, message = {}", ex.getMessage(), ex); - } - } - } - return lock; - } - - public static void destroy() { - RaftServerFactory.getInstance().destroy(); - if (ROOT_SESSION_MANAGER != null) { - ROOT_SESSION_MANAGER.destroy(); - } - SESSION_MANAGER_MAP = null; - } - - @FunctionalInterface - public interface NoArgsFunc { - - void call(); - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionLifecycle.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionLifecycle.java deleted file mode 100644 index 9ab5ed9f55..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionLifecycle.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; - -/** - * The interface Session lifecycle. - * - * @author sharajava - */ -public interface SessionLifecycle { - - /** - * Begin. - * @throws TransactionException the transaction exception - */ - void begin() throws TransactionException; - - /** - * Change status. - * @param status the status - * @throws TransactionException the transaction exception - */ - void changeGlobalStatus(GlobalStatus status) throws TransactionException; - - /** - * Change branch status. - * @param branchSession the branch session - * @param status the status - * @throws TransactionException the transaction exception - */ - void changeBranchStatus(BranchSession branchSession, BranchStatus status) throws TransactionException; - - /** - * Add branch. - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - void addBranch(BranchSession branchSession) throws TransactionException; - - /** - * Release the lock of branch. - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - void unlockBranch(BranchSession branchSession) throws TransactionException; - - /** - * Remove branch. - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - void removeBranch(BranchSession branchSession) throws TransactionException; - - /** - * Remove branch and release the lock of branch. - * @param branchSession the branchSession - * @throws TransactionException the TransactionException - */ - void removeAndUnlockBranch(BranchSession branchSession) throws TransactionException; - - /** - * Is active boolean. - * @return the boolean - */ - boolean isActive(); - - /** - * Close. - * @throws TransactionException the transaction exception - */ - void close() throws TransactionException; - - /** - * end. - * @throws TransactionException the transaction exception - */ - void end() throws TransactionException; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionLifecycleListener.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionLifecycleListener.java deleted file mode 100644 index 5dd444c288..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionLifecycleListener.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; - -/** - * The interface Session lifecycle listener. - * - * @author sharajava - */ -public interface SessionLifecycleListener { - - /** - * On begin. - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - void onBegin(GlobalSession globalSession) throws TransactionException; - - /** - * On status change. - * @param globalSession the global session - * @param status the status - * @throws TransactionException the transaction exception - */ - void onStatusChange(GlobalSession globalSession, GlobalStatus status) throws TransactionException; - - /** - * On branch status change. - * @param globalSession the global session - * @param branchSession the branch session - * @param status the status - * @throws TransactionException the transaction exception - */ - void onBranchStatusChange(GlobalSession globalSession, BranchSession branchSession, BranchStatus status) - throws TransactionException; - - /** - * On add branch. - * @param globalSession the global session - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - void onAddBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException; - - /** - * On remove branch. - * @param globalSession the global session - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - void onRemoveBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException; - - /** - * On close. - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - void onClose(GlobalSession globalSession) throws TransactionException; - - /** - * On end. - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - void onSuccessEnd(GlobalSession globalSession) throws TransactionException; - - /** - * On fail end. - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - void onFailEnd(GlobalSession globalSession) throws TransactionException; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionManager.java deleted file mode 100644 index 40785cabc5..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionManager.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import java.util.Collection; -import java.util.List; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; -import io.seata.core.rpc.Disposable; - -/** - * The interface Session manager. - * - * @author sharajava - */ -public interface SessionManager extends Disposable { - - /** - * Add global session. - * @param session the session - * @throws TransactionException the transaction exception - */ - void addGlobalSession(GlobalSession session) throws TransactionException; - - /** - * Find global session global session. - * @param xid the xid - * @return the global session - */ - GlobalSession findGlobalSession(String xid); - - /** - * Find global session global session. - * @param xid the xid - * @param withBranchSessions the withBranchSessions - * @return the global session - */ - GlobalSession findGlobalSession(String xid, boolean withBranchSessions); - - /** - * Update global session status. - * @param session the session - * @param status the status - * @throws TransactionException the transaction exception - */ - void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException; - - /** - * Remove global session. - * @param session the session - * @throws TransactionException the transaction exception - */ - void removeGlobalSession(GlobalSession session) throws TransactionException; - - /** - * Add branch session. - * @param globalSession the global session - * @param session the session - * @throws TransactionException the transaction exception - */ - void addBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException; - - /** - * Update branch session status. - * @param session the session - * @param status the status - * @throws TransactionException the transaction exception - */ - void updateBranchSessionStatus(BranchSession session, BranchStatus status) throws TransactionException; - - /** - * Remove branch session. - * @param globalSession the global session - * @param session the session - * @throws TransactionException the transaction exception - */ - void removeBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException; - - /** - * All sessions collection. - * @return the collection - */ - Collection allSessions(); - - /** - * Find global sessions list. - * @param condition the condition - * @return the list - */ - List findGlobalSessions(SessionCondition condition); - - /** - * lock and execute - * @param globalSession the global session - * @param lockCallable the lock Callable - * @return the value - * @throws TransactionException the transaction exception - */ - @Deprecated - T lockAndExecute(GlobalSession globalSession, GlobalSession.LockCallable lockCallable) - throws TransactionException; - - /** - * On begin. - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - @Deprecated - void onBegin(GlobalSession globalSession) throws TransactionException; - - /** - * On status change. - * @param globalSession the global session - * @param status the status - * @throws TransactionException the transaction exception - */ - @Deprecated - void onStatusChange(GlobalSession globalSession, GlobalStatus status) throws TransactionException; - - /** - * On branch status change. - * @param globalSession the global session - * @param branchSession the branch session - * @param status the status - * @throws TransactionException the transaction exception - */ - @Deprecated - void onBranchStatusChange(GlobalSession globalSession, BranchSession branchSession, BranchStatus status) - throws TransactionException; - - /** - * On add branch. - * @param globalSession the global session - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - @Deprecated - void onAddBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException; - - /** - * On remove branch. - * @param globalSession the global session - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - @Deprecated - void onRemoveBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException; - - /** - * On close. - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - @Deprecated - void onClose(GlobalSession globalSession) throws TransactionException; - - /** - * On end. - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - @Deprecated - void onSuccessEnd(GlobalSession globalSession) throws TransactionException; - - /** - * On fail end. - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - @Deprecated - void onFailEnd(GlobalSession globalSession) throws TransactionException; - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionStatusValidator.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionStatusValidator.java deleted file mode 100644 index 9601a6b59b..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/session/SessionStatusValidator.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.model.GlobalStatus; - -/** - * The type change status validator. - * - * @author Bughue - */ -public class SessionStatusValidator { - - /** - * is timeout global status - * @param status the global session - */ - public static boolean isTimeoutGlobalStatus(GlobalStatus status) { - return status == GlobalStatus.TimeoutRollbacked || status == GlobalStatus.TimeoutRollbackFailed - || status == GlobalStatus.TimeoutRollbacking || status == GlobalStatus.TimeoutRollbackRetrying; - } - - /** - * is rollback global status - * @param status the global session - */ - public static boolean isRollbackGlobalStatus(GlobalStatus status) { - return status == GlobalStatus.Rollbacking || status == GlobalStatus.RollbackRetrying - || status == GlobalStatus.Rollbacked || status == GlobalStatus.RollbackFailed - || status == GlobalStatus.RollbackRetryTimeout; - } - - /** - * is commit global status - * @param status the global session - */ - public static boolean isCommitGlobalStatus(GlobalStatus status) { - return status == GlobalStatus.Committing || status == GlobalStatus.AsyncCommitting - || status == GlobalStatus.CommitRetrying || status == GlobalStatus.Committed - || status == GlobalStatus.CommitFailed || status == GlobalStatus.CommitRetryTimeout; - } - - /** - * check the relation of before status and after status - * @param before the global session - * @param after the global session - */ - public static boolean validateUpdateStatus(GlobalStatus before, GlobalStatus after) { - if (isTimeoutGlobalStatus(before) && isCommitGlobalStatus(after)) { - return false; - } - if (isCommitGlobalStatus(before) && isTimeoutGlobalStatus(after)) { - return false; - } - if (isRollbackGlobalStatus(before) && isCommitGlobalStatus(after)) { - return false; - } - if (isCommitGlobalStatus(before) && isRollbackGlobalStatus(after)) { - return false; - } - return true; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/spring/listener/SeataPropertiesLoader.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/spring/listener/SeataPropertiesLoader.java deleted file mode 100644 index c435744b97..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/spring/listener/SeataPropertiesLoader.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.spring.listener; - -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.config.FileConfiguration; -import io.seata.config.file.FileConfig; -import io.seata.server.store.StoreConfig; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.PropertiesPropertySource; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; - -import static io.seata.common.ConfigurationKeys.FILE_ROOT_PREFIX_CONFIG; -import static io.seata.common.ConfigurationKeys.FILE_ROOT_PREFIX_REGISTRY; -import static io.seata.common.ConfigurationKeys.METRICS_PREFIX; -import static io.seata.common.ConfigurationKeys.SEATA_FILE_PREFIX_ROOT_CONFIG; -import static io.seata.common.ConfigurationKeys.SERVER_PREFIX; -import static io.seata.common.ConfigurationKeys.STORE_PREFIX; -import static io.seata.common.ConfigurationKeys.TRANSPORT_PREFIX; - -@Order(Ordered.HIGHEST_PRECEDENCE) -public class SeataPropertiesLoader implements ApplicationContextInitializer { - - List prefixList = Arrays.asList(FILE_ROOT_PREFIX_CONFIG, FILE_ROOT_PREFIX_REGISTRY, SERVER_PREFIX, - STORE_PREFIX, METRICS_PREFIX, TRANSPORT_PREFIX); - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - ConfigurableEnvironment environment = applicationContext.getEnvironment(); - FileConfiguration configuration = ConfigurationFactory.getOriginFileInstanceRegistry(); - FileConfig fileConfig = configuration.getFileConfig(); - Map configs = fileConfig.getAllConfig(); - if (CollectionUtils.isNotEmpty(configs)) { - Optional originFileInstance = ConfigurationFactory.getOriginFileInstance(); - originFileInstance - .ifPresent(fileConfiguration -> configs.putAll(fileConfiguration.getFileConfig().getAllConfig())); - Properties properties = new Properties(); - configs.forEach((k, v) -> { - if (v instanceof String) { - if (StringUtils.isEmpty((String) v)) { - return; - } - } - // Convert the configuration name to the configuration name under Spring - // Boot - if (prefixList.stream().anyMatch(k::startsWith)) { - properties.put(SEATA_FILE_PREFIX_ROOT_CONFIG + k, v); - } - }); - environment.getPropertySources().addLast(new PropertiesPropertySource("seataOldConfig", properties)); - } - // Load by priority - System.setProperty("sessionMode", StoreConfig.getSessionMode().getName()); - System.setProperty("lockMode", StoreConfig.getLockMode().getName()); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/spring/listener/ServerApplicationListener.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/spring/listener/ServerApplicationListener.java deleted file mode 100644 index bdb73b9507..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/spring/listener/ServerApplicationListener.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.spring.listener; - -import io.seata.common.holder.ObjectHolder; -import io.seata.common.util.StringUtils; -import io.seata.spring.boot.autoconfigure.SeataCoreEnvironmentPostProcessor; -import io.seata.spring.boot.autoconfigure.SeataServerEnvironmentPostProcessor; -import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.boot.context.logging.LoggingApplicationListener; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.event.GenericApplicationListener; -import org.springframework.core.ResolvableType; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.PropertiesPropertySource; - -import java.util.Properties; - -import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; -import static io.seata.common.DefaultValues.SERVICE_OFFSET_SPRING_BOOT; -import static io.seata.core.constants.ConfigurationKeys.*; - -/** - * @author slievrly - * @author funkye - */ -public class ServerApplicationListener implements GenericApplicationListener { - - @Override - public boolean supportsEventType(ResolvableType eventType) { - return eventType.getRawClass() != null - && ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType.getRawClass()); - } - - @Override - public void onApplicationEvent(ApplicationEvent event) { - if (!(event instanceof ApplicationEnvironmentPreparedEvent environmentPreparedEvent)) { - return; - } - ConfigurableEnvironment environment = environmentPreparedEvent.getEnvironment(); - ObjectHolder.INSTANCE.setObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT, environment); - SeataCoreEnvironmentPostProcessor.init(); - SeataServerEnvironmentPostProcessor.init(); - - String[] args = environmentPreparedEvent.getArgs(); - - // port: -p > -D > env > yml > default - - // -p 8091 - if (args != null && args.length >= 2) { - for (int i = 0; i < args.length; ++i) { - if ("-p".equalsIgnoreCase(args[i]) && i < args.length - 1) { - setTargetPort(environment, args[i + 1], true); - return; - } - } - } - - // -Dserver.servicePort=8091 - String dPort = environment.getProperty(SERVER_SERVICE_PORT_CAMEL, String.class); - if (StringUtils.isNotBlank(dPort)) { - setTargetPort(environment, dPort, true); - return; - } - - // docker -e SEATA_PORT=8091 - String envPort = environment.getProperty(ENV_SEATA_PORT_KEY, String.class); - if (StringUtils.isNotBlank(envPort)) { - setTargetPort(environment, envPort, true); - return; - } - - // yml properties server.service-port=8091 - String configPort = environment.getProperty(SERVER_SERVICE_PORT_CONFIG, String.class); - if (StringUtils.isNotBlank(configPort)) { - setTargetPort(environment, configPort, false); - return; - } - - // server.port=7091 - String serverPort = environment.getProperty("server.port", String.class); - if (StringUtils.isBlank(serverPort)) { - serverPort = "8080"; - } - String servicePort = String.valueOf(Integer.parseInt(serverPort) + SERVICE_OFFSET_SPRING_BOOT); - setTargetPort(environment, servicePort, true); - } - - private void setTargetPort(ConfigurableEnvironment environment, String port, boolean needAddPropertySource) { - // get rpc port first, use to logback-spring.xml, @see the class named - // `SystemPropertyLoggerContextListener` - System.setProperty(SERVER_SERVICE_PORT_CAMEL, port); - if (needAddPropertySource) { - // add property source to the first position - Properties pro = new Properties(); - pro.setProperty(SERVER_SERVICE_PORT_CONFIG, port); - environment.getPropertySources().addFirst(new PropertiesPropertySource("serverProperties", pro)); - } - } - - /** - * higher than LoggingApplicationListener. - * @return the order - */ - @Override - public int getOrder() { - return LoggingApplicationListener.DEFAULT_ORDER - 1; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/SessionConverter.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/SessionConverter.java deleted file mode 100644 index d1614e840e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/SessionConverter.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage; - -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.core.store.BranchTransactionDO; -import io.seata.core.store.GlobalTransactionDO; -import io.seata.server.cluster.raft.sync.msg.dto.BranchTransactionDTO; -import io.seata.server.console.vo.BranchSessionVO; -import io.seata.server.console.vo.GlobalSessionVO; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.store.SessionStorable; -import org.springframework.beans.BeanUtils; - -import java.util.*; - -/** - * The session converter. - * - * @author wangzhongxiang - * @author doubleDimple - */ -public class SessionConverter { - - public static GlobalSession convertGlobalSession(GlobalTransactionDO globalTransactionDO, boolean lazyLoadBranch) { - if (globalTransactionDO == null) { - return null; - } - GlobalSession session = new GlobalSession(globalTransactionDO.getApplicationId(), - globalTransactionDO.getTransactionServiceGroup(), globalTransactionDO.getTransactionName(), - globalTransactionDO.getTimeout(), lazyLoadBranch); - session.setXid(globalTransactionDO.getXid()); - session.setTransactionId(globalTransactionDO.getTransactionId()); - session.setStatus(GlobalStatus.get(globalTransactionDO.getStatus())); - session.setApplicationData(globalTransactionDO.getApplicationData()); - session.setBeginTime(globalTransactionDO.getBeginTime()); - return session; - } - - public static GlobalSession convertGlobalSession(GlobalTransactionDO globalTransactionDO) { - return convertGlobalSession(globalTransactionDO, false); - } - - public static BranchSession convertBranchSession(BranchTransactionDO branchTransactionDO) { - if (branchTransactionDO == null) { - return null; - } - BranchSession branchSession = new BranchSession(); - branchSession.setXid(branchTransactionDO.getXid()); - branchSession.setTransactionId(branchTransactionDO.getTransactionId()); - branchSession.setApplicationData(branchTransactionDO.getApplicationData()); - branchSession.setBranchId(branchTransactionDO.getBranchId()); - branchSession.setBranchType(BranchType.valueOf(branchTransactionDO.getBranchType())); - branchSession.setResourceId(branchTransactionDO.getResourceId()); - branchSession.setClientId(branchTransactionDO.getClientId()); - branchSession.setResourceGroupId(branchTransactionDO.getResourceGroupId()); - branchSession.setStatus(BranchStatus.get(branchTransactionDO.getStatus())); - if (branchTransactionDO instanceof BranchTransactionDTO) { - branchSession.setLockKey(((BranchTransactionDTO) branchTransactionDO).getLockKey()); - } - return branchSession; - } - - public static GlobalTransactionDO convertGlobalTransactionDO(SessionStorable session) { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - convertGlobalTransactionDO(globalTransactionDO, session); - return globalTransactionDO; - } - - public static void convertGlobalTransactionDO(GlobalTransactionDO globalTransactionDO, SessionStorable session) { - if (!(session instanceof GlobalSession)) { - throw new IllegalArgumentException("The parameter of SessionStorable is not available, SessionStorable:" - + StringUtils.toString(session)); - } - GlobalSession globalSession = (GlobalSession) session; - globalTransactionDO.setXid(globalSession.getXid()); - globalTransactionDO.setStatus(globalSession.getStatus().getCode()); - globalTransactionDO.setApplicationId(globalSession.getApplicationId()); - globalTransactionDO.setBeginTime(globalSession.getBeginTime()); - globalTransactionDO.setTimeout(globalSession.getTimeout()); - globalTransactionDO.setTransactionId(globalSession.getTransactionId()); - globalTransactionDO.setTransactionName(globalSession.getTransactionName()); - globalTransactionDO.setTransactionServiceGroup(globalSession.getTransactionServiceGroup()); - globalTransactionDO.setApplicationData(globalSession.getApplicationData()); - } - - public static BranchTransactionDO convertBranchTransactionDO(SessionStorable session) { - if (!(session instanceof BranchSession)) { - throw new IllegalArgumentException("The parameter of SessionStorable is not available, SessionStorable:" - + StringUtils.toString(session)); - } - BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); - convertBranchTransaction(branchTransactionDO, session); - return branchTransactionDO; - } - - public static BranchTransactionDTO convertBranchTransactionDTO(SessionStorable session) { - if (!(session instanceof BranchSession)) { - throw new IllegalArgumentException("The parameter of SessionStorable is not available, SessionStorable:" - + StringUtils.toString(session)); - } - BranchTransactionDTO branchTransactionDTO = new BranchTransactionDTO(); - convertBranchTransaction(branchTransactionDTO, session); - return branchTransactionDTO; - } - - public static void convertBranchTransaction(BranchTransactionDO branchTransactionDO, SessionStorable session) { - BranchSession branchSession = (BranchSession) session; - branchTransactionDO.setXid(branchSession.getXid()); - branchTransactionDO.setBranchId(branchSession.getBranchId()); - branchTransactionDO.setBranchType(branchSession.getBranchType().name()); - branchTransactionDO.setClientId(branchSession.getClientId()); - branchTransactionDO.setResourceGroupId(branchSession.getResourceGroupId()); - branchTransactionDO.setTransactionId(branchSession.getTransactionId()); - branchTransactionDO.setApplicationData(branchSession.getApplicationData()); - branchTransactionDO.setResourceId(branchSession.getResourceId()); - branchTransactionDO.setStatus(branchSession.getStatus().getCode()); - if (branchTransactionDO instanceof BranchTransactionDTO) { - ((BranchTransactionDTO) branchTransactionDO).setLockKey(branchSession.getLockKey()); - } - } - - public static void convertToGlobalSessionVo(List result, List globalSessions) { - if (CollectionUtils.isNotEmpty(globalSessions)) { - for (GlobalSession globalSession : globalSessions) { - GlobalSessionVO globalSessionVO = new GlobalSessionVO(); - BeanUtils.copyProperties(globalSession, globalSessionVO); - globalSessionVO.setStatus(globalSession.getStatus().getCode()); - globalSessionVO.setTimeout(Long.valueOf(globalSession.getTimeout())); - globalSessionVO.setBranchSessionVOs(converToBranchSession(globalSession.getBranchSessions())); - result.add(globalSessionVO); - } - } - } - - public static Set converToBranchSession(List branchSessions) { - Set branchSessionVOs = new HashSet<>(branchSessions.size()); - if (CollectionUtils.isNotEmpty(branchSessions)) { - for (BranchSession branchSession : branchSessions) { - BranchSessionVO branchSessionVONew = new BranchSessionVO(); - BeanUtils.copyProperties(branchSession, branchSessionVONew); - - branchSessionVONew.setBranchType(branchSession.getBranchType().name()); - branchSessionVONew.setStatus(branchSession.getStatus().getCode()); - branchSessionVOs.add(branchSessionVONew); - } - } - return branchSessionVOs; - } - - /** - * convert GlobalSession to GlobalSessionVO. - * @param filteredSessions the GlobalSession list - * @return the GlobalSessionVO list - */ - public static List convertGlobalSession(List filteredSessions) { - - if (CollectionUtils.isEmpty(filteredSessions)) { - return Collections.emptyList(); - } - - final ArrayList result = new ArrayList<>(filteredSessions.size()); - - for (GlobalSession session : filteredSessions) { - result.add(new GlobalSessionVO(session.getXid(), session.getTransactionId(), session.getStatus().getCode(), - session.getApplicationId(), session.getTransactionServiceGroup(), session.getTransactionName(), - (long) session.getTimeout(), session.getBeginTime(), session.getApplicationData(), - convertBranchSession(session.getBranchSessions()))); - } - return result; - } - - /** - * convert BranchSession to BranchSessionVO. - * @param branchSessions the BranchSession list - * @return the BranchSessionVO list - */ - public static Set convertBranchSession(List branchSessions) { - - if (CollectionUtils.isEmpty(branchSessions)) { - return Collections.emptySet(); - } - - final Set result = new HashSet<>(branchSessions.size()); - - for (BranchSession session : branchSessions) { - result.add(new BranchSessionVO(session.getXid(), session.getTransactionId(), session.getBranchId(), - session.getResourceGroupId(), session.getResourceId(), session.getBranchType().name(), - session.getStatus().getCode(), session.getClientId(), session.getApplicationData())); - } - return result; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseDistributedLocker.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseDistributedLocker.java deleted file mode 100644 index 84cb402c4a..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseDistributedLocker.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.db.lock; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import javax.sql.DataSource; - -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.loader.LoadLevel; -import io.seata.common.loader.Scope; -import io.seata.common.util.IOUtil; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationCache; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.constants.ServerTableColumnsName; -import io.seata.core.store.DistributedLockDO; -import io.seata.core.store.DistributedLocker; -import io.seata.core.store.db.DataSourceProvider; -import io.seata.core.store.db.sql.distributed.lock.DistributedLockSqlFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static io.seata.core.constants.ConfigurationKeys.DISTRIBUTED_LOCK_DB_TABLE; - -/** - * @author chd - */ -@LoadLevel(name = "db", scope = Scope.SINGLETON) -public class DataBaseDistributedLocker implements DistributedLocker { - - private static final Logger LOGGER = LoggerFactory.getLogger(DataBaseDistributedLocker.class); - - private final String dbType; - - private final String datasourceType; - - private volatile String distributedLockTable; - - private DataSource distributedLockDataSource; - - private static final String LOCK_WAIT_TIMEOUT_MYSQL_MESSAGE = "try restarting transaction"; - - private static final int LOCK_WAIT_TIMEOUT_MYSQL_CODE = 1205; - - private static final Set IGNORE_MYSQL_CODE = new HashSet<>(); - - private static final Set IGNORE_MYSQL_MESSAGE = new HashSet<>(); - - static { - IGNORE_MYSQL_CODE.add(LOCK_WAIT_TIMEOUT_MYSQL_CODE); - IGNORE_MYSQL_MESSAGE.add(LOCK_WAIT_TIMEOUT_MYSQL_MESSAGE); - } - - /** - * whether the distribute lock demotion using for 1.5.0 only and will remove in 1.6.0 - */ - @Deprecated - private volatile boolean demotion; - - /** - * Instantiates a new Log store data base dao. - */ - public DataBaseDistributedLocker() { - Configuration configuration = ConfigurationFactory.getInstance(); - - distributedLockTable = configuration.getConfig(DISTRIBUTED_LOCK_DB_TABLE); - dbType = configuration.getConfig(ConfigurationKeys.STORE_DB_TYPE); - datasourceType = configuration.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); - - if (StringUtils.isBlank(distributedLockTable)) { - demotion = true; - ConfigurationCache.addConfigListener(DISTRIBUTED_LOCK_DB_TABLE, new ConfigurationChangeListener() { - @Override - public void onChangeEvent(ConfigurationChangeEvent event) { - String newValue = event.getNewValue(); - if (StringUtils.isNotBlank(newValue)) { - distributedLockTable = newValue; - init(); - demotion = false; - ConfigurationCache.removeConfigListener(DISTRIBUTED_LOCK_DB_TABLE, this); - } - } - }); - - LOGGER.error("The distribute lock table is not config, please create the target table and config it"); - return; - } - - init(); - } - - @Override - public boolean acquireLock(DistributedLockDO distributedLockDO) { - if (demotion) { - return true; - } - - Connection connection = null; - boolean originalAutoCommit = false; - try { - connection = distributedLockDataSource.getConnection(); - originalAutoCommit = connection.getAutoCommit(); - connection.setAutoCommit(false); - - DistributedLockDO lockFromDB = getDistributedLockDO(connection, distributedLockDO.getLockKey()); - if (null == lockFromDB) { - boolean ret = insertDistribute(connection, distributedLockDO); - connection.commit(); - return ret; - } - - if (lockFromDB.getExpireTime() >= System.currentTimeMillis()) { - LOGGER.debug("the distribute lock for key :{} is holding by :{}, acquire lock failure.", - distributedLockDO.getLockKey(), lockFromDB.getLockValue()); - connection.commit(); - return false; - } - - boolean ret = updateDistributedLock(connection, distributedLockDO); - connection.commit(); - - return ret; - } - catch (SQLException ex) { - // ignore "Lock wait timeout exceeded; try restarting transaction" - // TODO: need nowait adaptation - if (!ignoreSQLException(ex)) { - LOGGER.error("execute acquire lock failure, key is: {}", distributedLockDO.getLockKey(), ex); - } - try { - if (connection != null) { - connection.rollback(); - } - } - catch (SQLException e) { - LOGGER.warn("rollback fail because of {}", e.getMessage(), e); - } - return false; - } - finally { - try { - if (originalAutoCommit) { - connection.setAutoCommit(true); - } - IOUtil.close(connection); - } - catch (SQLException ignore) { - } - } - } - - @Override - public boolean releaseLock(DistributedLockDO distributedLockDO) { - if (demotion) { - return true; - } - - Connection connection = null; - boolean originalAutoCommit = false; - try { - connection = distributedLockDataSource.getConnection(); - originalAutoCommit = connection.getAutoCommit(); - connection.setAutoCommit(false); - - DistributedLockDO distributedLockDOFromDB = getDistributedLockDO(connection, - distributedLockDO.getLockKey()); - if (null == distributedLockDOFromDB) { - throw new ShouldNeverHappenException( - "distributedLockDO would not be null when release distribute lock"); - } - - if (distributedLockDOFromDB.getExpireTime() >= System.currentTimeMillis() - && !Objects.equals(distributedLockDOFromDB.getLockValue(), distributedLockDO.getLockValue())) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("the distribute lock for key :{} is holding by :{}, skip the release lock.", - distributedLockDO.getLockKey(), distributedLockDOFromDB.getLockValue()); - } - connection.commit(); - return true; - } - - distributedLockDO.setLockValue(StringUtils.SPACE); - distributedLockDO.setExpireTime(0L); - boolean ret = updateDistributedLock(connection, distributedLockDO); - - connection.commit(); - return ret; - } - catch (SQLException ex) { - if (!ignoreSQLException(ex)) { - LOGGER.error("execute release lock failure, key is: {}", distributedLockDO.getLockKey(), ex); - } - - try { - if (connection != null) { - connection.rollback(); - } - } - catch (SQLException e) { - LOGGER.warn("rollback fail because of {}", e.getMessage(), e); - } - return false; - } - finally { - try { - if (originalAutoCommit) { - connection.setAutoCommit(true); - } - IOUtil.close(connection); - } - catch (SQLException ignore) { - } - } - } - - protected DistributedLockDO getDistributedLockDO(Connection connection, String key) throws SQLException { - try (PreparedStatement pst = connection - .prepareStatement(DistributedLockSqlFactory.getDistributedLogStoreSql(dbType) - .getSelectDistributeForUpdateSql(distributedLockTable))) { - - pst.setString(1, key); - ResultSet resultSet = pst.executeQuery(); - - if (resultSet.next()) { - DistributedLockDO distributedLock = new DistributedLockDO(); - distributedLock.setExpireTime(resultSet.getLong(ServerTableColumnsName.DISTRIBUTED_LOCK_EXPIRE)); - distributedLock.setLockValue(resultSet.getString(ServerTableColumnsName.DISTRIBUTED_LOCK_VALUE)); - distributedLock.setLockKey(key); - return distributedLock; - } - return null; - } - } - - protected boolean insertDistribute(Connection connection, DistributedLockDO distributedLockDO) throws SQLException { - try (PreparedStatement insertPst = connection.prepareStatement( - DistributedLockSqlFactory.getDistributedLogStoreSql(dbType).getInsertSql(distributedLockTable))) { - insertPst.setString(1, distributedLockDO.getLockKey()); - insertPst.setString(2, distributedLockDO.getLockValue()); - if (distributedLockDO.getExpireTime() > 0) { - distributedLockDO.setExpireTime(distributedLockDO.getExpireTime() + System.currentTimeMillis()); - } - insertPst.setLong(3, distributedLockDO.getExpireTime()); - return insertPst.executeUpdate() > 0; - } - } - - protected boolean updateDistributedLock(Connection connection, DistributedLockDO distributedLockDO) - throws SQLException { - try (PreparedStatement updatePst = connection.prepareStatement( - DistributedLockSqlFactory.getDistributedLogStoreSql(dbType).getUpdateSql(distributedLockTable))) { - updatePst.setString(1, distributedLockDO.getLockValue()); - if (distributedLockDO.getExpireTime() > 0) { - distributedLockDO.setExpireTime(distributedLockDO.getExpireTime() + System.currentTimeMillis()); - } - updatePst.setLong(2, distributedLockDO.getExpireTime()); - updatePst.setString(3, distributedLockDO.getLockKey()); - return updatePst.executeUpdate() > 0; - } - } - - private void init() { - this.distributedLockDataSource = EnhancedServiceLoader.load(DataSourceProvider.class, datasourceType).provide(); - } - - private boolean ignoreSQLException(SQLException exception) { - if (IGNORE_MYSQL_CODE.contains(exception.getErrorCode())) { - return true; - } - if (StringUtils.isNotBlank(exception.getMessage())) { - return IGNORE_MYSQL_MESSAGE.stream().anyMatch(message -> exception.getMessage().contains(message)); - } - return false; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java deleted file mode 100644 index 8b822a7796..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.db.lock; - -import javax.sql.DataSource; -import io.seata.common.executor.Initialize; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.loader.LoadLevel; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.exception.TransactionException; -import io.seata.core.lock.Locker; -import io.seata.core.store.db.DataSourceProvider; -import io.seata.server.lock.AbstractLockManager; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; - -/** - * The type db lock manager. - * - * @author zjinlei - */ -@LoadLevel(name = "db") -public class DataBaseLockManager extends AbstractLockManager implements Initialize { - - /** - * The locker. - */ - private Locker locker; - - @Override - public void init() { - // init dataSource - String datasourceType = ConfigurationFactory.getInstance() - .getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); - DataSource lockStoreDataSource = EnhancedServiceLoader.load(DataSourceProvider.class, datasourceType).provide(); - locker = new DataBaseLocker(lockStoreDataSource); - } - - @Override - public boolean releaseLock(BranchSession branchSession) throws TransactionException { - try { - return getLocker().releaseLock(branchSession.getXid(), branchSession.getBranchId()); - } - catch (Exception t) { - LOGGER.error("unLock error, xid {}, branchId:{}", branchSession.getXid(), branchSession.getBranchId(), t); - return false; - } - } - - @Override - public Locker getLocker(BranchSession branchSession) { - return locker; - } - - @Override - public boolean releaseGlobalSessionLock(GlobalSession globalSession) throws TransactionException { - try { - return getLocker().releaseLock(globalSession.getXid()); - } - catch (Exception t) { - LOGGER.error("unLock globalSession error, xid:{}", globalSession.getXid(), t); - return false; - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseLocker.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseLocker.java deleted file mode 100644 index 8df4b0c350..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/DataBaseLocker.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.db.lock; - -import java.util.List; -import javax.sql.DataSource; -import io.seata.common.exception.DataAccessException; -import io.seata.common.exception.StoreException; -import io.seata.common.util.CollectionUtils; -import io.seata.core.lock.AbstractLocker; -import io.seata.core.lock.RowLock; -import io.seata.core.model.LockStatus; -import io.seata.core.store.LockStore; - -/** - * The type Data base locker. - * - * @author zhangsen - */ -public class DataBaseLocker extends AbstractLocker { - - private LockStore lockStore; - - /** - * Instantiates a new Data base locker. - */ - public DataBaseLocker() { - } - - /** - * Instantiates a new Data base locker. - * @param logStoreDataSource the log store data source - */ - public DataBaseLocker(DataSource logStoreDataSource) { - lockStore = new LockStoreDataBaseDAO(logStoreDataSource); - } - - @Override - public boolean acquireLock(List locks) { - return acquireLock(locks, true, false); - } - - @Override - public boolean acquireLock(List locks, boolean autoCommit, boolean skipCheckLock) { - if (CollectionUtils.isEmpty(locks)) { - // no lock - return true; - } - try { - return lockStore.acquireLock(convertToLockDO(locks), autoCommit, skipCheckLock); - } - catch (StoreException e) { - throw e; - } - catch (Exception t) { - LOGGER.error("AcquireLock error, locks:{}", CollectionUtils.toString(locks), t); - return false; - } - } - - @Override - public boolean releaseLock(List locks) { - if (CollectionUtils.isEmpty(locks)) { - // no lock - return true; - } - try { - return lockStore.unLock(convertToLockDO(locks)); - } - catch (StoreException e) { - throw e; - } - catch (Exception t) { - LOGGER.error("unLock error, locks:{}", CollectionUtils.toString(locks), t); - return false; - } - } - - @Override - public boolean releaseLock(String xid, Long branchId) { - try { - return lockStore.unLock(branchId); - } - catch (StoreException e) { - throw e; - } - catch (Exception t) { - LOGGER.error("unLock by branchId error, xid {}, branchId:{}", xid, branchId, t); - return false; - } - } - - @Override - public boolean releaseLock(String xid) { - try { - return lockStore.unLock(xid); - } - catch (StoreException e) { - throw e; - } - catch (Exception t) { - LOGGER.error("unLock by branchIds error, xid {}", xid, t); - return false; - } - } - - @Override - public boolean isLockable(List locks) { - if (CollectionUtils.isEmpty(locks)) { - // no lock - return true; - } - try { - return lockStore.isLockable(convertToLockDO(locks)); - } - catch (DataAccessException e) { - throw e; - } - catch (Exception t) { - LOGGER.error("isLockable error, locks:{}", CollectionUtils.toString(locks), t); - return false; - } - } - - @Override - public void updateLockStatus(String xid, LockStatus lockStatus) { - lockStore.updateLockStatus(xid, lockStatus); - } - - /** - * Sets lock store. - * @param lockStore the lock store - */ - public void setLockStore(LockStore lockStore) { - this.lockStore = lockStore; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/LockStoreDataBaseDAO.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/LockStoreDataBaseDAO.java deleted file mode 100644 index c4085d5a78..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/lock/LockStoreDataBaseDAO.java +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.db.lock; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.SQLIntegrityConstraintViolationException; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import javax.sql.DataSource; -import io.seata.common.exception.DataAccessException; -import io.seata.common.exception.StoreException; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.IOUtil; -import io.seata.common.util.LambdaUtils; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.constants.ServerTableColumnsName; -import io.seata.core.exception.BranchTransactionException; -import io.seata.core.model.LockStatus; -import io.seata.core.store.LockDO; -import io.seata.core.store.LockStore; -import io.seata.core.store.db.sql.lock.LockStoreSqlFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static io.seata.common.DefaultValues.DEFAULT_LOCK_DB_TABLE; -import static io.seata.core.exception.TransactionExceptionCode.LockKeyConflictFailFast; - -/** - * The type Data base lock store. - * - * @author zhangsen - */ -public class LockStoreDataBaseDAO implements LockStore { - - private static final Logger LOGGER = LoggerFactory.getLogger(LockStoreDataBaseDAO.class); - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The Lock store data source. - */ - protected DataSource lockStoreDataSource; - - /** - * The Lock table. - */ - protected String lockTable; - - /** - * The Db type. - */ - protected String dbType; - - /** - * Instantiates a new Data base lock store dao. - * @param lockStoreDataSource the log store data source - */ - public LockStoreDataBaseDAO(DataSource lockStoreDataSource) { - this.lockStoreDataSource = lockStoreDataSource; - lockTable = CONFIG.getConfig(ConfigurationKeys.LOCK_DB_TABLE, DEFAULT_LOCK_DB_TABLE); - dbType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE); - if (StringUtils.isBlank(dbType)) { - throw new StoreException("there must be db type."); - } - if (lockStoreDataSource == null) { - throw new StoreException("there must be lockStoreDataSource."); - } - } - - @Override - public boolean acquireLock(LockDO lockDO) { - return acquireLock(Collections.singletonList(lockDO)); - } - - @Override - public boolean acquireLock(List lockDOs) { - return acquireLock(lockDOs, true, false); - } - - @Override - public boolean acquireLock(List lockDOs, boolean autoCommit, boolean skipCheckLock) { - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - Set dbExistedRowKeys = new HashSet<>(); - boolean originalAutoCommit = true; - if (lockDOs.size() > 1) { - lockDOs = lockDOs.stream() - .filter(LambdaUtils.distinctByKey(LockDO::getRowKey)) - .collect(Collectors.toList()); - } - try { - conn = lockStoreDataSource.getConnection(); - if (originalAutoCommit = conn.getAutoCommit()) { - conn.setAutoCommit(false); - } - List unrepeatedLockDOs = lockDOs; - - // check lock - if (!skipCheckLock) { - - boolean canLock = true; - // query - String checkLockSQL = LockStoreSqlFactory.getLogStoreSql(dbType) - .getCheckLockableSql(lockTable, lockDOs.size()); - ps = conn.prepareStatement(checkLockSQL); - for (int i = 0; i < lockDOs.size(); i++) { - ps.setString(i + 1, lockDOs.get(i).getRowKey()); - } - rs = ps.executeQuery(); - String currentXID = lockDOs.get(0).getXid(); - boolean failFast = false; - while (rs.next()) { - String dbXID = rs.getString(ServerTableColumnsName.LOCK_TABLE_XID); - if (!StringUtils.equals(dbXID, currentXID)) { - if (LOGGER.isInfoEnabled()) { - String dbPk = rs.getString(ServerTableColumnsName.LOCK_TABLE_PK); - String dbTableName = rs.getString(ServerTableColumnsName.LOCK_TABLE_TABLE_NAME); - long dbBranchId = rs.getLong(ServerTableColumnsName.LOCK_TABLE_BRANCH_ID); - LOGGER.info("Global lock on [{}:{}] is holding by xid {} branchId {}", dbTableName, dbPk, - dbXID, dbBranchId); - } - if (!autoCommit) { - int status = rs.getInt(ServerTableColumnsName.LOCK_TABLE_STATUS); - if (status == LockStatus.Rollbacking.getCode()) { - failFast = true; - } - } - canLock = false; - break; - } - - dbExistedRowKeys.add(rs.getString(ServerTableColumnsName.LOCK_TABLE_ROW_KEY)); - } - if (!canLock) { - conn.rollback(); - if (failFast) { - throw new StoreException(new BranchTransactionException(LockKeyConflictFailFast)); - } - return false; - } - // If the lock has been exists in db, remove it from the lockDOs - if (CollectionUtils.isNotEmpty(dbExistedRowKeys)) { - unrepeatedLockDOs = lockDOs.stream() - .filter(lockDO -> !dbExistedRowKeys.contains(lockDO.getRowKey())) - .collect(Collectors.toList()); - } - if (CollectionUtils.isEmpty(unrepeatedLockDOs)) { - conn.rollback(); - return true; - } - } - - // lock - if (unrepeatedLockDOs.size() == 1) { - LockDO lockDO = unrepeatedLockDOs.get(0); - if (!doAcquireLock(conn, lockDO)) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Global lock acquire failed, xid {} branchId {} pk {}", lockDO.getXid(), - lockDO.getBranchId(), lockDO.getPk()); - } - conn.rollback(); - return false; - } - } - else { - if (!doAcquireLocks(conn, unrepeatedLockDOs)) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Global lock batch acquire failed, xid {} branchId {} pks {}", - unrepeatedLockDOs.get(0).getXid(), unrepeatedLockDOs.get(0).getBranchId(), - unrepeatedLockDOs.stream().map(lockDO -> lockDO.getPk()).collect(Collectors.toList())); - } - conn.rollback(); - return false; - } - } - conn.commit(); - return true; - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(rs, ps); - if (conn != null) { - try { - if (originalAutoCommit) { - conn.setAutoCommit(true); - } - conn.close(); - } - catch (SQLException e) { - } - } - } - } - - @Override - public boolean unLock(LockDO lockDO) { - return unLock(Collections.singletonList(lockDO)); - } - - @Override - public boolean unLock(List lockDOs) { - Connection conn = null; - PreparedStatement ps = null; - try { - conn = lockStoreDataSource.getConnection(); - conn.setAutoCommit(true); - - // batch release lock - String batchDeleteSQL = LockStoreSqlFactory.getLogStoreSql(dbType) - .getBatchDeleteLockSql(lockTable, lockDOs.size()); - ps = conn.prepareStatement(batchDeleteSQL); - ps.setString(1, lockDOs.get(0).getXid()); - for (int i = 0; i < lockDOs.size(); i++) { - ps.setString(i + 2, lockDOs.get(i).getRowKey()); - } - ps.executeUpdate(); - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - return true; - } - - @Override - public boolean unLock(String xid) { - Connection conn = null; - PreparedStatement ps = null; - try { - conn = lockStoreDataSource.getConnection(); - conn.setAutoCommit(true); - // batch release lock by branch list - String batchDeleteSQL = LockStoreSqlFactory.getLogStoreSql(dbType).getBatchDeleteLockSqlByXid(lockTable); - ps = conn.prepareStatement(batchDeleteSQL); - ps.setString(1, xid); - ps.executeUpdate(); - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - return true; - } - - @Override - public boolean unLock(Long branchId) { - Connection conn = null; - PreparedStatement ps = null; - try { - conn = lockStoreDataSource.getConnection(); - conn.setAutoCommit(true); - // batch release lock by branchId - String batchDeleteSQL = LockStoreSqlFactory.getLogStoreSql(dbType) - .getBatchDeleteLockSqlByBranchId(lockTable); - ps = conn.prepareStatement(batchDeleteSQL); - ps.setLong(1, branchId); - ps.executeUpdate(); - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - return true; - } - - @Override - public boolean isLockable(List lockDOs) { - Connection conn = null; - try { - conn = lockStoreDataSource.getConnection(); - conn.setAutoCommit(true); - if (!checkLockable(conn, lockDOs)) { - return false; - } - return true; - } - catch (SQLException e) { - throw new DataAccessException(e); - } - finally { - IOUtil.close(conn); - } - } - - @Override - public void updateLockStatus(String xid, LockStatus lockStatus) { - String updateStatusLockByGlobalSql = LockStoreSqlFactory.getLogStoreSql(dbType) - .getBatchUpdateStatusLockByGlobalSql(lockTable); - try (Connection conn = lockStoreDataSource.getConnection(); - PreparedStatement ps = conn.prepareStatement(updateStatusLockByGlobalSql)) { - conn.setAutoCommit(true); - ps.setInt(1, lockStatus.getCode()); - ps.setString(2, xid); - ps.executeUpdate(); - } - catch (SQLException e) { - throw new DataAccessException(e); - } - } - - /** - * Do acquire lock boolean. - * @param conn the conn - * @param lockDO the lock do - * @return the boolean - */ - protected boolean doAcquireLock(Connection conn, LockDO lockDO) { - PreparedStatement ps = null; - try { - // insert - String insertLockSQL = LockStoreSqlFactory.getLogStoreSql(dbType).getInsertLockSQL(lockTable); - ps = conn.prepareStatement(insertLockSQL); - ps.setString(1, lockDO.getXid()); - ps.setLong(2, lockDO.getTransactionId()); - ps.setLong(3, lockDO.getBranchId()); - ps.setString(4, lockDO.getResourceId()); - ps.setString(5, lockDO.getTableName()); - ps.setString(6, lockDO.getPk()); - ps.setString(7, lockDO.getRowKey()); - ps.setInt(8, LockStatus.Locked.getCode()); - return ps.executeUpdate() > 0; - } - catch (SQLException e) { - if (e instanceof SQLIntegrityConstraintViolationException) { - return false; - } - throw new StoreException(e); - } - finally { - IOUtil.close(ps); - } - } - - /** - * Do acquire lock boolean. - * @param conn the conn - * @param lockDOs the lock do list - * @return the boolean - */ - protected boolean doAcquireLocks(Connection conn, List lockDOs) throws SQLException { - PreparedStatement ps = null; - try { - // insert - String insertLockSQL = LockStoreSqlFactory.getLogStoreSql(dbType).getInsertLockSQL(lockTable); - ps = conn.prepareStatement(insertLockSQL); - for (LockDO lockDO : lockDOs) { - ps.setString(1, lockDO.getXid()); - ps.setLong(2, lockDO.getTransactionId()); - ps.setLong(3, lockDO.getBranchId()); - ps.setString(4, lockDO.getResourceId()); - ps.setString(5, lockDO.getTableName()); - ps.setString(6, lockDO.getPk()); - ps.setString(7, lockDO.getRowKey()); - ps.setInt(8, lockDO.getStatus()); - ps.addBatch(); - } - return ps.executeBatch().length == lockDOs.size(); - } - catch (SQLIntegrityConstraintViolationException e) { - LOGGER.error("Global lock batch acquire error: {}", e.getMessage(), e); - // return false,let the caller go to conn.rollabck() - return false; - } - catch (SQLException e) { - throw e; - } - finally { - IOUtil.close(ps); - } - } - - /** - * Check lock boolean. - * @param conn the conn - * @param lockDOs the lock do - * @return the boolean - */ - protected boolean checkLockable(Connection conn, List lockDOs) { - PreparedStatement ps = null; - ResultSet rs = null; - try { - // query - String checkLockSQL = LockStoreSqlFactory.getLogStoreSql(dbType) - .getCheckLockableSql(lockTable, lockDOs.size()); - ps = conn.prepareStatement(checkLockSQL); - for (int i = 0; i < lockDOs.size(); i++) { - ps.setString(i + 1, lockDOs.get(i).getRowKey()); - } - rs = ps.executeQuery(); - while (rs.next()) { - String xid = rs.getString("xid"); - if (!StringUtils.equals(xid, lockDOs.get(0).getXid())) { - return false; - } - } - return true; - } - catch (SQLException e) { - throw new DataAccessException(e); - } - finally { - IOUtil.close(rs, ps); - } - } - - /** - * Sets lock table. - * @param lockTable the lock table - */ - public void setLockTable(String lockTable) { - this.lockTable = lockTable; - } - - /** - * Sets db type. - * @param dbType the db type - */ - public void setDbType(String dbType) { - this.dbType = dbType; - } - - /** - * Sets log store data source. - * @param lockStoreDataSource the log store data source - */ - public void setLogStoreDataSource(DataSource lockStoreDataSource) { - this.lockStoreDataSource = lockStoreDataSource; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java deleted file mode 100644 index fc6a912eb0..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.db.session; - -import java.util.Collection; -import java.util.List; -import io.seata.common.exception.StoreException; -import io.seata.common.executor.Initialize; -import io.seata.common.loader.LoadLevel; -import io.seata.common.loader.Scope; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; -import io.seata.server.session.AbstractSessionManager; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.storage.db.store.DataBaseTransactionStoreManager; -import io.seata.server.store.TransactionStoreManager.LogOperation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The Data base session manager. - * - * @author zhangsen - */ -@LoadLevel(name = "db", scope = Scope.PROTOTYPE) -public class DataBaseSessionManager extends AbstractSessionManager implements Initialize { - - /** - * The constant LOGGER. - */ - protected static final Logger LOGGER = LoggerFactory.getLogger(DataBaseSessionManager.class); - - /** - * Instantiates a new Data base session manager. - */ - public DataBaseSessionManager() { - super(); - } - - @Override - public void init() { - transactionStoreManager = DataBaseTransactionStoreManager.getInstance(); - } - - @Override - public void addGlobalSession(GlobalSession session) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_ADD, session); - if (!ret) { - throw new StoreException("addGlobalSession failed."); - } - - } - - @Override - public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException { - try { - // set expected status threadlocal - session.setExpectedStatusFromCurrent(); - session.setStatus(status); - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_UPDATE, session); - if (!ret) { - throw new StoreException("updateGlobalSessionStatus failed."); - } - } - finally { - // remove expected status threadlocal - session.cleanExpectedStatus(); - } - } - - /** - * remove globalSession 1. rootSessionManager remove normal globalSession 2. - * retryCommitSessionManager and retryRollbackSessionManager remove retry expired - * globalSession - * @param session the session - * @throws TransactionException the transaction exception - */ - @Override - public void removeGlobalSession(GlobalSession session) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_REMOVE, session); - if (!ret) { - throw new StoreException("removeGlobalSession failed."); - } - } - - @Override - public void addBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_ADD, session); - if (!ret) { - throw new StoreException("addBranchSession failed."); - } - } - - @Override - public void updateBranchSessionStatus(BranchSession session, BranchStatus status) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_UPDATE, session); - if (!ret) { - throw new StoreException("updateBranchSessionStatus failed."); - } - } - - @Override - public void removeBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_REMOVE, session); - if (!ret) { - throw new StoreException("removeBranchSession failed."); - } - } - - @Override - public GlobalSession findGlobalSession(String xid) { - return this.findGlobalSession(xid, true); - } - - @Override - public GlobalSession findGlobalSession(String xid, boolean withBranchSessions) { - return transactionStoreManager.readSession(xid, withBranchSessions); - } - - @Override - public Collection allSessions() { - // all data - return findGlobalSessions(new SessionCondition(GlobalStatus.UnKnown, GlobalStatus.Begin, - GlobalStatus.Committing, GlobalStatus.CommitRetrying, GlobalStatus.Rollbacking, - GlobalStatus.RollbackRetrying, GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbackRetrying, - GlobalStatus.AsyncCommitting)); - } - - @Override - public List findGlobalSessions(SessionCondition condition) { - // nothing need to do - return transactionStoreManager.readSession(condition); - } - - @Override - public T lockAndExecute(GlobalSession globalSession, GlobalSession.LockCallable lockCallable) - throws TransactionException { - return lockCallable.call(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java deleted file mode 100644 index 97d4e5d93e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.db.store; - -import io.seata.common.exception.StoreException; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.model.GlobalStatus; -import io.seata.core.store.BranchTransactionDO; -import io.seata.core.store.GlobalTransactionDO; -import io.seata.core.store.LogStore; -import io.seata.core.store.db.DataSourceProvider; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.storage.SessionConverter; -import io.seata.server.store.AbstractTransactionStoreManager; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager; -import lombok.Setter; - -import javax.sql.DataSource; -import java.util.*; -import java.util.stream.Collectors; - -import static io.seata.common.DefaultValues.DEFAULT_QUERY_LIMIT; - -/** - * The type Database transaction store manager. - * - * @author zhangsen - */ -@Setter -public class DataBaseTransactionStoreManager extends AbstractTransactionStoreManager - implements TransactionStoreManager { - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - private static volatile DataBaseTransactionStoreManager instance; - - /** - * The Log store. -- SETTER -- Sets log store. - * @param logStore the log store - */ - protected LogStore logStore; - - /** - * The Log query limit. -- SETTER -- Sets log query limit. - * @param logQueryLimit the log query limit - */ - protected int logQueryLimit; - - /** - * Instantiates a new Database transaction store manager. - */ - private DataBaseTransactionStoreManager() { - logQueryLimit = CONFIG.getInt(ConfigurationKeys.STORE_DB_LOG_QUERY_LIMIT, DEFAULT_QUERY_LIMIT); - String datasourceType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); - // init dataSource - DataSource logStoreDataSource = EnhancedServiceLoader.load(DataSourceProvider.class, datasourceType).provide(); - logStore = new LogStoreDataBaseDAO(logStoreDataSource); - } - - /** - * Get the instance. - */ - public static DataBaseTransactionStoreManager getInstance() { - if (instance == null) { - synchronized (DataBaseTransactionStoreManager.class) { - if (instance == null) { - instance = new DataBaseTransactionStoreManager(); - } - } - } - return instance; - } - - @Override - public boolean writeSession(LogOperation logOperation, SessionStorable session) { - if (LogOperation.GLOBAL_ADD.equals(logOperation)) { - return logStore.insertGlobalTransactionDO(SessionConverter.convertGlobalTransactionDO(session)); - } - else if (LogOperation.GLOBAL_UPDATE.equals(logOperation)) { - GlobalSession globalSession = (GlobalSession) session; - if (globalSession.getExpectedStatus() != null) { - return logStore.updateGlobalTransactionDO(SessionConverter.convertGlobalTransactionDO(session), - globalSession.getExpectedStatus().getCode()); - } - else { - return logStore.updateGlobalTransactionDO(SessionConverter.convertGlobalTransactionDO(session)); - } - } - else if (LogOperation.GLOBAL_REMOVE.equals(logOperation)) { - return logStore.deleteGlobalTransactionDO(SessionConverter.convertGlobalTransactionDO(session)); - } - else if (LogOperation.BRANCH_ADD.equals(logOperation)) { - return logStore.insertBranchTransactionDO(SessionConverter.convertBranchTransactionDO(session)); - } - else if (LogOperation.BRANCH_UPDATE.equals(logOperation)) { - return logStore.updateBranchTransactionDO(SessionConverter.convertBranchTransactionDO(session)); - } - else if (LogOperation.BRANCH_REMOVE.equals(logOperation)) { - return logStore.deleteBranchTransactionDO(SessionConverter.convertBranchTransactionDO(session)); - } - else { - throw new StoreException("Unknown LogOperation:" + logOperation.name()); - } - } - - /** - * Read session global session. - * @param transactionId the transaction id - * @return the global session - */ - public GlobalSession readSession(Long transactionId) { - // global transaction - GlobalTransactionDO globalTransactionDO = logStore.queryGlobalTransactionDO(transactionId); - if (globalTransactionDO == null) { - return null; - } - // branch transactions - List branchTransactionDOs = logStore - .queryBranchTransactionDO(globalTransactionDO.getXid()); - return getGlobalSession(globalTransactionDO, branchTransactionDOs); - } - - /** - * Read session global session. - * @param xid the xid - * @return the global session - */ - @Override - public GlobalSession readSession(String xid) { - return this.readSession(xid, true); - } - - /** - * Read session global session. - * @param xid the xid - * @param withBranchSessions the withBranchSessions - * @return the global session - */ - @Override - public GlobalSession readSession(String xid, boolean withBranchSessions) { - // global transaction - GlobalTransactionDO globalTransactionDO = logStore.queryGlobalTransactionDO(xid); - if (globalTransactionDO == null) { - return null; - } - // branch transactions - List branchTransactionDOs = null; - // reduce rpc with db when branchRegister and getGlobalStatus - if (withBranchSessions) { - branchTransactionDOs = logStore.queryBranchTransactionDO(globalTransactionDO.getXid()); - } - return getGlobalSession(globalTransactionDO, branchTransactionDOs); - } - - @Override - public List readSortByTimeoutBeginSessions(boolean withBranchSessions) { - return readSession(new GlobalStatus[] { GlobalStatus.Begin }, withBranchSessions); - } - - /** - * Read session list. - * @param statuses the statuses - * @return the list - */ - @Override - public List readSession(GlobalStatus[] statuses, boolean withBranchSessions) { - int[] states = new int[statuses.length]; - for (int i = 0; i < statuses.length; i++) { - states[i] = statuses[i].getCode(); - } - // global transaction - List globalTransactionDOs = logStore.queryGlobalTransactionDO(states, logQueryLimit); - Map> branchTransactionDOsMap = Collections.emptyMap(); - if (CollectionUtils.isNotEmpty(globalTransactionDOs)) { - List xids = globalTransactionDOs.stream() - .map(GlobalTransactionDO::getXid) - .collect(Collectors.toList()); - if (withBranchSessions) { - List branchTransactionDOs = logStore.queryBranchTransactionDO(xids); - branchTransactionDOsMap = branchTransactionDOs.stream() - .collect(Collectors.groupingBy(BranchTransactionDO::getXid, LinkedHashMap::new, - Collectors.toList())); - } - } - Map> finalBranchTransactionDOsMap = branchTransactionDOsMap; - return globalTransactionDOs.stream() - .map(globalTransactionDO -> getGlobalSession(globalTransactionDO, - finalBranchTransactionDOsMap.get(globalTransactionDO.getXid()), withBranchSessions)) - .collect(Collectors.toList()); - } - - @Override - public List readSession(SessionCondition sessionCondition) { - if (StringUtils.isNotBlank(sessionCondition.getXid())) { - GlobalSession globalSession = readSession(sessionCondition.getXid()); - if (globalSession != null) { - List globalSessions = new ArrayList<>(); - globalSessions.add(globalSession); - return globalSessions; - } - } - else if (sessionCondition.getTransactionId() != null) { - GlobalSession globalSession = readSession(sessionCondition.getTransactionId()); - if (globalSession != null) { - List globalSessions = new ArrayList<>(); - globalSessions.add(globalSession); - return globalSessions; - } - } - else if (CollectionUtils.isNotEmpty(sessionCondition.getStatuses())) { - return readSession(sessionCondition.getStatuses(), !sessionCondition.isLazyLoadBranch()); - } - return null; - } - - private GlobalSession getGlobalSession(GlobalTransactionDO globalTransactionDO, - List branchTransactionDOs) { - return getGlobalSession(globalTransactionDO, branchTransactionDOs, true); - } - - private GlobalSession getGlobalSession(GlobalTransactionDO globalTransactionDO, - List branchTransactionDOs, boolean withBranchSessions) { - GlobalSession globalSession = SessionConverter.convertGlobalSession(globalTransactionDO, !withBranchSessions); - // branch transactions - if (CollectionUtils.isNotEmpty(branchTransactionDOs)) { - for (BranchTransactionDO branchTransactionDO : branchTransactionDOs) { - globalSession.add(SessionConverter.convertBranchSession(branchTransactionDO)); - } - } - return globalSession; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java deleted file mode 100644 index 76ad4d7c37..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java +++ /dev/null @@ -1,667 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.db.store; - -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import javax.sql.DataSource; - -import io.seata.common.exception.DataAccessException; -import io.seata.common.exception.StoreException; -import io.seata.common.util.IOUtil; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.constants.ServerTableColumnsName; -import io.seata.core.store.BranchTransactionDO; -import io.seata.core.store.GlobalTransactionDO; -import io.seata.core.store.LogStore; -import io.seata.core.store.db.sql.log.LogStoreSqlsFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static io.seata.common.DefaultValues.DEFAULT_STORE_DB_BRANCH_TABLE; -import static io.seata.common.DefaultValues.DEFAULT_STORE_DB_GLOBAL_TABLE; - -/** - * The type Log store data base dao. - * - * @author zhangsen - */ -public class LogStoreDataBaseDAO implements LogStore { - - private static final Logger LOGGER = LoggerFactory.getLogger(LogStoreDataBaseDAO.class); - - /** - * The transaction name key - */ - private static final String TRANSACTION_NAME_KEY = "TRANSACTION_NAME"; - - /** - * The transaction name default size is 128 - */ - private static final int TRANSACTION_NAME_DEFAULT_SIZE = 128; - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The Log store data source. - */ - protected DataSource logStoreDataSource = null; - - /** - * The Global table. - */ - protected String globalTable; - - /** - * The Branch table. - */ - protected String branchTable; - - private String dbType; - - private int transactionNameColumnSize = TRANSACTION_NAME_DEFAULT_SIZE; - - /** - * Instantiates a new Log store data base dao. - * @param logStoreDataSource the log store data source - */ - public LogStoreDataBaseDAO(DataSource logStoreDataSource) { - this.logStoreDataSource = logStoreDataSource; - globalTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_GLOBAL_TABLE, DEFAULT_STORE_DB_GLOBAL_TABLE); - branchTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_BRANCH_TABLE, DEFAULT_STORE_DB_BRANCH_TABLE); - dbType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE); - if (StringUtils.isBlank(dbType)) { - throw new StoreException("there must be db type."); - } - if (logStoreDataSource == null) { - throw new StoreException("there must be logStoreDataSource."); - } - // init transaction_name size - initTransactionNameSize(); - } - - @Override - public GlobalTransactionDO queryGlobalTransactionDO(String xid) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryGlobalTransactionSQL(globalTable); - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(1, xid); - rs = ps.executeQuery(); - if (rs.next()) { - return convertGlobalTransactionDO(rs); - } - else { - return null; - } - } - catch (SQLException e) { - throw new DataAccessException(e); - } - finally { - IOUtil.close(rs, ps, conn); - } - } - - @Override - public GlobalTransactionDO queryGlobalTransactionDO(long transactionId) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType) - .getQueryGlobalTransactionSQLByTransactionId(globalTable); - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setLong(1, transactionId); - rs = ps.executeQuery(); - if (rs.next()) { - return convertGlobalTransactionDO(rs); - } - else { - return null; - } - } - catch (SQLException e) { - throw new DataAccessException(e); - } - finally { - IOUtil.close(rs, ps, conn); - } - } - - @Override - public List queryGlobalTransactionDO(int[] statuses, int limit) { - List ret = new ArrayList<>(); - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - - String paramsPlaceHolder = org.apache.commons.lang.StringUtils.repeat("?", ",", statuses.length); - - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType) - .getQueryGlobalTransactionSQLByStatus(globalTable, paramsPlaceHolder); - ps = conn.prepareStatement(sql); - for (int i = 0; i < statuses.length; i++) { - int status = statuses[i]; - ps.setInt(i + 1, status); - } - ps.setInt(statuses.length + 1, limit); - - // modify for the change of limit position in sqlserver - if ("sqlserver".equalsIgnoreCase(dbType)) { - ps.setInt(1, limit); - ps.setInt(statuses.length + 1, statuses[0]); - } - rs = ps.executeQuery(); - while (rs.next()) { - ret.add(convertGlobalTransactionDO(rs)); - } - return ret; - } - catch (SQLException e) { - throw new DataAccessException(e); - } - finally { - IOUtil.close(rs, ps, conn); - } - } - - @Override - public boolean insertGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getInsertGlobalTransactionSQL(globalTable); - Connection conn = null; - PreparedStatement ps = null; - try { - int index = 1; - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(index++, globalTransactionDO.getXid()); - ps.setLong(index++, globalTransactionDO.getTransactionId()); - ps.setInt(index++, globalTransactionDO.getStatus()); - ps.setString(index++, globalTransactionDO.getApplicationId()); - ps.setString(index++, globalTransactionDO.getTransactionServiceGroup()); - String transactionName = globalTransactionDO.getTransactionName(); - transactionName = transactionName.length() > transactionNameColumnSize - ? transactionName.substring(0, transactionNameColumnSize) : transactionName; - ps.setString(index++, transactionName); - ps.setInt(index++, globalTransactionDO.getTimeout()); - ps.setLong(index++, globalTransactionDO.getBeginTime()); - ps.setString(index++, globalTransactionDO.getApplicationData()); - return ps.executeUpdate() > 0; - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - } - - @Override - public boolean updateGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getUpdateGlobalTransactionStatusSQL(globalTable); - Connection conn = null; - PreparedStatement ps = null; - try { - int index = 1; - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setInt(index++, globalTransactionDO.getStatus()); - ps.setString(index++, globalTransactionDO.getXid()); - return ps.executeUpdate() > 0; - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - } - - @Override - public boolean updateGlobalTransactionDO(GlobalTransactionDO globalTransactionDO, Integer expectedStatus) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType) - .getUpdateGlobalTransactionStatusByStatusSQL(globalTable); - Connection conn = null; - PreparedStatement ps = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setInt(1, globalTransactionDO.getStatus()); - ps.setString(2, globalTransactionDO.getXid()); - ps.setInt(3, expectedStatus); - return ps.executeUpdate() > 0; - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - } - - @Override - public boolean deleteGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getDeleteGlobalTransactionSQL(globalTable); - Connection conn = null; - PreparedStatement ps = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(1, globalTransactionDO.getXid()); - ps.executeUpdate(); - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - return true; - } - - @Override - public List queryBranchTransactionDO(String xid) { - List rets = new ArrayList<>(); - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryBranchTransaction(branchTable); - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - - ps = conn.prepareStatement(sql); - ps.setString(1, xid); - - rs = ps.executeQuery(); - while (rs.next()) { - rets.add(convertBranchTransactionDO(rs)); - } - return rets; - } - catch (SQLException e) { - throw new DataAccessException(e); - } - finally { - IOUtil.close(rs, ps, conn); - } - } - - @Override - public List queryBranchTransactionDO(List xids) { - int length = xids.size(); - List rets = new ArrayList<>(length * 3); - String paramsPlaceHolder = org.apache.commons.lang.StringUtils.repeat("?", ",", length); - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType) - .getQueryBranchTransaction(branchTable, paramsPlaceHolder); - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - for (int i = 0; i < length; i++) { - ps.setString(i + 1, xids.get(i)); - } - rs = ps.executeQuery(); - while (rs.next()) { - rets.add(convertBranchTransactionDO(rs)); - } - return rets; - } - catch (SQLException e) { - throw new DataAccessException(e); - } - finally { - IOUtil.close(rs, ps, conn); - } - } - - @Override - public boolean insertBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getInsertBranchTransactionSQL(branchTable); - Connection conn = null; - PreparedStatement ps = null; - try { - int index = 1; - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(index++, branchTransactionDO.getXid()); - ps.setLong(index++, branchTransactionDO.getTransactionId()); - ps.setLong(index++, branchTransactionDO.getBranchId()); - ps.setString(index++, branchTransactionDO.getResourceGroupId()); - ps.setString(index++, branchTransactionDO.getResourceId()); - ps.setString(index++, branchTransactionDO.getBranchType()); - ps.setInt(index++, branchTransactionDO.getStatus()); - ps.setString(index++, branchTransactionDO.getClientId()); - ps.setString(index++, branchTransactionDO.getApplicationData()); - return ps.executeUpdate() > 0; - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - } - - @Override - public boolean updateBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - boolean shouldUpdateAppData = StringUtils.isNotBlank(branchTransactionDO.getApplicationData()); - String sql = shouldUpdateAppData - ? LogStoreSqlsFactory.getLogStoreSqls(dbType).getUpdateBranchTransactionStatusAppDataSQL(branchTable) - : LogStoreSqlsFactory.getLogStoreSqls(dbType).getUpdateBranchTransactionStatusSQL(branchTable); - Connection conn = null; - PreparedStatement ps = null; - try { - int index = 1; - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setInt(index++, branchTransactionDO.getStatus()); - if (shouldUpdateAppData) { - ps.setString(index++, branchTransactionDO.getApplicationData()); - } - ps.setString(index++, branchTransactionDO.getXid()); - ps.setLong(index++, branchTransactionDO.getBranchId()); - return ps.executeUpdate() > 0; - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - } - - @Override - public boolean deleteBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getDeleteBranchTransactionByBranchIdSQL(branchTable); - Connection conn = null; - PreparedStatement ps = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(1, branchTransactionDO.getXid()); - ps.setLong(2, branchTransactionDO.getBranchId()); - ps.executeUpdate(); - } - catch (SQLException e) { - throw new StoreException(e); - } - finally { - IOUtil.close(ps, conn); - } - return true; - } - - @Override - public long getCurrentMaxSessionId(long high, long low) { - String transMaxSql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryGlobalMax(globalTable); - String branchMaxSql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryBranchMax(branchTable); - long maxTransId = getCurrentMaxSessionId(transMaxSql, high, low); - long maxBranchId = getCurrentMaxSessionId(branchMaxSql, high, low); - return Math.max(maxBranchId, maxTransId); - } - - private long getCurrentMaxSessionId(String sql, long high, long low) { - long max = 0; - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - int index = 1; - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setLong(index++, high); - ps.setLong(index++, low); - - rs = ps.executeQuery(); - while (rs.next()) { - max = rs.getLong(1); - } - } - catch (SQLException e) { - throw new DataAccessException(e); - } - finally { - IOUtil.close(rs, ps, conn); - } - return max; - } - - private GlobalTransactionDO convertGlobalTransactionDO(ResultSet rs) throws SQLException { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_XID)); - globalTransactionDO.setStatus(rs.getInt(ServerTableColumnsName.GLOBAL_TABLE_STATUS)); - globalTransactionDO.setApplicationId(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_APPLICATION_ID)); - globalTransactionDO.setBeginTime(rs.getLong(ServerTableColumnsName.GLOBAL_TABLE_BEGIN_TIME)); - globalTransactionDO.setTimeout(rs.getInt(ServerTableColumnsName.GLOBAL_TABLE_TIMEOUT)); - globalTransactionDO.setTransactionId(rs.getLong(ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID)); - globalTransactionDO.setTransactionName(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_NAME)); - globalTransactionDO - .setTransactionServiceGroup(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_SERVICE_GROUP)); - globalTransactionDO.setApplicationData(rs.getString(ServerTableColumnsName.GLOBAL_TABLE_APPLICATION_DATA)); - globalTransactionDO.setGmtCreate(rs.getTimestamp(ServerTableColumnsName.GLOBAL_TABLE_GMT_CREATE)); - globalTransactionDO.setGmtModified(rs.getTimestamp(ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED)); - return globalTransactionDO; - } - - private BranchTransactionDO convertBranchTransactionDO(ResultSet rs) throws SQLException { - BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); - branchTransactionDO.setResourceGroupId(rs.getString(ServerTableColumnsName.BRANCH_TABLE_RESOURCE_GROUP_ID)); - branchTransactionDO.setStatus(rs.getInt(ServerTableColumnsName.BRANCH_TABLE_STATUS)); - branchTransactionDO.setApplicationData(rs.getString(ServerTableColumnsName.BRANCH_TABLE_APPLICATION_DATA)); - branchTransactionDO.setClientId(rs.getString(ServerTableColumnsName.BRANCH_TABLE_CLIENT_ID)); - branchTransactionDO.setXid(rs.getString(ServerTableColumnsName.BRANCH_TABLE_XID)); - branchTransactionDO.setResourceId(rs.getString(ServerTableColumnsName.BRANCH_TABLE_RESOURCE_ID)); - branchTransactionDO.setBranchId(rs.getLong(ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID)); - branchTransactionDO.setBranchType(rs.getString(ServerTableColumnsName.BRANCH_TABLE_BRANCH_TYPE)); - branchTransactionDO.setTransactionId(rs.getLong(ServerTableColumnsName.BRANCH_TABLE_TRANSACTION_ID)); - branchTransactionDO.setGmtCreate(rs.getTimestamp(ServerTableColumnsName.BRANCH_TABLE_GMT_CREATE)); - branchTransactionDO.setGmtModified(rs.getTimestamp(ServerTableColumnsName.BRANCH_TABLE_GMT_MODIFIED)); - return branchTransactionDO; - } - - /** - * the public modifier only for test - */ - public void initTransactionNameSize() { - ColumnInfo columnInfo = queryTableStructure(globalTable, TRANSACTION_NAME_KEY); - if (columnInfo == null) { - LOGGER.warn("{} table or {} column not found", globalTable, TRANSACTION_NAME_KEY); - return; - } - this.transactionNameColumnSize = columnInfo.getColumnSize(); - } - - /** - * query column info from table - * @param tableName the table name - * @param colName the column name - * @return the column info - */ - private ColumnInfo queryTableStructure(final String tableName, String colName) { - try (Connection conn = logStoreDataSource.getConnection()) { - DatabaseMetaData dbmd = conn.getMetaData(); - String schema = getSchema(conn); - ResultSet tableRs = dbmd.getTables(null, schema, "%", new String[] { "TABLE" }); - while (tableRs.next()) { - String table = tableRs.getString("TABLE_NAME"); - if (StringUtils.equalsIgnoreCase(table, tableName)) { - ResultSet columnRs = conn.getMetaData().getColumns(null, schema, table, null); - while (columnRs.next()) { - ColumnInfo info = new ColumnInfo(); - String columnName = columnRs.getString("COLUMN_NAME"); - info.setColumnName(columnName); - String typeName = columnRs.getString("TYPE_NAME"); - info.setTypeName(typeName); - int columnSize = columnRs.getInt("COLUMN_SIZE"); - info.setColumnSize(columnSize); - String remarks = columnRs.getString("REMARKS"); - info.setRemarks(remarks); - if (StringUtils.equalsIgnoreCase(columnName, colName)) { - return info; - } - } - break; - } - } - } - catch (SQLException e) { - LOGGER.error("query transaction_name size fail, {}", e.getMessage(), e); - } - return null; - } - - private String getSchema(Connection conn) throws SQLException { - if ("h2".equalsIgnoreCase(dbType)) { - return null; - } - else if ("postgresql".equalsIgnoreCase(dbType)) { - String sql = "select current_schema"; - try (PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { - String schema = null; - if (rs.next()) { - schema = rs.getString(1); - } - return schema; - } - catch (SQLException e) { - throw new StoreException(e); - } - } - else if ("sqlserver".equalsIgnoreCase(dbType)) { - return conn.getSchema(); - } - else { - return conn.getMetaData().getUserName(); - } - } - - /** - * Sets log store data source. - * @param logStoreDataSource the log store data source - */ - public void setLogStoreDataSource(DataSource logStoreDataSource) { - this.logStoreDataSource = logStoreDataSource; - } - - /** - * Sets global table. - * @param globalTable the global table - */ - public void setGlobalTable(String globalTable) { - this.globalTable = globalTable; - } - - /** - * Sets branch table. - * @param branchTable the branch table - */ - public void setBranchTable(String branchTable) { - this.branchTable = branchTable; - } - - /** - * Sets db type. - * @param dbType the db type - */ - public void setDbType(String dbType) { - this.dbType = dbType; - } - - public int getTransactionNameColumnSize() { - return transactionNameColumnSize; - } - - /** - * column info - */ - private static class ColumnInfo { - - private String columnName; - - private String typeName; - - private int columnSize; - - private String remarks; - - public String getColumnName() { - return columnName; - } - - public void setColumnName(String columnName) { - this.columnName = columnName; - } - - public String getTypeName() { - return typeName; - } - - public void setTypeName(String typeName) { - this.typeName = typeName; - } - - public int getColumnSize() { - return columnSize; - } - - public void setColumnSize(int columnSize) { - this.columnSize = columnSize; - } - - public String getRemarks() { - return remarks; - } - - public void setRemarks(String remarks) { - this.remarks = remarks; - } - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/FlushDiskMode.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/FlushDiskMode.java deleted file mode 100644 index cab554b167..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/FlushDiskMode.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.file; - -/** - * @author lizhao - */ -public enum FlushDiskMode { - - /** - * sync flush disk - */ - SYNC_MODEL("sync"), - /** - * async flush disk - */ - ASYNC_MODEL("async"); - - private String modeStr; - - FlushDiskMode(String modeStr) { - this.modeStr = modeStr; - } - - public static FlushDiskMode findDiskMode(String modeStr) { - if (SYNC_MODEL.modeStr.equals(modeStr)) { - return SYNC_MODEL; - } - return ASYNC_MODEL; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/ReloadableStore.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/ReloadableStore.java deleted file mode 100644 index 90e822bdcf..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/ReloadableStore.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.file; - -import java.util.List; - -/** - * The interface Reloadable store. - * - * @author zhangsen - */ -public interface ReloadableStore { - - /** - * Read write store. - * @param readSize the read size - * @param isHistory the is history - * @return the list - */ - List readWriteStore(int readSize, boolean isHistory); - - /** - * Has remaining boolean. - * @param isHistory the is history - * @return the boolean - */ - boolean hasRemaining(boolean isHistory); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/TransactionWriteStore.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/TransactionWriteStore.java deleted file mode 100644 index 315d21dace..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/TransactionWriteStore.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.file; - -import java.nio.ByteBuffer; - -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager.LogOperation; - -/** - * The type Transaction write store. - * - * @author slievrly - */ -public class TransactionWriteStore implements SessionStorable { - - private SessionStorable sessionRequest; - - private LogOperation operate; - - /** - * Instantiates a new Transaction write store. - * @param sessionRequest the session request - * @param operate the operate - */ - public TransactionWriteStore(SessionStorable sessionRequest, LogOperation operate) { - this.sessionRequest = sessionRequest; - this.operate = operate; - } - - /** - * Instantiates a new Transaction write store. - */ - public TransactionWriteStore() { - } - - /** - * Gets session request. - * @return the session request - */ - public SessionStorable getSessionRequest() { - return sessionRequest; - } - - /** - * Sets session request. - * @param sessionRequest the session request - */ - public void setSessionRequest(SessionStorable sessionRequest) { - this.sessionRequest = sessionRequest; - } - - /** - * Gets operate. - * @return the operate - */ - public LogOperation getOperate() { - return operate; - } - - /** - * Sets operate. - * @param operate the operate - */ - public void setOperate(LogOperation operate) { - this.operate = operate; - } - - @Override - public byte[] encode() { - byte[] bySessionRequest = this.sessionRequest.encode(); - byte byOpCode = this.getOperate().getCode(); - int len = bySessionRequest.length + 1; - byte[] byResult = new byte[len]; - ByteBuffer byteBuffer = ByteBuffer.wrap(byResult); - byteBuffer.put(bySessionRequest); - byteBuffer.put(byOpCode); - return byResult; - } - - @Override - public void decode(byte[] src) { - ByteBuffer byteBuffer = ByteBuffer.wrap(src); - byte[] bySessionRequest = new byte[src.length - 1]; - byteBuffer.get(bySessionRequest); - byte byOpCode = byteBuffer.get(); - this.operate = LogOperation.getLogOperationByCode(byOpCode); - SessionStorable tmpSessionStorable = getSessionInstanceByOperation(this.operate); - tmpSessionStorable.decode(bySessionRequest); - this.sessionRequest = tmpSessionStorable; - } - - private SessionStorable getSessionInstanceByOperation(LogOperation logOperation) { - SessionStorable sessionStorable = null; - switch (logOperation) { - case GLOBAL_ADD: - case GLOBAL_UPDATE: - case GLOBAL_REMOVE: - sessionStorable = new GlobalSession(); - break; - case BRANCH_ADD: - case BRANCH_UPDATE: - case BRANCH_REMOVE: - sessionStorable = new BranchSession(); - break; - default: - throw new ShouldNeverHappenException("incorrect logOperation"); - } - return sessionStorable; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/lock/FileLockManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/lock/FileLockManager.java deleted file mode 100644 index 705378d6dc..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/lock/FileLockManager.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.file.lock; - -import java.util.List; - -import io.seata.common.loader.LoadLevel; -import io.seata.core.exception.TransactionException; -import io.seata.core.lock.Locker; -import io.seata.server.lock.AbstractLockManager; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.storage.raft.lock.RaftLockManager; -import org.slf4j.MDC; - -import static io.seata.core.context.RootContext.MDC_KEY_BRANCH_ID; - -/** - * The type file lock manager. - * - * @author zhangsen - */ -@LoadLevel(name = "file") -public class FileLockManager extends AbstractLockManager { - - @Override - public Locker getLocker(BranchSession branchSession) { - return new FileLocker(branchSession); - } - - @Override - public boolean releaseGlobalSessionLock(GlobalSession globalSession) throws TransactionException { - List branchSessions = globalSession.getBranchSessions(); - boolean releaseLockResult = true; - for (BranchSession branchSession : branchSessions) { - try { - MDC.put(MDC_KEY_BRANCH_ID, String.valueOf(branchSession.getBranchId())); - releaseLockResult = this instanceof RaftLockManager ? super.releaseLock(branchSession) - : this.releaseLock(branchSession); - } - finally { - MDC.remove(MDC_KEY_BRANCH_ID); - } - } - return releaseLockResult; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/lock/FileLocker.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/lock/FileLocker.java deleted file mode 100644 index 0a9760422f..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/lock/FileLocker.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.file.lock; - -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import io.seata.common.exception.FrameworkException; -import io.seata.common.exception.StoreException; -import io.seata.common.util.CollectionUtils; -import io.seata.core.exception.BranchTransactionException; -import io.seata.core.exception.TransactionException; -import io.seata.core.lock.AbstractLocker; -import io.seata.core.lock.RowLock; -import io.seata.core.model.LockStatus; -import io.seata.server.session.BranchSession; - -import static io.seata.core.exception.TransactionExceptionCode.LockKeyConflictFailFast; - -/** - * The type Memory locker. - * - * @author zhangsen - */ -public class FileLocker extends AbstractLocker { - - private static final int BUCKET_PER_TABLE = 128; - - private static final ConcurrentMap>> LOCK_MAP = new ConcurrentHashMap<>(); - - /** - * The Branch session. - */ - protected BranchSession branchSession; - - /** - * Instantiates a new Memory locker. - * @param branchSession the branch session - */ - public FileLocker(BranchSession branchSession) { - this.branchSession = branchSession; - } - - @Override - public boolean acquireLock(List rowLocks) { - return acquireLock(rowLocks, true, false); - } - - @Override - public boolean acquireLock(List rowLocks, boolean autoCommit, boolean skipCheckLock) { - if (CollectionUtils.isEmpty(rowLocks)) { - // no lock - return true; - } - String resourceId = branchSession.getResourceId(); - long transactionId = branchSession.getTransactionId(); - - Map> bucketHolder = branchSession.getLockHolder(); - Map> dbLockMap = CollectionUtils.computeIfAbsent(LOCK_MAP, - resourceId, key -> new ConcurrentHashMap<>(8)); - boolean failFast = false; - boolean canLock = true; - for (RowLock lock : rowLocks) { - String tableName = lock.getTableName(); - String pk = lock.getPk(); - ConcurrentMap tableLockMap = CollectionUtils.computeIfAbsent(dbLockMap, tableName, - key -> new ConcurrentHashMap<>(8)); - - int bucketId = pk.hashCode() % BUCKET_PER_TABLE; - BucketLockMap bucketLockMap = CollectionUtils.computeIfAbsent(tableLockMap, bucketId, - key -> new BucketLockMap()); - BranchSession previousLockBranchSession = bucketLockMap.get().putIfAbsent(pk, branchSession); - if (previousLockBranchSession == null) { - // No existing lock, and now locked by myself - Set keysInHolder = CollectionUtils.computeIfAbsent(bucketHolder, bucketLockMap, - key -> ConcurrentHashMap.newKeySet()); - keysInHolder.add(pk); - } - else if (previousLockBranchSession.getTransactionId() == transactionId) { - // Locked by me before - } - else { - LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " - + previousLockBranchSession.getBranchId()); - try { - // Release all acquired locks. - branchSession.unlock(); - } - catch (TransactionException e) { - throw new FrameworkException(e); - } - if (!autoCommit && previousLockBranchSession.getLockStatus() == LockStatus.Rollbacking) { - failFast = true; - break; - } - if (canLock) { - canLock = false; - if (autoCommit) { - break; - } - } - } - } - if (failFast) { - throw new StoreException(new BranchTransactionException(LockKeyConflictFailFast)); - } - return canLock; - } - - @Override - public boolean releaseLock(List rowLock) { - if (CollectionUtils.isEmpty(rowLock)) { - // no lock - return true; - } - Map> lockHolder = branchSession.getLockHolder(); - if (CollectionUtils.isEmpty(lockHolder)) { - return true; - } - lockHolder.forEach((bucket, keys) -> { - for (String key : keys) { - // remove lock only if it locked by myself - bucket.get().remove(key, branchSession); - } - }); - lockHolder.clear(); - return true; - } - - @Override - public boolean isLockable(List rowLocks) { - if (CollectionUtils.isEmpty(rowLocks)) { - // no lock - return true; - } - Long transactionId = rowLocks.get(0).getTransactionId(); - String resourceId = rowLocks.get(0).getResourceId(); - ConcurrentMap> dbLockMap = LOCK_MAP.get(resourceId); - if (dbLockMap == null) { - return true; - } - for (RowLock rowLock : rowLocks) { - String tableName = rowLock.getTableName(); - String pk = rowLock.getPk(); - - ConcurrentMap tableLockMap = dbLockMap.get(tableName); - if (tableLockMap == null) { - continue; - } - int bucketId = pk.hashCode() % BUCKET_PER_TABLE; - BucketLockMap bucketLockMap = tableLockMap.get(bucketId); - if (bucketLockMap == null) { - continue; - } - BranchSession branchSession = bucketLockMap.get().get(pk); - Long lockingTransactionId = branchSession != null ? branchSession.getTransactionId() : null; - if (lockingTransactionId == null || lockingTransactionId.longValue() == transactionId) { - // Locked by me - continue; - } - else { - LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); - return false; - } - } - return true; - } - - @Override - public void updateLockStatus(String xid, LockStatus lockStatus) { - } - - @Override - public void cleanAllLocks() { - LOCK_MAP.clear(); - } - - /** - * Because bucket lock map will be key of HashMap(lockHolder), however - * {@link ConcurrentHashMap} overwrites {@link Object#hashCode()} and - * {@link Object#equals(Object)}, that leads to hash key conflict in lockHolder. We - * define a {@link BucketLockMap} to hold the ConcurrentHashMap(bucketLockMap) and - * replace it as key of HashMap(lockHolder). - */ - public static class BucketLockMap { - - private final ConcurrentHashMap bucketLockMap = new ConcurrentHashMap<>(); - - ConcurrentHashMap get() { - return bucketLockMap; - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) { - return super.equals(o); - } - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java deleted file mode 100644 index 51b165f8db..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.file.session; - -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Arrays; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.loader.LoadLevel; -import io.seata.common.loader.Scope; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.GlobalStatus; -import io.seata.server.session.AbstractSessionManager; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.Reloadable; -import io.seata.server.session.SessionCondition; -import io.seata.server.storage.file.ReloadableStore; -import io.seata.server.storage.file.TransactionWriteStore; -import io.seata.server.storage.file.store.FileTransactionStoreManager; -import io.seata.server.store.AbstractTransactionStoreManager; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager; - -import static io.seata.common.DefaultValues.DEFAULT_SERVICE_SESSION_RELOAD_READ_SIZE; - -/** - * The type File based session manager. - * - * @author slievrly - */ -@LoadLevel(name = "file", scope = Scope.PROTOTYPE) -public class FileSessionManager extends AbstractSessionManager implements Reloadable { - - private static final int READ_SIZE = ConfigurationFactory.getInstance() - .getInt(ConfigurationKeys.SERVICE_SESSION_RELOAD_READ_SIZE, DEFAULT_SERVICE_SESSION_RELOAD_READ_SIZE); - - /** - * The Session map. - */ - private Map sessionMap = new ConcurrentHashMap<>(64); - - /** - * Instantiates a new File based session manager. - * @param name the name - */ - public FileSessionManager(String name) { - super(name); - transactionStoreManager = new AbstractTransactionStoreManager() { - @Override - public boolean writeSession(LogOperation logOperation, SessionStorable session) { - return true; - } - }; - } - - /** - * Instantiates a new File based session manager. - * @param name the name - * @param sessionStoreFilePath the session store file path - * @throws IOException the io exception - */ - public FileSessionManager(String name, String sessionStoreFilePath) throws IOException { - super(name); - if (StringUtils.isNotBlank(sessionStoreFilePath)) { - transactionStoreManager = new FileTransactionStoreManager(sessionStoreFilePath + File.separator + name, - this); - } - else { - transactionStoreManager = new AbstractTransactionStoreManager() { - @Override - public boolean writeSession(LogOperation logOperation, SessionStorable session) { - return true; - } - }; - } - } - - @Override - public void reload() { - restoreSessions(); - } - - @Override - public void addGlobalSession(GlobalSession session) throws TransactionException { - CollectionUtils.computeIfAbsent(sessionMap, session.getXid(), k -> { - try { - super.addGlobalSession(session); - } - catch (TransactionException e) { - LOGGER.error("addGlobalSession fail, msg: {}", e.getMessage()); - } - return session; - }); - } - - @Override - public GlobalSession findGlobalSession(String xid) { - return sessionMap.get(xid); - } - - @Override - public GlobalSession findGlobalSession(String xid, boolean withBranchSessions) { - // withBranchSessions without process in memory - return sessionMap.get(xid); - } - - @Override - public void removeGlobalSession(GlobalSession session) throws TransactionException { - if (sessionMap.remove(session.getXid()) != null) { - super.removeGlobalSession(session); - } - } - - @Override - public Collection allSessions() { - return sessionMap.values(); - } - - @Override - public List findGlobalSessions(SessionCondition condition) { - List globalStatuses = null; - if (null != condition.getStatuses() && condition.getStatuses().length > 0) { - globalStatuses = Arrays.asList(condition.getStatuses()); - } - Collection list = sessionMap.values(); - List finalGlobalStatuses = globalStatuses; - return list.parallelStream().filter(globalSession -> { - - if (null != condition.getOverTimeAliveMills() && condition.getOverTimeAliveMills() > 0) { - if (System.currentTimeMillis() - globalSession.getBeginTime() <= condition.getOverTimeAliveMills()) { - return false; - } - } - - if (!StringUtils.isEmpty(condition.getXid())) { - // Only one will be found, just add and return - return Objects.equals(condition.getXid(), globalSession.getXid()); - } - - if (null != condition.getTransactionId() && condition.getTransactionId() > 0) { - // Only one will be found, just add and return - return Objects.equals(condition.getTransactionId(), globalSession.getTransactionId()); - } - - if (null != finalGlobalStatuses) { - return finalGlobalStatuses.contains(globalSession.getStatus()); - } - // All test pass, add to resp - return true; - }).collect(Collectors.toList()); - } - - @Override - public T lockAndExecute(GlobalSession globalSession, GlobalSession.LockCallable lockCallable) - throws TransactionException { - globalSession.lock(); - try { - return lockCallable.call(); - } - finally { - globalSession.unlock(); - } - } - - private void restoreSessions() { - final Set removedGlobalBuffer = new HashSet<>(); - final Map> unhandledBranchBuffer = new HashMap<>(); - - restoreSessions(true, removedGlobalBuffer, unhandledBranchBuffer); - restoreSessions(false, removedGlobalBuffer, unhandledBranchBuffer); - - if (!unhandledBranchBuffer.isEmpty()) { - unhandledBranchBuffer.values().forEach(unhandledBranchSessions -> { - unhandledBranchSessions.values().forEach(branchSession -> { - String xid = branchSession.getXid(); - if (removedGlobalBuffer.contains(xid)) { - return; - } - - long bid = branchSession.getBranchId(); - GlobalSession found = sessionMap.get(xid); - if (found == null) { - // Ignore - if (LOGGER.isInfoEnabled()) { - LOGGER.info("GlobalSession Does Not Exists For BranchSession [" + bid + "/" + xid + "]"); - } - } - else { - BranchSession existingBranch = found.getBranch(branchSession.getBranchId()); - if (existingBranch == null) { - found.add(branchSession); - } - else { - existingBranch.setStatus(branchSession.getStatus()); - } - } - }); - }); - } - } - - private boolean checkSessionStatus(GlobalSession globalSession) { - GlobalStatus globalStatus = globalSession.getStatus(); - switch (globalStatus) { - case UnKnown: - case Committed: - case CommitFailed: - case Rollbacked: - case RollbackFailed: - case TimeoutRollbacked: - case TimeoutRollbackFailed: - case RollbackRetryTimeout: - case Finished: - return false; - default: - return true; - } - } - - private void restoreSessions(boolean isHistory, Set removedGlobalBuffer, - Map> unhandledBranchBuffer) { - if (!(transactionStoreManager instanceof ReloadableStore)) { - return; - } - while (((ReloadableStore) transactionStoreManager).hasRemaining(isHistory)) { - List stores = ((ReloadableStore) transactionStoreManager).readWriteStore(READ_SIZE, - isHistory); - restore(stores, removedGlobalBuffer, unhandledBranchBuffer); - } - } - - private void restore(List stores, Set removedGlobalBuffer, - Map> unhandledBranchBuffer) { - for (TransactionWriteStore store : stores) { - TransactionStoreManager.LogOperation logOperation = store.getOperate(); - SessionStorable sessionStorable = store.getSessionRequest(); - switch (logOperation) { - case GLOBAL_ADD: - case GLOBAL_UPDATE: { - GlobalSession globalSession = (GlobalSession) sessionStorable; - if (globalSession.getTransactionId() == 0) { - LOGGER.error("Restore globalSession from file failed, the transactionId is zero , xid:" - + globalSession.getXid()); - break; - } - if (removedGlobalBuffer.contains(globalSession.getXid())) { - break; - } - GlobalSession foundGlobalSession = sessionMap.get(globalSession.getXid()); - if (foundGlobalSession == null) { - if (this.checkSessionStatus(globalSession)) { - sessionMap.put(globalSession.getXid(), globalSession); - } - else { - removedGlobalBuffer.add(globalSession.getXid()); - unhandledBranchBuffer.remove(globalSession.getXid()); - } - } - else { - if (this.checkSessionStatus(globalSession)) { - foundGlobalSession.setStatus(globalSession.getStatus()); - } - else { - sessionMap.remove(globalSession.getXid()); - removedGlobalBuffer.add(globalSession.getXid()); - unhandledBranchBuffer.remove(globalSession.getXid()); - } - } - break; - } - case GLOBAL_REMOVE: { - GlobalSession globalSession = (GlobalSession) sessionStorable; - if (globalSession.getTransactionId() == 0) { - LOGGER.error("Restore globalSession from file failed, the transactionId is zero , xid:" - + globalSession.getXid()); - break; - } - if (removedGlobalBuffer.contains(globalSession.getXid())) { - break; - } - if (sessionMap.remove(globalSession.getXid()) == null) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("GlobalSession To Be Removed Does Not Exists [" + globalSession.getXid() + "]"); - } - } - removedGlobalBuffer.add(globalSession.getXid()); - unhandledBranchBuffer.remove(globalSession.getXid()); - break; - } - case BRANCH_ADD: - case BRANCH_UPDATE: { - BranchSession branchSession = (BranchSession) sessionStorable; - if (branchSession.getTransactionId() == 0) { - LOGGER.error("Restore branchSession from file failed, the transactionId is zero , xid:" - + branchSession.getXid()); - break; - } - if (removedGlobalBuffer.contains(branchSession.getXid())) { - break; - } - GlobalSession foundGlobalSession = sessionMap.get(branchSession.getXid()); - if (foundGlobalSession == null) { - unhandledBranchBuffer.computeIfAbsent(branchSession.getXid(), key -> new HashMap<>()) - .put(branchSession.getBranchId(), branchSession); - } - else { - BranchSession existingBranch = foundGlobalSession.getBranch(branchSession.getBranchId()); - if (existingBranch == null) { - foundGlobalSession.add(branchSession); - } - else { - existingBranch.setStatus(branchSession.getStatus()); - } - } - break; - } - case BRANCH_REMOVE: { - BranchSession branchSession = (BranchSession) sessionStorable; - String xid = branchSession.getXid(); - if (removedGlobalBuffer.contains(xid)) { - break; - } - long bid = branchSession.getBranchId(); - if (branchSession.getTransactionId() == 0) { - LOGGER.error("Restore branchSession from file failed, the transactionId is zero , xid:" - + branchSession.getXid()); - break; - } - GlobalSession found = sessionMap.get(xid); - if (found == null) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("GlobalSession To Be Updated (Remove Branch) Does Not Exists [" + bid + "/" - + xid + "]"); - } - } - else { - BranchSession theBranch = found.getBranch(bid); - if (theBranch == null) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("BranchSession To Be Updated Does Not Exists [" + bid + "/" + xid + "]"); - } - } - else { - found.remove(theBranch); - } - } - break; - } - default: - throw new ShouldNeverHappenException("Unknown Operation: " + logOperation); - } - } - - } - - public Map getSessionMap() { - return sessionMap; - } - - public void setSessionMap(Map sessionMap) { - this.sessionMap = sessionMap; - } - - @Override - public void destroy() { - transactionStoreManager.shutdown(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/store/FileTransactionStoreManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/store/FileTransactionStoreManager.java deleted file mode 100644 index 6dc12e73cc..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/file/store/FileTransactionStoreManager.java +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.file.store; - -import com.alipay.sofa.jraft.util.BufferUtils; -import io.seata.common.exception.StoreException; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.util.CollectionUtils; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.session.SessionManager; -import io.seata.server.storage.file.FlushDiskMode; -import io.seata.server.storage.file.ReloadableStore; -import io.seata.server.storage.file.TransactionWriteStore; -import io.seata.server.store.AbstractTransactionStoreManager; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.StoreConfig; -import io.seata.server.store.TransactionStoreManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.ReentrantLock; - -import static io.seata.core.context.RootContext.MDC_KEY_BRANCH_ID; - -/** - * The type File transaction store manager. - * - * @author slievrly - */ -public class FileTransactionStoreManager extends AbstractTransactionStoreManager - implements TransactionStoreManager, ReloadableStore { - - private static final Logger LOGGER = LoggerFactory.getLogger(FileTransactionStoreManager.class); - - private static final int MAX_THREAD_WRITE = 1; - - private ExecutorService fileWriteExecutor; - - private volatile boolean stopping = false; - - private static final int MAX_SHUTDOWN_RETRY = 3; - - private static final int SHUTDOWN_CHECK_INTERVAL = 1 * 1000; - - private static final int MAX_WRITE_RETRY = 5; - - private static final String HIS_DATA_FILENAME_POSTFIX = ".1"; - - private static final AtomicLong FILE_TRX_NUM = new AtomicLong(0); - - private static final AtomicLong FILE_FLUSH_NUM = new AtomicLong(0); - - private static final int MARK_SIZE = 4; - - private static final int MAX_WAIT_TIME_MILLS = 2 * 1000; - - private static final int MAX_FLUSH_TIME_MILLS = 2 * 1000; - - private static final int MAX_FLUSH_NUM = 10; - - private static final int PER_FILE_BLOCK_SIZE = 65535 * 8; - - private static final long MAX_TRX_TIMEOUT_MILLS = 30 * 60 * 1000; - - private static volatile long trxStartTimeMills = System.currentTimeMillis(); - - private File currDataFile; - - private RandomAccessFile currRaf; - - private FileChannel currFileChannel; - - private long recoverCurrOffset = 0; - - private long recoverHisOffset = 0; - - private SessionManager sessionManager; - - private String currFullFileName; - - private String hisFullFileName; - - private WriteDataFileRunnable writeDataFileRunnable; - - private ReentrantLock writeSessionLock = new ReentrantLock(); - - private volatile long lastModifiedTime; - - private static final int MAX_WRITE_BUFFER_SIZE = StoreConfig.getFileWriteBufferCacheSize(); - - private final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(MAX_WRITE_BUFFER_SIZE); - - private static final FlushDiskMode FLUSH_DISK_MODE = StoreConfig.getFlushDiskMode(); - - private static final int MAX_WAIT_FOR_FLUSH_TIME_MILLS = 2 * 1000; - - private static final int MAX_WAIT_FOR_CLOSE_TIME_MILLS = 2 * 1000; - - private static final int INT_BYTE_SIZE = 4; - - /** - * Instantiates a new File transaction store manager. - * @param fullFileName the dir path - * @param sessionManager the session manager - * @throws IOException the io exception - */ - public FileTransactionStoreManager(String fullFileName, SessionManager sessionManager) throws IOException { - initFile(fullFileName); - fileWriteExecutor = new ThreadPoolExecutor(MAX_THREAD_WRITE, MAX_THREAD_WRITE, Integer.MAX_VALUE, - TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), - new NamedThreadFactory("fileTransactionStore", MAX_THREAD_WRITE, true)); - writeDataFileRunnable = new WriteDataFileRunnable(); - fileWriteExecutor.submit(writeDataFileRunnable); - this.sessionManager = sessionManager; - } - - private void initFile(String fullFileName) throws IOException { - this.currFullFileName = fullFileName; - this.hisFullFileName = fullFileName + HIS_DATA_FILENAME_POSTFIX; - try { - currDataFile = new File(currFullFileName); - if (!currDataFile.exists()) { - // create parent dir first - if (currDataFile.getParentFile() != null && !currDataFile.getParentFile().exists()) { - currDataFile.getParentFile().mkdirs(); - } - currDataFile.createNewFile(); - trxStartTimeMills = System.currentTimeMillis(); - } - else { - trxStartTimeMills = currDataFile.lastModified(); - } - lastModifiedTime = System.currentTimeMillis(); - currRaf = new RandomAccessFile(currDataFile, "rw"); - currRaf.seek(currDataFile.length()); - currFileChannel = currRaf.getChannel(); - } - catch (IOException exx) { - LOGGER.error("init file error,{}", exx.getMessage(), exx); - throw exx; - } - } - - @Override - public boolean writeSession(LogOperation logOperation, SessionStorable session) { - long curFileTrxNum; - writeSessionLock.lock(); - try { - if (!writeDataFile(new TransactionWriteStore(session, logOperation).encode())) { - return false; - } - lastModifiedTime = System.currentTimeMillis(); - curFileTrxNum = FILE_TRX_NUM.incrementAndGet(); - if (curFileTrxNum % PER_FILE_BLOCK_SIZE == 0 - && (System.currentTimeMillis() - trxStartTimeMills) > MAX_TRX_TIMEOUT_MILLS) { - return saveHistory(); - } - } - catch (Exception exx) { - LOGGER.error("writeSession error, {}", exx.getMessage(), exx); - return false; - } - finally { - writeSessionLock.unlock(); - } - flushDisk(curFileTrxNum, currFileChannel); - return true; - } - - private void flushDisk(long curFileNum, FileChannel currFileChannel) { - - if (FLUSH_DISK_MODE == FlushDiskMode.SYNC_MODEL) { - SyncFlushRequest syncFlushRequest = new SyncFlushRequest(curFileNum, currFileChannel); - writeDataFileRunnable.putRequest(syncFlushRequest); - syncFlushRequest.waitForFlush(MAX_WAIT_FOR_FLUSH_TIME_MILLS); - } - else { - writeDataFileRunnable.putRequest(new AsyncFlushRequest(curFileNum, currFileChannel)); - } - } - - /** - * get all overTimeSessionStorables merge write file - * @throws IOException - */ - private boolean saveHistory() throws IOException { - boolean result; - try { - result = findTimeoutAndSave(); - CloseFileRequest request = new CloseFileRequest(currFileChannel, currRaf); - writeDataFileRunnable.putRequest(request); - request.waitForClose(MAX_WAIT_FOR_CLOSE_TIME_MILLS); - Files.move(currDataFile.toPath(), new File(hisFullFileName).toPath(), StandardCopyOption.REPLACE_EXISTING); - } - catch (IOException exx) { - LOGGER.error("save history data file error, {}", exx.getMessage(), exx); - result = false; - } - finally { - initFile(currFullFileName); - } - return result; - } - - private boolean writeDataFrame(byte[] data) { - if (data == null || data.length <= 0) { - return true; - } - int dataLength = data.length; - int bufferRemainingSize = writeBuffer.remaining(); - if (bufferRemainingSize <= INT_BYTE_SIZE) { - if (!flushWriteBuffer(writeBuffer)) { - return false; - } - } - bufferRemainingSize = writeBuffer.remaining(); - if (bufferRemainingSize <= INT_BYTE_SIZE) { - throw new IllegalStateException( - String.format("Write buffer remaining size %d was too small", bufferRemainingSize)); - } - writeBuffer.putInt(dataLength); - bufferRemainingSize = writeBuffer.remaining(); - int dataPos = 0; - while (dataPos < dataLength) { - int dataLengthToWrite = dataLength - dataPos; - dataLengthToWrite = Math.min(dataLengthToWrite, bufferRemainingSize); - writeBuffer.put(data, dataPos, dataLengthToWrite); - bufferRemainingSize = writeBuffer.remaining(); - if (bufferRemainingSize == 0) { - if (!flushWriteBuffer(writeBuffer)) { - return false; - } - bufferRemainingSize = writeBuffer.remaining(); - } - dataPos += dataLengthToWrite; - } - return true; - } - - private boolean flushWriteBuffer(ByteBuffer writeBuffer) { - BufferUtils.flip(writeBuffer); - if (!writeDataFileByBuffer(writeBuffer)) { - return false; - } - BufferUtils.clear(writeBuffer); - return true; - } - - private boolean findTimeoutAndSave() throws IOException { - List globalSessionsOverMaxTimeout = sessionManager - .findGlobalSessions(new SessionCondition(MAX_TRX_TIMEOUT_MILLS)); - if (CollectionUtils.isEmpty(globalSessionsOverMaxTimeout)) { - return true; - } - for (GlobalSession globalSession : globalSessionsOverMaxTimeout) { - TransactionWriteStore globalWriteStore = new TransactionWriteStore(globalSession, LogOperation.GLOBAL_ADD); - byte[] data = globalWriteStore.encode(); - if (!writeDataFrame(data)) { - return false; - } - List branchSessIonsOverMaXTimeout = globalSession.getSortedBranches(); - if (branchSessIonsOverMaXTimeout != null) { - for (BranchSession branchSession : branchSessIonsOverMaXTimeout) { - try { - MDC.put(MDC_KEY_BRANCH_ID, String.valueOf(branchSession.getBranchId())); - TransactionWriteStore branchWriteStore = new TransactionWriteStore(branchSession, - LogOperation.BRANCH_ADD); - data = branchWriteStore.encode(); - if (!writeDataFrame(data)) { - return false; - } - } - finally { - MDC.remove(MDC_KEY_BRANCH_ID); - } - } - } - } - if (flushWriteBuffer(writeBuffer)) { - currFileChannel.force(false); - return true; - } - return false; - } - - @Override - public GlobalSession readSession(String xid) { - throw new StoreException("unsupport for read from file, xid:" + xid); - } - - @Override - public List readSession(SessionCondition sessionCondition) { - throw new StoreException("unsupport for read from file"); - } - - @Override - public void shutdown() { - if (fileWriteExecutor != null) { - fileWriteExecutor.shutdown(); - stopping = true; - int retry = 0; - while (!fileWriteExecutor.isTerminated() && retry < MAX_SHUTDOWN_RETRY) { - ++retry; - try { - Thread.sleep(SHUTDOWN_CHECK_INTERVAL); - } - catch (InterruptedException ignore) { - } - } - if (retry >= MAX_SHUTDOWN_RETRY) { - fileWriteExecutor.shutdownNow(); - } - } - try { - if (currFileChannel.isOpen()) { - currFileChannel.force(true); - } - } - catch (IOException e) { - LOGGER.error("fileChannel force error: {}", e.getMessage(), e); - } - closeFile(currRaf); - } - - @Override - public List readWriteStore(int readSize, boolean isHistory) { - File file = null; - long currentOffset = 0; - if (isHistory) { - file = new File(hisFullFileName); - currentOffset = recoverHisOffset; - } - else { - file = new File(currFullFileName); - currentOffset = recoverCurrOffset; - } - if (file.exists()) { - return parseDataFile(file, readSize, currentOffset, isHistory); - } - return null; - } - - @Override - public boolean hasRemaining(boolean isHistory) { - File file; - RandomAccessFile raf = null; - long currentOffset; - if (isHistory) { - file = new File(hisFullFileName); - currentOffset = recoverHisOffset; - } - else { - file = new File(currFullFileName); - currentOffset = recoverCurrOffset; - } - try { - raf = new RandomAccessFile(file, "r"); - return currentOffset < raf.length(); - - } - catch (IOException ignore) { - } - finally { - closeFile(raf); - } - return false; - } - - private List parseDataFile(File file, int readSize, long currentOffset, boolean isHistory) { - List transactionWriteStores = new ArrayList<>(readSize); - RandomAccessFile raf = null; - FileChannel fileChannel = null; - try { - raf = new RandomAccessFile(file, "r"); - raf.seek(currentOffset); - fileChannel = raf.getChannel(); - fileChannel.position(currentOffset); - long size = raf.length(); - ByteBuffer buffSize = ByteBuffer.allocate(MARK_SIZE); - while (fileChannel.position() < size) { - try { - BufferUtils.clear(buffSize); - int avilReadSize = fileChannel.read(buffSize); - if (avilReadSize != MARK_SIZE) { - break; - } - BufferUtils.flip(buffSize); - int bodySize = buffSize.getInt(); - byte[] byBody = new byte[bodySize]; - ByteBuffer buffBody = ByteBuffer.wrap(byBody); - avilReadSize = fileChannel.read(buffBody); - if (avilReadSize != bodySize) { - break; - } - TransactionWriteStore writeStore = new TransactionWriteStore(); - writeStore.decode(byBody); - transactionWriteStores.add(writeStore); - if (transactionWriteStores.size() == readSize) { - break; - } - } - catch (Exception ex) { - LOGGER.error("decode data file error:{}", ex.getMessage(), ex); - break; - } - } - return transactionWriteStores; - } - catch (IOException exx) { - LOGGER.error("parse data file error:{},file:{}", exx.getMessage(), file.getName(), exx); - return null; - } - finally { - try { - if (fileChannel != null) { - if (isHistory) { - recoverHisOffset = fileChannel.position(); - } - else { - recoverCurrOffset = fileChannel.position(); - } - } - closeFile(raf); - } - catch (IOException exx) { - LOGGER.error("file close error{}", exx.getMessage(), exx); - } - } - } - - private void closeFile(RandomAccessFile raf) { - try { - if (raf != null) { - raf.close(); - raf = null; - } - } - catch (IOException exx) { - LOGGER.error("file close error,{}", exx.getMessage(), exx); - } - } - - private boolean writeDataFile(byte[] bs) { - if (bs == null || bs.length >= Integer.MAX_VALUE - 3) { - return false; - } - if (!writeDataFrame(bs)) { - return false; - } - return flushWriteBuffer(writeBuffer); - } - - private boolean writeDataFileByBuffer(ByteBuffer byteBuffer) { - for (int retry = 0; retry < MAX_WRITE_RETRY; retry++) { - try { - while (byteBuffer.hasRemaining()) { - currFileChannel.write(byteBuffer); - } - return true; - } - catch (Exception exx) { - LOGGER.error("write data file error:{}", exx.getMessage(), exx); - } - } - LOGGER.error("write dataFile failed,retry more than :{}", MAX_WRITE_RETRY); - return false; - } - - interface StoreRequest { - - } - - abstract static class AbstractFlushRequest implements StoreRequest { - - private final long curFileTrxNum; - - private final FileChannel curFileChannel; - - protected AbstractFlushRequest(long curFileTrxNum, FileChannel curFileChannel) { - this.curFileTrxNum = curFileTrxNum; - this.curFileChannel = curFileChannel; - } - - public long getCurFileTrxNum() { - return curFileTrxNum; - } - - public FileChannel getCurFileChannel() { - return curFileChannel; - } - - } - - class SyncFlushRequest extends AbstractFlushRequest { - - private final CountDownLatch countDownLatch = new CountDownLatch(1); - - public SyncFlushRequest(long curFileTrxNum, FileChannel curFileChannel) { - super(curFileTrxNum, curFileChannel); - } - - public void wakeup() { - this.countDownLatch.countDown(); - } - - public void waitForFlush(long timeout) { - try { - this.countDownLatch.await(timeout, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) { - LOGGER.error("Interrupted", e); - } - } - - } - - class AsyncFlushRequest extends AbstractFlushRequest { - - public AsyncFlushRequest(long curFileTrxNum, FileChannel curFileChannel) { - super(curFileTrxNum, curFileChannel); - } - - } - - static class CloseFileRequest implements StoreRequest { - - private final CountDownLatch countDownLatch = new CountDownLatch(1); - - private FileChannel fileChannel; - - private RandomAccessFile file; - - public CloseFileRequest(FileChannel fileChannel, RandomAccessFile file) { - this.fileChannel = fileChannel; - this.file = file; - } - - public FileChannel getFileChannel() { - return fileChannel; - } - - public RandomAccessFile getFile() { - return file; - } - - public void wakeup() { - this.countDownLatch.countDown(); - } - - public void waitForClose(long timeout) { - try { - this.countDownLatch.await(timeout, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) { - LOGGER.error("Interrupted", e); - } - } - - } - - /** - * The type Write data file runnable. - */ - class WriteDataFileRunnable implements Runnable { - - private LinkedBlockingQueue storeRequests = new LinkedBlockingQueue<>(); - - public void putRequest(final StoreRequest request) { - storeRequests.add(request); - } - - @Override - public void run() { - while (!stopping) { - try { - StoreRequest storeRequest = storeRequests.poll(MAX_WAIT_TIME_MILLS, TimeUnit.MILLISECONDS); - handleStoreRequest(storeRequest); - } - catch (Exception exx) { - LOGGER.error("write file error: {}", exx.getMessage(), exx); - } - } - handleRestRequest(); - } - - /** - * handle the rest requests when stopping is true - */ - private void handleRestRequest() { - int remainNums = storeRequests.size(); - for (int i = 0; i < remainNums; i++) { - handleStoreRequest(storeRequests.poll()); - } - } - - private void handleStoreRequest(StoreRequest storeRequest) { - if (storeRequest == null) { - flushOnCondition(currFileChannel); - } - if (storeRequest instanceof SyncFlushRequest) { - syncFlush((SyncFlushRequest) storeRequest); - } - else if (storeRequest instanceof AsyncFlushRequest) { - async((AsyncFlushRequest) storeRequest); - } - else if (storeRequest instanceof CloseFileRequest) { - closeAndFlush((CloseFileRequest) storeRequest); - } - } - - private void closeAndFlush(CloseFileRequest req) { - long diff = FILE_TRX_NUM.get() - FILE_FLUSH_NUM.get(); - flush(req.getFileChannel()); - FILE_FLUSH_NUM.addAndGet(diff); - closeFile(req.getFile()); - req.wakeup(); - } - - private void async(AsyncFlushRequest req) { - flushOnCondition(req.getCurFileChannel()); - } - - private void syncFlush(SyncFlushRequest req) { - if (req.getCurFileTrxNum() > FILE_FLUSH_NUM.get()) { - long diff = FILE_TRX_NUM.get() - FILE_FLUSH_NUM.get(); - flush(req.getCurFileChannel()); - FILE_FLUSH_NUM.addAndGet(diff); - } - // notify - req.wakeup(); - } - - private void flushOnCondition(FileChannel fileChannel) { - if (FLUSH_DISK_MODE == FlushDiskMode.SYNC_MODEL) { - return; - } - long diff = FILE_TRX_NUM.get() - FILE_FLUSH_NUM.get(); - if (diff == 0) { - return; - } - if (diff % MAX_FLUSH_NUM == 0 || System.currentTimeMillis() - lastModifiedTime > MAX_FLUSH_TIME_MILLS) { - flush(fileChannel); - FILE_FLUSH_NUM.addAndGet(diff); - } - } - - private void flush(FileChannel fileChannel) { - try { - fileChannel.force(false); - } - catch (IOException exx) { - LOGGER.error("flush error: {}", exx.getMessage(), exx); - } - } - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/lock/RaftDistributedLocker.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/lock/RaftDistributedLocker.java deleted file mode 100644 index ea173a63e0..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/lock/RaftDistributedLocker.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.raft.lock; - -import io.seata.common.ConfigurationKeys; -import io.seata.common.loader.LoadLevel; -import io.seata.config.ConfigurationFactory; -import io.seata.server.cluster.raft.RaftServerFactory; -import io.seata.core.store.DistributedLockDO; -import io.seata.core.store.DistributedLocker; -import io.seata.server.storage.redis.lock.RedisDistributedLocker; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static io.seata.common.DefaultValues.DEFAULT_SEATA_GROUP; - -/** - * @description raft distributed lock - * @author funkye - */ -@LoadLevel(name = "raft") -public class RaftDistributedLocker implements DistributedLocker { - - protected static final Logger LOGGER = LoggerFactory.getLogger(RedisDistributedLocker.class); - - private final String group = ConfigurationFactory.getInstance() - .getConfig(ConfigurationKeys.SERVER_RAFT_GROUP, DEFAULT_SEATA_GROUP); - - /** - * Acquire the distributed lock - * @param distributedLockDO distributedLockDO - * @return boolean - */ - @Override - public boolean acquireLock(DistributedLockDO distributedLockDO) { - return RaftServerFactory.getInstance().isLeader(group); - } - - /** - * Release the distributed lock - * @param distributedLockDO distributedLockDO - * @return boolean - */ - @Override - public boolean releaseLock(DistributedLockDO distributedLockDO) { - return true; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/lock/RaftLockManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/lock/RaftLockManager.java deleted file mode 100644 index 8bcbc5b76e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/lock/RaftLockManager.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.raft.lock; - -import java.util.concurrent.CompletableFuture; -import com.alipay.sofa.jraft.Closure; -import io.seata.common.loader.LoadLevel; -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.server.cluster.raft.sync.msg.RaftBranchSessionSyncMsg; -import io.seata.server.cluster.raft.sync.msg.RaftGlobalSessionSyncMsg; -import io.seata.server.cluster.raft.sync.msg.dto.BranchTransactionDTO; -import io.seata.server.cluster.raft.sync.msg.dto.GlobalTransactionDTO; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.storage.file.lock.FileLockManager; -import io.seata.server.cluster.raft.util.RaftTaskUtil; - -import static io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType.RELEASE_BRANCH_SESSION_LOCK; -import static io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType.RELEASE_GLOBAL_SESSION_LOCK; - -/** - * @author funkye - */ -@LoadLevel(name = "raft") -public class RaftLockManager extends FileLockManager { - - @Override - public boolean releaseGlobalSessionLock(GlobalSession globalSession) throws TransactionException { - GlobalTransactionDTO globalTransactionDTO = new GlobalTransactionDTO(); - globalTransactionDTO.setXid(globalSession.getXid()); - RaftGlobalSessionSyncMsg raftSyncMsg = new RaftGlobalSessionSyncMsg(RELEASE_GLOBAL_SESSION_LOCK, - globalTransactionDTO); - CompletableFuture completableFuture = new CompletableFuture<>(); - Closure closure = status -> { - if (status.isOk()) { - try { - completableFuture.complete(this.localReleaseGlobalSessionLock(globalSession)); - } - catch (TransactionException e) { - completableFuture.completeExceptionally(e); - } - } - else { - completableFuture.completeExceptionally(new TransactionException(TransactionExceptionCode.NotRaftLeader, - "seata raft state machine exception: " + status.getErrorMsg())); - } - }; - return RaftTaskUtil.createTask(closure, raftSyncMsg, completableFuture); - } - - @Override - public boolean releaseLock(BranchSession branchSession) throws TransactionException { - CompletableFuture completableFuture = new CompletableFuture<>(); - BranchTransactionDTO branchTransactionDTO = new BranchTransactionDTO(); - branchTransactionDTO.setBranchId(branchSession.getBranchId()); - branchTransactionDTO.setXid(branchSession.getXid()); - RaftBranchSessionSyncMsg raftSyncMsg = new RaftBranchSessionSyncMsg(RELEASE_BRANCH_SESSION_LOCK, - branchTransactionDTO); - Closure closure = status -> { - if (status.isOk()) { - try { - // ensure consistency through state machine reading - completableFuture.complete(super.releaseLock(branchSession)); - } - catch (TransactionException e) { - completableFuture.completeExceptionally(e); - } - } - else { - completableFuture.completeExceptionally(new TransactionException(TransactionExceptionCode.NotRaftLeader, - "seata raft state machine exception: " + status.getErrorMsg())); - } - }; - return RaftTaskUtil.createTask(closure, raftSyncMsg, completableFuture); - } - - public boolean localReleaseGlobalSessionLock(GlobalSession globalSession) throws TransactionException { - return super.releaseGlobalSessionLock(globalSession); - } - - public boolean localReleaseLock(BranchSession branchSession) throws TransactionException { - return super.releaseLock(branchSession); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/session/RaftSessionManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/session/RaftSessionManager.java deleted file mode 100644 index 8152280530..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/raft/session/RaftSessionManager.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.raft.session; - -import java.io.IOException; -import java.util.concurrent.CompletableFuture; -import com.alipay.sofa.jraft.Closure; -import io.seata.common.loader.LoadLevel; -import io.seata.common.loader.Scope; -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; -import io.seata.core.model.LockStatus; -import io.seata.server.cluster.raft.sync.msg.RaftBranchSessionSyncMsg; -import io.seata.server.cluster.raft.sync.msg.RaftGlobalSessionSyncMsg; -import io.seata.server.cluster.raft.sync.msg.dto.BranchTransactionDTO; -import io.seata.server.cluster.raft.sync.msg.dto.GlobalTransactionDTO; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.storage.SessionConverter; -import io.seata.server.storage.file.session.FileSessionManager; -import io.seata.server.cluster.raft.util.RaftTaskUtil; - -import static io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType.ADD_BRANCH_SESSION; -import static io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType.ADD_GLOBAL_SESSION; -import static io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType.REMOVE_BRANCH_SESSION; -import static io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType.REMOVE_GLOBAL_SESSION; -import static io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType.UPDATE_BRANCH_SESSION_STATUS; -import static io.seata.server.cluster.raft.sync.msg.RaftSyncMsgType.UPDATE_GLOBAL_SESSION_STATUS; - -/** - * @author funkye - */ -@LoadLevel(name = "raft", scope = Scope.PROTOTYPE) -public class RaftSessionManager extends FileSessionManager { - - public RaftSessionManager(String name) throws IOException { - super(name); - } - - @Override - public void addGlobalSession(GlobalSession globalSession) throws TransactionException { - super.addGlobalSession(globalSession); - } - - @Override - public GlobalSession findGlobalSession(String xid) { - return super.findGlobalSession(xid); - } - - @Override - public void onBegin(GlobalSession globalSession) throws TransactionException { - CompletableFuture completableFuture = new CompletableFuture<>(); - Closure closure = status -> { - if (status.isOk()) { - try { - super.addGlobalSession(globalSession); - completableFuture.complete(true); - } - catch (TransactionException e) { - completableFuture.completeExceptionally(e); - } - } - else { - try { - completableFuture - .completeExceptionally(new TransactionException(TransactionExceptionCode.NotRaftLeader, - "seata raft state machine exception: " + status.getErrorMsg())); - } - finally { - try { - super.removeGlobalSession(globalSession); - } - catch (TransactionException e) { - completableFuture.completeExceptionally(e); - } - } - } - }; - GlobalTransactionDTO globalTransactionDTO = new GlobalTransactionDTO(); - SessionConverter.convertGlobalTransactionDO(globalTransactionDTO, globalSession); - RaftGlobalSessionSyncMsg raftSyncMsg = new RaftGlobalSessionSyncMsg(ADD_GLOBAL_SESSION, globalTransactionDTO); - RaftTaskUtil.createTask(closure, raftSyncMsg, completableFuture); - } - - @Override - public void onStatusChange(GlobalSession globalSession, GlobalStatus globalStatus) throws TransactionException { - CompletableFuture completableFuture = new CompletableFuture<>(); - Closure closure = closureStatus -> { - if (closureStatus.isOk()) { - globalSession.setStatus(globalStatus); - if (GlobalStatus.RollbackRetrying.equals(globalSession.getStatus()) - || GlobalStatus.Rollbacking.equals(globalSession.getStatus()) - || GlobalStatus.TimeoutRollbacking.equals(globalSession.getStatus())) { - globalSession.getBranchSessions() - .parallelStream() - .forEach(branchSession -> branchSession.setLockStatus(LockStatus.Rollbacking)); - } - completableFuture.complete(true); - } - else { - completableFuture.completeExceptionally(new TransactionException(TransactionExceptionCode.NotRaftLeader, - "seata raft state machine exception: " + closureStatus.getErrorMsg())); - } - }; - GlobalTransactionDTO globalTransactionDO = new GlobalTransactionDTO(globalSession.getXid()); - globalTransactionDO.setStatus(globalStatus.getCode()); - RaftGlobalSessionSyncMsg raftSyncMsg = new RaftGlobalSessionSyncMsg(UPDATE_GLOBAL_SESSION_STATUS, - globalTransactionDO); - RaftTaskUtil.createTask(closure, raftSyncMsg, completableFuture); - } - - @Override - public void onBranchStatusChange(GlobalSession globalSession, BranchSession branchSession, - BranchStatus branchStatus) throws TransactionException { - CompletableFuture completableFuture = new CompletableFuture<>(); - Closure closure = closureStatus -> { - if (closureStatus.isOk()) { - branchSession.setStatus(branchStatus); - completableFuture.complete(true); - } - else { - completableFuture.completeExceptionally(new TransactionException(TransactionExceptionCode.NotRaftLeader, - "seata raft state machine exception: " + closureStatus.getErrorMsg())); - } - }; - BranchTransactionDTO branchTransactionDO = new BranchTransactionDTO(globalSession.getXid(), - branchSession.getBranchId()); - branchTransactionDO.setStatus(branchStatus.getCode()); - RaftBranchSessionSyncMsg raftSyncMsg = new RaftBranchSessionSyncMsg(UPDATE_BRANCH_SESSION_STATUS, - branchTransactionDO); - RaftTaskUtil.createTask(closure, raftSyncMsg, completableFuture); - } - - @Override - public void onAddBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException { - CompletableFuture completableFuture = new CompletableFuture<>(); - branchSession.setStatus(BranchStatus.Registered); - Closure closure = status -> { - if (status.isOk()) { - completableFuture.complete(globalSession.add(branchSession)); - } - else { - try { - completableFuture - .completeExceptionally(new TransactionException(TransactionExceptionCode.NotRaftLeader, - "seata raft state machine exception: " + status.getErrorMsg())); - } - finally { - try { - globalSession.removeBranch(branchSession); - } - catch (TransactionException e) { - completableFuture.completeExceptionally(e); - } - } - } - }; - BranchTransactionDTO branchTransactionDTO = new BranchTransactionDTO(); - SessionConverter.convertBranchTransaction(branchTransactionDTO, branchSession); - RaftBranchSessionSyncMsg raftSyncMsg = new RaftBranchSessionSyncMsg(ADD_BRANCH_SESSION, branchTransactionDTO); - RaftTaskUtil.createTask(closure, raftSyncMsg, completableFuture); - } - - @Override - public void onRemoveBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException { - CompletableFuture completableFuture = new CompletableFuture<>(); - Closure closure = closureStatus -> { - if (closureStatus.isOk()) { - completableFuture.complete(globalSession.remove(branchSession)); - } - else { - completableFuture.completeExceptionally(new TransactionException(TransactionExceptionCode.NotRaftLeader, - "seata raft state machine exception: " + closureStatus.getErrorMsg())); - } - }; - BranchTransactionDTO branchTransactionDO = new BranchTransactionDTO(globalSession.getXid(), - branchSession.getBranchId()); - RaftBranchSessionSyncMsg raftSyncMsg = new RaftBranchSessionSyncMsg(REMOVE_BRANCH_SESSION, branchTransactionDO); - RaftTaskUtil.createTask(closure, raftSyncMsg, completableFuture); - } - - @Override - public void onSuccessEnd(GlobalSession globalSession) throws TransactionException { - CompletableFuture completableFuture = new CompletableFuture<>(); - Closure closure = status -> { - if (status.isOk()) { - try { - super.removeGlobalSession(globalSession); - completableFuture.complete(true); - } - catch (TransactionException e) { - completableFuture.completeExceptionally(e); - } - } - else { - completableFuture.completeExceptionally(new TransactionException(TransactionExceptionCode.NotRaftLeader, - "seata raft state machine exception: " + status.getErrorMsg())); - } - }; - GlobalTransactionDTO globalTransactionDO = new GlobalTransactionDTO(globalSession.getXid()); - RaftGlobalSessionSyncMsg raftSyncMsg = new RaftGlobalSessionSyncMsg(REMOVE_GLOBAL_SESSION, globalTransactionDO); - RaftTaskUtil.createTask(closure, raftSyncMsg, completableFuture); - } - - @Override - public void onFailEnd(GlobalSession globalSession) throws TransactionException { - super.onFailEnd(globalSession); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public void destroy() { - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java deleted file mode 100644 index 6bddac2ba9..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import io.seata.common.exception.RedisException; -import io.seata.common.util.ConfigTools; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.JedisPoolAbstract; -import redis.clients.jedis.JedisPoolConfig; -import redis.clients.jedis.JedisSentinelPool; -import redis.clients.jedis.Protocol; -import redis.clients.jedis.Jedis; -import static io.seata.common.DefaultValues.DEFAULT_REDIS_MAX_IDLE; -import static io.seata.common.DefaultValues.DEFAULT_REDIS_MAX_TOTAL; -import static io.seata.common.DefaultValues.DEFAULT_REDIS_MIN_IDLE; - -/** - * @author funkye - */ -public class JedisPooledFactory { - - /** - * The constant LOGGER. - */ - protected static final Logger LOGGER = LoggerFactory.getLogger(JedisPooledFactory.class); - - private static volatile JedisPoolAbstract jedisPool = null; - - private static final String HOST = "127.0.0.1"; - - private static final int PORT = 6379; - - private static final int DATABASE = 0; - - private static final int SENTINEL_HOST_NUMBER = 3; - - private static final Configuration CONFIGURATION = ConfigurationFactory.getInstance(); - - /** - * get the RedisPool instance (singleton) - * @return redisPool - */ - public static JedisPoolAbstract getJedisPoolInstance(JedisPoolAbstract... jedisPools) { - if (jedisPool == null) { - synchronized (JedisPooledFactory.class) { - if (jedisPool == null) { - JedisPoolAbstract tempJedisPool = null; - if (jedisPools != null && jedisPools.length > 0) { - tempJedisPool = jedisPools[0]; - } - else { - String password = CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_PASSWORD); - if (StringUtils.isBlank(password)) { - password = null; - } - else { - String publicKey = CONFIGURATION.getConfig(ConfigurationKeys.STORE_PUBLIC_KEY); - if (StringUtils.isNotBlank(publicKey)) { - try { - password = ConfigTools.publicDecrypt(password, publicKey); - } - catch (Exception e) { - LOGGER.error( - "decryption failed,please confirm whether the ciphertext and secret key are correct! error msg: {}", - e.getMessage()); - } - } - } - JedisPoolConfig poolConfig = new JedisPoolConfig(); - poolConfig.setMinIdle( - CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_MIN_CONN, DEFAULT_REDIS_MIN_IDLE)); - poolConfig.setMaxIdle( - CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_MAX_CONN, DEFAULT_REDIS_MAX_IDLE)); - poolConfig.setMaxTotal( - CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_MAX_TOTAL, DEFAULT_REDIS_MAX_TOTAL)); - String mode = CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_MODE, - ConfigurationKeys.REDIS_SINGLE_MODE); - if (mode.equals(ConfigurationKeys.REDIS_SENTINEL_MODE)) { - String masterName = CONFIGURATION - .getConfig(ConfigurationKeys.STORE_REDIS_SENTINEL_MASTERNAME); - if (StringUtils.isBlank(masterName)) { - throw new RedisException("The masterName is null in redis sentinel mode"); - } - Set sentinels = new HashSet<>(SENTINEL_HOST_NUMBER); - String[] sentinelHosts = CONFIGURATION - .getConfig(ConfigurationKeys.STORE_REDIS_SENTINEL_HOST) - .split(","); - Arrays.asList(sentinelHosts).forEach(sentinelHost -> sentinels.add(sentinelHost)); - String sentinelPassword = CONFIGURATION - .getConfig(ConfigurationKeys.STORE_REDIS_SENTINEL_PASSWORD); - if (StringUtils.isBlank(sentinelPassword)) { - sentinelPassword = null; - } - tempJedisPool = new JedisSentinelPool(masterName, sentinels, poolConfig, 60000, 60000, - password, CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_DATABASE, DATABASE), - null, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, sentinelPassword, null); - } - else if (mode.equals(ConfigurationKeys.REDIS_SINGLE_MODE)) { - String host = CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_SINGLE_HOST); - host = StringUtils.isBlank(host) - ? CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_HOST, HOST) : host; - int port = CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_SINGLE_PORT); - port = port == 0 ? CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_PORT, PORT) : port; - tempJedisPool = new JedisPool(poolConfig, host, port, 60000, password, - CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_DATABASE, DATABASE)); - } - else { - throw new RedisException("Configuration error of redis cluster mode"); - } - } - if (LOGGER.isInfoEnabled()) { - LOGGER.info("initialization of the build redis connection pool is complete"); - } - jedisPool = tempJedisPool; - } - } - } - return jedisPool; - } - - /** - * get an instance of Jedis (connection) from the connection pool - * @return jedis - */ - public static Jedis getJedisInstance() { - return getJedisPoolInstance().getResource(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/LuaParser.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/LuaParser.java deleted file mode 100644 index fcef449bcb..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/LuaParser.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Serializable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import io.seata.common.exception.StoreException; -import io.seata.common.io.FileLoader; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.exceptions.JedisDataException; -import redis.clients.jedis.exceptions.JedisNoScriptException; - -/** - * lua related utils - * - * @author conghuhu - */ -public class LuaParser { - - private static final Logger LOGGER = LoggerFactory.getLogger(LuaParser.class); - - private static final String WHITE_SPACE = " "; - - private static final String ANNOTATION_LUA = "--"; - - private static final Map LUA_FILE_MAP = new HashMap<>(); - - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - public final static class LuaResult implements Serializable { - - private static final long serialVersionUID = -4160065043902060730L; - - private Boolean success; - - private String status; - - private String data; - - public Boolean getSuccess() { - return success; - } - - public void setSuccess(Boolean success) { - this.success = success; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - @Override - public String toString() { - return "LuaResult{" + "success=" + success + ", type='" + status + '\'' + ", data='" + data + '\'' + '}'; - } - - } - - public final static class LuaErrorStatus { - - public static final String ANOTHER_ROLLBACKING = "AnotherRollbackIng"; - - public static final String ANOTHER_HOLDING = "AnotherHoldIng"; - - public static final String XID_NOT_EXISTED = "NotExisted"; - - public static final String ILLEGAL_CHANGE_STATUS = "ChangeStatusFail"; - - } - - /** - * get lua string from lua file. - * @param fileName - * @return - * @throws IOException - */ - public static Map getEvalShaMapFromFile(String fileName) throws IOException { - File luaFile = FileLoader.load(fileName); - if (luaFile == null) { - throw new IOException("no lua file: " + fileName); - } - StringBuilder luaByFile = new StringBuilder(); - try (FileInputStream fis = new FileInputStream(luaFile)) { - BufferedReader br = new BufferedReader(new InputStreamReader(fis)); - String line; - while ((line = br.readLine()) != null) { - if (line.trim().startsWith(ANNOTATION_LUA)) { - continue; - } - luaByFile.append(line); - luaByFile.append(WHITE_SPACE); - } - } - catch (IOException e) { - throw new IOException(e); - } - LUA_FILE_MAP.put(fileName, luaByFile.toString()); - Map resultMap = new ConcurrentHashMap<>(1); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - resultMap.put(fileName, jedis.scriptLoad(luaByFile.toString())); - return resultMap; - } - catch (UnsupportedOperationException | JedisDataException e) { - throw new IOException(e); - } - } - - public static T getObjectFromJson(String json, Class classz) { - try { - return OBJECT_MAPPER.readValue(json, classz); - } - catch (JsonProcessingException e) { - throw new StoreException(e.getMessage()); - } - } - - public static List getListFromJson(String json, Class classz) { - ObjectMapper objectMapper = new ObjectMapper(); - try { - return objectMapper.readValue(json, new TypeReference>() { - }); - } - catch (JsonProcessingException e) { - throw new StoreException(e.getMessage()); - } - } - - public static Object jedisEvalSha(Jedis jedis, String luaSHA, String luaFileName, List keys, - List args) { - try { - return jedis.evalsha(luaSHA, keys, args); - } - catch (JedisNoScriptException e) { - LOGGER.warn("try to reload the lua script and execute,jedis ex: " + e.getMessage()); - jedis.scriptLoad(LUA_FILE_MAP.get(luaFileName)); - return jedis.evalsha(luaSHA, keys, args); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisDistributedLocker.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisDistributedLocker.java deleted file mode 100644 index 9d9b934706..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisDistributedLocker.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis.lock; - -import io.seata.common.loader.LoadLevel; -import io.seata.common.loader.Scope; -import io.seata.core.store.DistributedLockDO; -import io.seata.core.store.DistributedLocker; -import io.seata.server.storage.redis.JedisPooledFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.Transaction; -import redis.clients.jedis.params.SetParams; - -/** - * Redis distributed lock - * - * @author zhongxiang.wang - */ -@LoadLevel(name = "redis", scope = Scope.SINGLETON) -public class RedisDistributedLocker implements DistributedLocker { - - protected static final Logger LOGGER = LoggerFactory.getLogger(RedisDistributedLocker.class); - - private static final String SUCCESS = "OK"; - - /** - * Acquire the distributed lock - * @param distributedLockDO the distributed lock info - * @return the distributed lock info - */ - @Override - public boolean acquireLock(DistributedLockDO distributedLockDO) { - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - // Don't need retry,if can't acquire the lock,let the other get the lock - String result = jedis.set(distributedLockDO.getLockKey(), distributedLockDO.getLockValue(), - SetParams.setParams().nx().px(distributedLockDO.getExpireTime())); - return SUCCESS.equalsIgnoreCase(result); - } - catch (Exception ex) { - LOGGER.error("The {} acquired the {} distributed lock failed.", distributedLockDO.getLockValue(), - distributedLockDO.getLockKey(), ex); - return false; - } - } - - /** - * Release the distributed lock - * @param distributedLockDO the distributed lock info - * @return the boolean - */ - @Override - public boolean releaseLock(DistributedLockDO distributedLockDO) { - String lockKey = distributedLockDO.getLockKey(); - String lockValue = distributedLockDO.getLockValue(); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - jedis.watch(lockKey); - // Check the value to prevent release the other's lock - if (lockValue.equals(jedis.get(lockKey))) { - Transaction multi = jedis.multi(); - multi.del(lockKey); - multi.exec(); - return true; - } - // The lock hold by others,If other one get the lock,we release lock success - // too as for current lockKey - jedis.unwatch(); - return true; - } - catch (Exception ex) { - LOGGER.error("The {} release the {} distributed lock failed.", lockValue, lockKey, ex); - return false; - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java deleted file mode 100644 index a6eb3bf91e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis.lock; - -import io.seata.common.executor.Initialize; -import io.seata.common.loader.LoadLevel; -import io.seata.core.exception.TransactionException; -import io.seata.core.lock.Locker; -import io.seata.server.lock.AbstractLockManager; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; - -/** - * @author funkye - */ -@LoadLevel(name = "redis") -public class RedisLockManager extends AbstractLockManager implements Initialize { - - /** - * The locker. - */ - private Locker locker; - - @Override - public void init() { - locker = RedisLockerFactory.getLocker(); - } - - @Override - public Locker getLocker(BranchSession branchSession) { - return locker; - } - - @Override - public boolean releaseLock(BranchSession branchSession) throws TransactionException { - try { - return getLocker().releaseLock(branchSession.getXid(), branchSession.getBranchId()); - } - catch (Exception t) { - LOGGER.error("unLock error, xid {}, branchId:{}", branchSession.getXid(), branchSession.getBranchId(), t); - return false; - } - } - - @Override - public boolean releaseGlobalSessionLock(GlobalSession globalSession) throws TransactionException { - try { - return getLocker().releaseLock(globalSession.getXid()); - } - catch (Exception t) { - LOGGER.error("unLock globalSession error, xid:{}", globalSession.getXid(), t); - return false; - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLocker.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLocker.java deleted file mode 100644 index 6190c1ccd6..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLocker.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis.lock; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.StringJoiner; -import java.util.stream.Collectors; - -import io.seata.common.exception.StoreException; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.LambdaUtils; -import io.seata.common.util.StringUtils; -import io.seata.core.exception.BranchTransactionException; -import io.seata.core.lock.AbstractLocker; -import io.seata.core.lock.RowLock; -import io.seata.core.model.LockStatus; -import io.seata.core.store.LockDO; -import io.seata.server.storage.redis.JedisPooledFactory; - -import com.google.common.collect.Lists; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.Pipeline; - -import static io.seata.common.Constants.ROW_LOCK_KEY_SPLIT_CHAR; -import static io.seata.core.constants.RedisKeyConstants.DEFAULT_REDIS_SEATA_GLOBAL_LOCK_PREFIX; -import static io.seata.core.constants.RedisKeyConstants.DEFAULT_REDIS_SEATA_ROW_LOCK_PREFIX; -import static io.seata.core.exception.TransactionExceptionCode.LockKeyConflictFailFast; - -/** - * The redis lock store operation - * - * @author funkye - * @author wangzhongxiang - * @author conghuhu - */ -public class RedisLocker extends AbstractLocker { - - private static final Logger LOGGER = LoggerFactory.getLogger(RedisLocker.class); - - private static final Integer SUCCEED = 1; - - private static final Integer FAILED = 0; - - private static final String XID = "xid"; - - private static final String TRANSACTION_ID = "transactionId"; - - private static final String BRANCH_ID = "branchId"; - - private static final String RESOURCE_ID = "resourceId"; - - private static final String TABLE_NAME = "tableName"; - - private static final String PK = "pk"; - - protected static final String STATUS = "status"; - - private static final String ROW_KEY = "rowKey"; - - /** - * Instantiates a new Redis locker. - */ - public RedisLocker() { - } - - @Override - public boolean acquireLock(List rowLocks) { - return acquireLock(rowLocks, true, false); - } - - @Override - public boolean acquireLock(List rowLocks, boolean autoCommit, boolean skipCheckLock) { - if (CollectionUtils.isEmpty(rowLocks)) { - return true; - } - - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - String needLockXid = rowLocks.get(0).getXid(); - Long branchId = rowLocks.get(0).getBranchId(); - List needLockDOS = convertToLockDO(rowLocks); - if (needLockDOS.size() > 1) { - needLockDOS = needLockDOS.stream() - .filter(LambdaUtils.distinctByKey(LockDO::getRowKey)) - .collect(Collectors.toList()); - } - List needLockKeys = new ArrayList<>(); - needLockDOS.forEach(lockDO -> needLockKeys.add(buildLockKey(lockDO.getRowKey()))); - Map needAddLock = new HashMap<>(needLockKeys.size(), 1); - - if (!skipCheckLock) { - Pipeline pipeline1 = jedis.pipelined(); - needLockKeys.stream().forEachOrdered(needLockKey -> { - pipeline1.hget(needLockKey, XID); - if (!autoCommit) { - pipeline1.hget(needLockKey, STATUS); - } - }); - List> existedLockInfos = Lists - .partition((List) (List) pipeline1.syncAndReturnAll(), autoCommit ? 1 : 2); - - // When the local transaction and the global transaction are enabled, - // the branch registration fails to acquire the global lock, - // the lock holder is in the second-stage rollback, - // and the branch registration fails to be retried quickly, - // because the retry with the local transaction does not release the - // database lock , - // resulting in a two-phase rollback wait. - // Therefore, if a global lock is found in the Rollbacking state, - // the fail-fast code is returned directly. - if (!autoCommit) { - boolean hasRollBackingLock = existedLockInfos.parallelStream() - .anyMatch(result -> StringUtils.equals(result.get(1), - String.valueOf(LockStatus.Rollbacking.getCode()))); - if (hasRollBackingLock) { - throw new StoreException(new BranchTransactionException(LockKeyConflictFailFast)); - } - } - - // The logic is executed here, there must be a lock without Rollbacking - // status when autoCommit equals false - for (int i = 0; i < needLockKeys.size(); i++) { - List results = existedLockInfos.get(i); - String existedLockXid = CollectionUtils.isEmpty(results) ? null : existedLockInfos.get(i).get(0); - if (StringUtils.isEmpty(existedLockXid)) { - // If empty,we need to lock this row - needAddLock.put(needLockKeys.get(i), needLockDOS.get(i)); - } - else { - if (!StringUtils.equals(existedLockXid, needLockXid)) { - // If not equals,means the rowkey is holding by another global - // transaction - logGlobalLockConflictInfo(needLockXid, needLockKeys.get(i), existedLockXid); - return false; - } - } - } - if (needAddLock.isEmpty()) { - return true; - } - } - - Pipeline pipeline = jedis.pipelined(); - List readyKeys = new ArrayList<>(needAddLock.keySet()); - needAddLock.forEach((key, value) -> { - pipeline.hsetnx(key, XID, value.getXid()); - pipeline.hsetnx(key, TRANSACTION_ID, value.getTransactionId().toString()); - pipeline.hsetnx(key, BRANCH_ID, value.getBranchId().toString()); - pipeline.hset(key, ROW_KEY, value.getRowKey()); - pipeline.hset(key, RESOURCE_ID, value.getResourceId()); - pipeline.hset(key, TABLE_NAME, value.getTableName()); - pipeline.hset(key, PK, value.getPk()); - }); - List results = (List) (List) pipeline.syncAndReturnAll(); - List> partitions = Lists.partition(results, 7); - - ArrayList success = new ArrayList<>(partitions.size()); - Integer status = SUCCEED; - for (int i = 0; i < partitions.size(); i++) { - if (Objects.equals(partitions.get(i).get(0), FAILED)) { - status = FAILED; - } - else { - success.add(readyKeys.get(i)); - } - } - - // If someone has failed,all the lockkey which has been added need to be - // delete. - if (FAILED.equals(status)) { - if (success.size() > 0) { - jedis.del(success.toArray(new String[0])); - } - return false; - } - String xidLockKey = buildXidLockKey(needLockXid); - StringJoiner lockKeysString = new StringJoiner(ROW_LOCK_KEY_SPLIT_CHAR); - needLockKeys.forEach(lockKeysString::add); - jedis.hset(xidLockKey, branchId.toString(), lockKeysString.toString()); - return true; - } - } - - protected void logGlobalLockConflictInfo(String needLockXid, String lockKey, String xIdOwnLock) { - LOGGER.info("tx:[{}] acquire Global lock failed. Global lock on [{}] is holding by xid {}", needLockXid, - lockKey, xIdOwnLock); - } - - @Override - public boolean releaseLock(String xid) { - return doReleaseLock(xid, null); - } - - @Override - public boolean releaseLock(String xid, Long branchId) { - if (branchId == null) { - return true; - } - return doReleaseLock(xid, branchId); - } - - @Override - public boolean isLockable(List rowLocks) { - if (CollectionUtils.isEmpty(rowLocks)) { - return true; - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - List locks = convertToLockDO(rowLocks); - Set lockKeys = new HashSet<>(); - for (LockDO rowlock : locks) { - lockKeys.add(buildLockKey(rowlock.getRowKey())); - } - - String xid = rowLocks.get(0).getXid(); - try (Pipeline pipeline = jedis.pipelined()) { - lockKeys.forEach(key -> pipeline.hget(key, XID)); - List existedXids = (List) (List) pipeline.syncAndReturnAll(); - return existedXids.stream().allMatch(existedXid -> existedXid == null || xid.equals(existedXid)); - } - } - } - - @Override - public void updateLockStatus(String xid, LockStatus lockStatus) { - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - String xidLockKey = buildXidLockKey(xid); - Map branchAndLockKeys = jedis.hgetAll(xidLockKey); - if (CollectionUtils.isEmpty(branchAndLockKeys)) { - return; - } - try (Pipeline pipeline = jedis.pipelined()) { - branchAndLockKeys.values().forEach(k -> { - if (StringUtils.isNotEmpty(k)) { - if (k.contains(ROW_LOCK_KEY_SPLIT_CHAR)) { - String[] keys = k.split(ROW_LOCK_KEY_SPLIT_CHAR); - for (String key : keys) { - pipeline.hset(key, STATUS, String.valueOf(lockStatus.getCode())); - } - } - else { - pipeline.hset(k, STATUS, String.valueOf(lockStatus.getCode())); - } - } - }); - pipeline.sync(); - } - } - } - - private boolean doReleaseLock(String xid, Long branchId) { - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - String xidLockKey = buildXidLockKey(xid); - final List rowKeys = new ArrayList<>(); - if (null == branchId) { - Map rowKeyMap = jedis.hgetAll(xidLockKey); - rowKeyMap.forEach((branch, rowKey) -> rowKeys.add(rowKey)); - } - else { - rowKeys.add(jedis.hget(xidLockKey, branchId.toString())); - } - if (CollectionUtils.isNotEmpty(rowKeys)) { - Pipeline pipelined = jedis.pipelined(); - if (null == branchId) { - pipelined.del(xidLockKey); - } - else { - pipelined.hdel(xidLockKey, branchId.toString()); - } - rowKeys.forEach(rowKeyStr -> { - if (StringUtils.isNotEmpty(rowKeyStr)) { - if (rowKeyStr.contains(ROW_LOCK_KEY_SPLIT_CHAR)) { - String[] keys = rowKeyStr.split(ROW_LOCK_KEY_SPLIT_CHAR); - pipelined.del(keys); - } - else { - pipelined.del(rowKeyStr); - } - } - }); - pipelined.sync(); - } - return true; - } - } - - protected String buildXidLockKey(String xid) { - return DEFAULT_REDIS_SEATA_GLOBAL_LOCK_PREFIX + xid; - } - - protected String buildLockKey(String rowKey) { - return DEFAULT_REDIS_SEATA_ROW_LOCK_PREFIX + rowKey; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLockerFactory.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLockerFactory.java deleted file mode 100644 index 27ae051849..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLockerFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis.lock; - -import io.seata.common.ConfigurationKeys; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.lock.Locker; - -import static io.seata.common.Constants.STORE_REDIS_TYPE_PIPELINE; - -/** - * @author conghuhu - */ -public class RedisLockerFactory { - - private static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The locker. - */ - private static volatile Locker locker; - - public static Locker getLocker() { - if (locker == null) { - synchronized (RedisLockerFactory.class) { - if (locker == null) { - String storeRedisType = CONFIG.getConfig(ConfigurationKeys.STORE_REDIS_TYPE, - STORE_REDIS_TYPE_PIPELINE); - locker = STORE_REDIS_TYPE_PIPELINE.equals(storeRedisType) ? new RedisLocker() - : new RedisLuaLocker(); - } - } - } - return locker; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLuaLocker.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLuaLocker.java deleted file mode 100644 index 40cd3f5e56..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/lock/RedisLuaLocker.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis.lock; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringJoiner; -import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import redis.clients.jedis.Jedis; - -import io.seata.common.exception.StoreException; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.LambdaUtils; -import io.seata.core.exception.BranchTransactionException; -import io.seata.core.lock.RowLock; -import io.seata.core.model.LockStatus; -import io.seata.core.store.LockDO; -import io.seata.server.storage.redis.JedisPooledFactory; -import io.seata.server.storage.redis.LuaParser; - -import static io.seata.common.Constants.ROW_LOCK_KEY_SPLIT_CHAR; -import static io.seata.core.exception.TransactionExceptionCode.LockKeyConflictFailFast; - -/** - * @author conghuhu - */ -public class RedisLuaLocker extends RedisLocker { - - private static final Logger LOGGER = LoggerFactory.getLogger(RedisLuaLocker.class); - - private static final String LUA_PREFIX = "lua/redislocker/"; - - private static final String ACQUIRE_LOCK_LUA_FILE_NAME = LUA_PREFIX + "acquireRedisLock.lua"; - - private static final String RELEASE_LOCK_LUA_FILE_NAME = LUA_PREFIX + "releaseRedisLock.lua"; - - private static final String UPDATE_LOCK_LUA_FILE_NAME = LUA_PREFIX + "updateLockStatus.lua"; - - private static final String LOCKABLE_LUA_FILE_NAME = LUA_PREFIX + "isLockable.lua"; - - /** - * key filename value LOCK_SHA_SCRIPT - */ - private static final Map LOCK_SHA_MAP = new HashMap<>(4); - - public RedisLuaLocker() { - if (LOCK_SHA_MAP.isEmpty()) { - loadLuaFile(ACQUIRE_LOCK_LUA_FILE_NAME, "acquire lock"); - loadLuaFile(RELEASE_LOCK_LUA_FILE_NAME, "release lock"); - loadLuaFile(UPDATE_LOCK_LUA_FILE_NAME, "update lock"); - loadLuaFile(LOCKABLE_LUA_FILE_NAME, "lockable"); - } - } - - private void loadLuaFile(String fileName, String mode) { - try { - LOCK_SHA_MAP.putAll(LuaParser.getEvalShaMapFromFile(fileName)); - } - catch (IOException e) { - // if it fails to read the file, pipeline mode is used - if (LOCK_SHA_MAP.get(fileName) != null) { - LOCK_SHA_MAP.remove(fileName); - } - if (LOGGER.isInfoEnabled()) { - LOGGER.info("redis locker: {} use pipeline mode", mode); - } - } - } - - @Override - public boolean acquireLock(List rowLocks, boolean autoCommit, boolean skipCheckLock) { - if (CollectionUtils.isEmpty(rowLocks)) { - return true; - } - - String luaSHA = LOCK_SHA_MAP.get(ACQUIRE_LOCK_LUA_FILE_NAME); - if (luaSHA == null) { - return super.acquireLock(rowLocks, autoCommit, skipCheckLock); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - String needLockXid = rowLocks.get(0).getXid(); - Long branchId = rowLocks.get(0).getBranchId(); - List needLockDOs = rowLocks.stream() - .map(this::convertToLockDO) - .filter(LambdaUtils.distinctByKey(LockDO::getRowKey)) - .collect(Collectors.toList()); - List keys = new ArrayList<>(); - List args = new ArrayList<>(); - int size = needLockDOs.size(); - args.add(String.valueOf(size)); - // args index 2 placeholder - args.add(null); - args.add(needLockXid); - for (LockDO lockDO : needLockDOs) { - keys.add(buildLockKey(lockDO.getRowKey())); - args.add(lockDO.getTransactionId().toString()); - args.add(lockDO.getBranchId().toString()); - args.add(lockDO.getResourceId()); - args.add(lockDO.getTableName()); - args.add(lockDO.getRowKey()); - args.add(lockDO.getPk()); - } - String xidLockKey = buildXidLockKey(needLockXid); - StringJoiner lockKeysString = new StringJoiner(ROW_LOCK_KEY_SPLIT_CHAR); - needLockDOs.stream().map(lockDO -> buildLockKey(lockDO.getRowKey())).forEach(lockKeysString::add); - - keys.add(xidLockKey); - keys.add(branchId.toString()); - args.add(lockKeysString.toString()); - // reset args index 2 - args.set(1, String.valueOf(args.size())); - - String result = (String) LuaParser.jedisEvalSha(jedis, luaSHA, ACQUIRE_LOCK_LUA_FILE_NAME, keys, args); - - LuaParser.LuaResult luaResult = LuaParser.getObjectFromJson(result, LuaParser.LuaResult.class); - - // luaResult.getData() : xIdOwnLock - if (luaResult.getSuccess() && luaResult.getData().equals(needLockXid)) { - return true; - } - else { - if (LuaParser.LuaErrorStatus.ANOTHER_ROLLBACKING.equals(luaResult.getStatus())) { - // if a global lock is found in the Rollbacking state,the fail-fast - // code is returned directly. - throw new StoreException(new BranchTransactionException(LockKeyConflictFailFast)); - } - else if (LuaParser.LuaErrorStatus.ANOTHER_HOLDING.equals(luaResult.getStatus())) { - // means the rowKey is holding by another global transaction - logGlobalLockConflictInfo(needLockXid, keys.get(0), luaResult.getData()); - } - return false; - } - } - } - - @Override - public boolean releaseLock(String xid) { - String luaSHA = LOCK_SHA_MAP.get(RELEASE_LOCK_LUA_FILE_NAME); - if (luaSHA == null) { - return super.releaseLock(xid); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - String xidLockKey = buildXidLockKey(xid); - List keys = new ArrayList<>(); - List args = Collections.emptyList(); - keys.add(xidLockKey); - LuaParser.jedisEvalSha(jedis, luaSHA, RELEASE_LOCK_LUA_FILE_NAME, keys, args); - return true; - } - } - - @Override - public boolean releaseLock(String xid, Long branchId) { - if (branchId == null) { - return true; - } - String luaSHA = LOCK_SHA_MAP.get(RELEASE_LOCK_LUA_FILE_NAME); - if (luaSHA == null) { - return super.releaseLock(xid, branchId); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - String xidLockKey = buildXidLockKey(xid); - List keys = new ArrayList<>(); - List args = Collections.emptyList(); - keys.add(xidLockKey); - keys.add(String.valueOf(branchId)); - LuaParser.jedisEvalSha(jedis, luaSHA, RELEASE_LOCK_LUA_FILE_NAME, keys, args); - return true; - } - } - - @Override - public boolean isLockable(List rowLocks) { - if (CollectionUtils.isEmpty(rowLocks)) { - return true; - } - String luaSHA = LOCK_SHA_MAP.get(LOCKABLE_LUA_FILE_NAME); - if (luaSHA == null) { - return super.isLockable(rowLocks); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - List locks = convertToLockDO(rowLocks); - Set lockKeys = new HashSet<>(); - for (LockDO rowlock : locks) { - lockKeys.add(buildLockKey(rowlock.getRowKey())); - } - String xid = rowLocks.get(0).getXid(); - List keys = new ArrayList<>(); - keys.add(String.valueOf(lockKeys.size())); - keys.addAll(lockKeys); - List args = new ArrayList<>(); - args.add(xid); - String res = (String) LuaParser.jedisEvalSha(jedis, luaSHA, LOCKABLE_LUA_FILE_NAME, keys, args); - return "true".equals(res); - } - } - - @Override - public void updateLockStatus(String xid, LockStatus lockStatus) { - String luaSHA = LOCK_SHA_MAP.get(UPDATE_LOCK_LUA_FILE_NAME); - if (luaSHA == null) { - super.updateLockStatus(xid, lockStatus); - return; - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - String xidLockKey = buildXidLockKey(xid); - List keys = new ArrayList<>(); - List args = new ArrayList<>(); - keys.add(xidLockKey); - keys.add(STATUS); - args.add(String.valueOf(lockStatus.getCode())); - LuaParser.jedisEvalSha(jedis, luaSHA, UPDATE_LOCK_LUA_FILE_NAME, keys, args); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java deleted file mode 100644 index ebac73e94d..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis.session; - -import java.util.Collection; -import java.util.List; - -import io.seata.common.exception.StoreException; -import io.seata.common.executor.Initialize; -import io.seata.common.loader.LoadLevel; -import io.seata.common.loader.Scope; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; -import io.seata.server.session.AbstractSessionManager; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.store.TransactionStoreManager.LogOperation; -import io.seata.server.storage.redis.store.RedisTransactionStoreManagerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author funkye - */ -@LoadLevel(name = "redis", scope = Scope.PROTOTYPE) -public class RedisSessionManager extends AbstractSessionManager implements Initialize { - - /** - * The constant LOGGER. - */ - protected static final Logger LOGGER = LoggerFactory.getLogger(RedisSessionManager.class); - - /** - * Instantiates a new Data base session manager. - */ - public RedisSessionManager() { - super(); - } - - @Override - public void init() { - transactionStoreManager = RedisTransactionStoreManagerFactory.getInstance(); - } - - @Override - public void addGlobalSession(GlobalSession session) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_ADD, session); - if (!ret) { - throw new StoreException("addGlobalSession failed."); - } - } - - @Override - public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException { - session.setStatus(status); - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_UPDATE, session); - if (!ret) { - throw new StoreException("updateGlobalSessionStatus failed."); - } - } - - /** - * remove globalSession 1. rootSessionManager remove normal globalSession 2. - * retryCommitSessionManager and retryRollbackSessionManager remove retry expired - * globalSession - * @param session the session - * @throws TransactionException - */ - @Override - public void removeGlobalSession(GlobalSession session) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_REMOVE, session); - if (!ret) { - throw new StoreException("removeGlobalSession failed."); - } - } - - @Override - public void addBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_ADD, session); - if (!ret) { - throw new StoreException("addBranchSession failed."); - } - } - - @Override - public void updateBranchSessionStatus(BranchSession session, BranchStatus status) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_UPDATE, session); - if (!ret) { - throw new StoreException("updateBranchSessionStatus failed."); - } - } - - @Override - public void removeBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { - boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_REMOVE, session); - if (!ret) { - throw new StoreException("removeBranchSession failed."); - } - } - - @Override - public GlobalSession findGlobalSession(String xid) { - return this.findGlobalSession(xid, true); - } - - @Override - public GlobalSession findGlobalSession(String xid, boolean withBranchSessions) { - return transactionStoreManager.readSession(xid, withBranchSessions); - } - - @Override - public Collection allSessions() { - return findGlobalSessions(new SessionCondition(GlobalStatus.UnKnown, GlobalStatus.Begin, - GlobalStatus.Committing, GlobalStatus.CommitRetrying, GlobalStatus.Rollbacking, - GlobalStatus.RollbackRetrying, GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbackRetrying, - GlobalStatus.AsyncCommitting)); - } - - @Override - public List findGlobalSessions(SessionCondition condition) { - // nothing need to do - return transactionStoreManager.readSession(condition); - } - - @Override - public T lockAndExecute(GlobalSession globalSession, GlobalSession.LockCallable lockCallable) - throws TransactionException { - return lockCallable.call(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisLuaTransactionStoreManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisLuaTransactionStoreManager.java deleted file mode 100644 index 5df7c40c15..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisLuaTransactionStoreManager.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis.store; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import io.seata.common.exception.RedisException; -import io.seata.common.exception.StoreException; -import io.seata.common.util.BeanUtils; -import io.seata.common.util.CollectionUtils; -import io.seata.core.model.GlobalStatus; -import io.seata.core.store.BranchTransactionDO; -import io.seata.core.store.GlobalTransactionDO; -import io.seata.server.storage.redis.JedisPooledFactory; -import io.seata.server.storage.redis.LuaParser; - -import com.google.common.collect.ImmutableMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import redis.clients.jedis.Jedis; - -import static io.seata.core.constants.RedisKeyConstants.REDIS_KEY_BRANCH_APPLICATION_DATA; -import static io.seata.core.constants.RedisKeyConstants.REDIS_KEY_BRANCH_GMT_MODIFIED; -import static io.seata.core.constants.RedisKeyConstants.REDIS_KEY_BRANCH_STATUS; -import static io.seata.core.constants.RedisKeyConstants.REDIS_KEY_BRANCH_XID; -import static io.seata.core.constants.RedisKeyConstants.REDIS_KEY_GLOBAL_GMT_MODIFIED; -import static io.seata.core.constants.RedisKeyConstants.REDIS_KEY_GLOBAL_STATUS; -import static io.seata.core.constants.RedisKeyConstants.REDIS_KEY_GLOBAL_XID; - -/** - * @author conghuhu - */ -public class RedisLuaTransactionStoreManager extends RedisTransactionStoreManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(RedisLuaTransactionStoreManager.class); - - private static final String LUA_PREFIX = "lua/redisStore/"; - - private static final String INSERT_TRANSACTION_DO_LUA_FILE_NAME = LUA_PREFIX + "insertTransactionDO.lua"; - - private static final String DELETE_TRANSACTION_DO_LUA_FILE_NAME = LUA_PREFIX + "deleteTransactionDO.lua"; - - private static final String UPDATE_BRANCH_TRANSACTION_DO_LUA_FILE_NAME = LUA_PREFIX - + "updateBranchTransactionDO.lua"; - - private static final String UPDATE_GLOBAL_TRANSACTION_DO_LUA_FILE_NAME = LUA_PREFIX - + "updateGlobalTransactionDO.lua"; - - private static final String ROLLBACK_GLOBAL_TRANSACTION_DO_LUA_FILE_NAME = LUA_PREFIX - + "rollbackGlobalTransactionDO.lua"; - - /** - * key filename value LOCK_SHA_SCRIPT_ID - */ - private static final Map LOCK_SHA_MAP = new HashMap<>(); - - /** - * load redis lua script - */ - private void initRedisMode() { - loadLuaFile(INSERT_TRANSACTION_DO_LUA_FILE_NAME, "insertTransactionDO"); - loadLuaFile(DELETE_TRANSACTION_DO_LUA_FILE_NAME, "deleteTransactionDO"); - loadLuaFile(UPDATE_BRANCH_TRANSACTION_DO_LUA_FILE_NAME, "updateBranchTransactionDO"); - loadLuaFile(UPDATE_GLOBAL_TRANSACTION_DO_LUA_FILE_NAME, "updateGlobalTransactionDO"); - loadLuaFile(ROLLBACK_GLOBAL_TRANSACTION_DO_LUA_FILE_NAME, "rollbackGlobalTransactionDO"); - } - - private void loadLuaFile(String fileName, String mode) { - try { - LOCK_SHA_MAP.putAll(LuaParser.getEvalShaMapFromFile(fileName)); - } - catch (IOException e) { - // if it fails to read the file, pipeline mode is used - if (LOCK_SHA_MAP.get(fileName) != null) { - LOCK_SHA_MAP.remove(fileName); - } - if (LOGGER.isInfoEnabled()) { - LOGGER.info("redis session: {} use pipeline mode", mode); - } - } - } - - public RedisLuaTransactionStoreManager() { - LOGGER.info("init redisLuaTransactionStoreManager"); - initRedisMode(); - } - - @Override - public void initGlobalMap() { - if (CollectionUtils.isEmpty(branchMap)) { - globalMap = ImmutableMap.>builder() - .put(LogOperation.GLOBAL_ADD, this::insertGlobalTransactionDO) - .put(LogOperation.GLOBAL_UPDATE, this::updateGlobalTransactionDO) - .put(LogOperation.GLOBAL_REMOVE, this::deleteGlobalTransactionDO) - .build(); - } - } - - @Override - public void initBranchMap() { - if (CollectionUtils.isEmpty(branchMap)) { - branchMap = ImmutableMap.>builder() - .put(LogOperation.BRANCH_ADD, this::insertBranchTransactionDO) - .put(LogOperation.BRANCH_UPDATE, this::updateBranchTransactionDO) - .put(LogOperation.BRANCH_REMOVE, this::deleteBranchTransactionDO) - .build(); - } - } - - @Override - protected boolean insertBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String branchKey = buildBranchKey(branchTransactionDO.getBranchId()); - String branchListKey = buildBranchListKeyByXid(branchTransactionDO.getXid()); - Date now = new Date(); - branchTransactionDO.setGmtCreate(now); - branchTransactionDO.setGmtModified(now); - Map branchTransactionDOMap = BeanUtils.objectToMap(branchTransactionDO); - String luaSHA = LOCK_SHA_MAP.get(INSERT_TRANSACTION_DO_LUA_FILE_NAME); - if (luaSHA == null) { - return super.insertBranchTransactionDO(branchTransactionDO); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - List keys = new ArrayList() { - { - add(branchKey); - add(branchListKey); - } - }; - List args = new ArrayList() { - { - add("branch"); - add(String.valueOf(branchTransactionDOMap.size())); - } - }; - for (Map.Entry entry : branchTransactionDOMap.entrySet()) { - keys.add(entry.getKey()); - args.add(entry.getValue()); - } - LuaParser.jedisEvalSha(jedis, luaSHA, INSERT_TRANSACTION_DO_LUA_FILE_NAME, keys, args); - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - @Override - protected boolean deleteBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String branchKey = buildBranchKey(branchTransactionDO.getBranchId()); - String branchListKey = buildBranchListKeyByXid(branchTransactionDO.getXid()); - String luaSHA = LOCK_SHA_MAP.get(DELETE_TRANSACTION_DO_LUA_FILE_NAME); - if (luaSHA == null) { - return super.deleteBranchTransactionDO(branchTransactionDO); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - List keys = new ArrayList() { - { - add(branchKey); - add(branchListKey); - add(REDIS_KEY_BRANCH_XID); - } - }; - List args = new ArrayList() { - { - add("branch"); - } - }; - LuaParser.jedisEvalSha(jedis, luaSHA, DELETE_TRANSACTION_DO_LUA_FILE_NAME, keys, args); - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - @Override - protected boolean updateBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String branchKey = buildBranchKey(branchTransactionDO.getBranchId()); - String branchStatus = String.valueOf(branchTransactionDO.getStatus()); - String applicationData = String.valueOf(branchTransactionDO.getApplicationData()); - String luaSHA = LOCK_SHA_MAP.get(UPDATE_BRANCH_TRANSACTION_DO_LUA_FILE_NAME); - if (luaSHA == null) { - return super.updateBranchTransactionDO(branchTransactionDO); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - List keys = new ArrayList() { - { - add(branchKey); - add(REDIS_KEY_BRANCH_STATUS); - add(REDIS_KEY_BRANCH_GMT_MODIFIED); - add(REDIS_KEY_BRANCH_APPLICATION_DATA); - } - }; - List args = new ArrayList() { - { - add(branchStatus); - add(String.valueOf((new Date()).getTime())); - add(applicationData); - } - }; - String result = (String) LuaParser.jedisEvalSha(jedis, luaSHA, UPDATE_BRANCH_TRANSACTION_DO_LUA_FILE_NAME, - keys, args); - LuaParser.LuaResult luaResult = LuaParser.getObjectFromJson(result, LuaParser.LuaResult.class); - if (!luaResult.getSuccess()) { - throw new StoreException("Branch transaction is not exist, update branch transaction failed."); - } - else { - return true; - } - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - @Override - protected boolean insertGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String globalKey = buildGlobalKeyByTransactionId(globalTransactionDO.getTransactionId()); - String globalStatus = buildGlobalStatus(globalTransactionDO.getStatus()); - String xid = globalTransactionDO.getXid(); - Date now = new Date(); - globalTransactionDO.setGmtCreate(now); - globalTransactionDO.setGmtModified(now); - Map globalTransactionDOMap = BeanUtils.objectToMap(globalTransactionDO); - String luaSHA = LOCK_SHA_MAP.get(INSERT_TRANSACTION_DO_LUA_FILE_NAME); - if (luaSHA == null) { - return super.insertGlobalTransactionDO(globalTransactionDO); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - // lua mode - List keys = new ArrayList() { - { - add(globalKey); - add(globalStatus); - } - }; - List args = new ArrayList() { - { - add("global"); - add(String.valueOf(globalTransactionDOMap.size())); - } - }; - for (Map.Entry entry : globalTransactionDOMap.entrySet()) { - keys.add(entry.getKey()); - args.add(entry.getValue()); - } - keys.add(REDIS_SEATA_BEGIN_TRANSACTIONS_KEY); - args.add(xid); - args.add(String.valueOf(globalTransactionDO.getBeginTime() + globalTransactionDO.getTimeout())); - LuaParser.jedisEvalSha(jedis, luaSHA, INSERT_TRANSACTION_DO_LUA_FILE_NAME, keys, args); - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - @Override - protected boolean deleteGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String globalKey = buildGlobalKeyByTransactionId(globalTransactionDO.getTransactionId()); - String globalStatus = buildGlobalStatus(globalTransactionDO.getStatus()); - String luaSHA = LOCK_SHA_MAP.get(DELETE_TRANSACTION_DO_LUA_FILE_NAME); - if (luaSHA == null) { - return super.deleteGlobalTransactionDO(globalTransactionDO); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - // lua mode - List keys = new ArrayList() { - { - add(globalKey); - add(globalStatus); - add(REDIS_KEY_GLOBAL_XID); - add(REDIS_SEATA_BEGIN_TRANSACTIONS_KEY); - } - }; - List args = new ArrayList() { - { - add("global"); - add(globalTransactionDO.getXid()); - add(String.valueOf(globalTransactionDO.getStatus())); - } - }; - LuaParser.jedisEvalSha(jedis, luaSHA, DELETE_TRANSACTION_DO_LUA_FILE_NAME, keys, args); - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - @Override - protected boolean updateGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String xid = globalTransactionDO.getXid(); - String globalKey = buildGlobalKeyByTransactionId(globalTransactionDO.getTransactionId()); - Integer status = globalTransactionDO.getStatus(); - - String luaSHA = LOCK_SHA_MAP.get(UPDATE_GLOBAL_TRANSACTION_DO_LUA_FILE_NAME); - if (luaSHA == null) { - return super.updateGlobalTransactionDO(globalTransactionDO); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - List keys = new ArrayList() { - { - add(globalKey); - add(REDIS_KEY_GLOBAL_STATUS); - add(REDIS_KEY_GLOBAL_GMT_MODIFIED); - add(REDIS_SEATA_BEGIN_TRANSACTIONS_KEY); - } - }; - List args = new ArrayList() { - { - add(String.valueOf(status)); - add(String.valueOf((new Date()).getTime())); - add(xid); - } - }; - String result = (String) LuaParser.jedisEvalSha(jedis, luaSHA, UPDATE_GLOBAL_TRANSACTION_DO_LUA_FILE_NAME, - keys, args); - LuaParser.LuaResult luaResult = LuaParser.getObjectFromJson(result, LuaParser.LuaResult.class); - // fail - if (!luaResult.getSuccess()) { - String type = luaResult.getStatus(); - if (LuaParser.LuaErrorStatus.XID_NOT_EXISTED.equals(type)) { - throw new StoreException("Global transaction is not exist, update global transaction failed."); - } - else if (LuaParser.LuaErrorStatus.ILLEGAL_CHANGE_STATUS.equals(type)) { - String previousStatus = luaResult.getData(); - GlobalStatus before = GlobalStatus.get(Integer.parseInt(previousStatus)); - GlobalStatus after = GlobalStatus.get(status); - throw new StoreException( - "Illegal changing of global status, update global transaction failed." + " beforeStatus[" - + before.name() + "] cannot be changed to afterStatus[" + after.name() + "]"); - } - } - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManager.java deleted file mode 100644 index 73aabc929e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManager.java +++ /dev/null @@ -1,861 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis.store; - -import com.google.common.collect.ImmutableMap; -import io.seata.common.XID; -import io.seata.common.exception.RedisException; -import io.seata.common.exception.StoreException; -import io.seata.common.util.BeanUtils; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.model.GlobalStatus; -import io.seata.core.store.BranchTransactionDO; -import io.seata.core.store.GlobalTransactionDO; -import io.seata.server.console.param.GlobalSessionParam; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.session.SessionStatusValidator; -import io.seata.server.storage.SessionConverter; -import io.seata.server.storage.redis.JedisPooledFactory; -import io.seata.server.store.AbstractTransactionStoreManager; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.Pipeline; -import redis.clients.jedis.Transaction; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static io.seata.common.ConfigurationKeys.STORE_REDIS_QUERY_LIMIT; -import static io.seata.common.DefaultValues.DEFAULT_QUERY_LIMIT; -import static io.seata.core.constants.RedisKeyConstants.*; - -/** - * The redis transaction store manager - * - * @author funkye - * @author wangzhongxiang - * @author doubleDimple - * @author conghuhu - */ -public class RedisTransactionStoreManager extends AbstractTransactionStoreManager implements TransactionStoreManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(RedisTransactionStoreManager.class); - - /** - * the prefix of the branch transactions - */ - private static final String REDIS_SEATA_BRANCHES_PREFIX = "SEATA_BRANCHES_"; - - /** - * the prefix of the branch transaction - */ - private static final String REDIS_SEATA_BRANCH_PREFIX = "SEATA_BRANCH_"; - - /** - * the prefix of the global transaction - */ - private static final String REDIS_SEATA_GLOBAL_PREFIX = "SEATA_GLOBAL_"; - - /** - * the prefix of the global transaction status - */ - private static final String REDIS_SEATA_STATUS_PREFIX = "SEATA_STATUS_"; - - /** the key of global transaction status for begin */ - protected static final String REDIS_SEATA_BEGIN_TRANSACTIONS_KEY = "SEATA_BEGIN_TRANSACTIONS"; - - private static volatile RedisTransactionStoreManager instance; - - private static final String OK = "OK"; - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The Log query limit. - */ - protected int logQueryLimit; - - /** - * Get the instance. - */ - public static RedisTransactionStoreManager getInstance() { - if (instance == null) { - synchronized (RedisTransactionStoreManager.class) { - if (instance == null) { - instance = new RedisTransactionStoreManager(); - } - } - } - return instance; - } - - /** - * init map to constructor - */ - public RedisTransactionStoreManager() { - super(); - initGlobalMap(); - initBranchMap(); - initLogQueryLimit(); - } - - protected void initLogQueryLimit() { - logQueryLimit = CONFIG.getInt(STORE_REDIS_QUERY_LIMIT, DEFAULT_QUERY_LIMIT); - } - - /** - * Map for LogOperation Global Operation - */ - public static volatile ImmutableMap> globalMap; - - /** - * Map for LogOperation Branch Operation - */ - public static volatile ImmutableMap> branchMap; - - /** - * init globalMap - */ - public void initGlobalMap() { - if (CollectionUtils.isEmpty(branchMap)) { - globalMap = ImmutableMap.>builder() - .put(LogOperation.GLOBAL_ADD, this::insertGlobalTransactionDO) - .put(LogOperation.GLOBAL_UPDATE, this::updateGlobalTransactionDO) - .put(LogOperation.GLOBAL_REMOVE, this::deleteGlobalTransactionDO) - .build(); - } - } - - /** - * init branchMap - */ - public void initBranchMap() { - if (CollectionUtils.isEmpty(branchMap)) { - branchMap = ImmutableMap.>builder() - .put(LogOperation.BRANCH_ADD, this::insertBranchTransactionDO) - .put(LogOperation.BRANCH_UPDATE, this::updateBranchTransactionDO) - .put(LogOperation.BRANCH_REMOVE, this::deleteBranchTransactionDO) - .build(); - } - } - - @Override - public boolean writeSession(LogOperation logOperation, SessionStorable session) { - if (globalMap.containsKey(logOperation) || branchMap.containsKey(logOperation)) { - return globalMap.containsKey(logOperation) - ? globalMap.get(logOperation).apply(SessionConverter.convertGlobalTransactionDO(session)) - : branchMap.get(logOperation).apply(SessionConverter.convertBranchTransactionDO(session)); - } - else { - throw new StoreException("Unknown LogOperation:" + logOperation.name()); - } - } - - /** - * Insert branch transaction - * @param branchTransactionDO - * @return the boolean - */ - protected boolean insertBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String branchKey = buildBranchKey(branchTransactionDO.getBranchId()); - String branchListKey = buildBranchListKeyByXid(branchTransactionDO.getXid()); - try (Jedis jedis = JedisPooledFactory.getJedisInstance(); Pipeline pipelined = jedis.pipelined()) { - Date now = new Date(); - branchTransactionDO.setGmtCreate(now); - branchTransactionDO.setGmtModified(now); - pipelined.hmset(branchKey, BeanUtils.objectToMap(branchTransactionDO)); - pipelined.rpush(branchListKey, branchKey); - pipelined.sync(); - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - /** - * Delete the branch transaction - * @param branchTransactionDO - * @return - */ - protected boolean deleteBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String branchKey = buildBranchKey(branchTransactionDO.getBranchId()); - String branchListKey = buildBranchListKeyByXid(branchTransactionDO.getXid()); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - String xid = jedis.hget(branchKey, REDIS_KEY_BRANCH_XID); - if (StringUtils.isEmpty(xid)) { - return true; - } - try (Pipeline pipelined = jedis.pipelined()) { - pipelined.lrem(branchListKey, 0, branchKey); - pipelined.del(branchKey); - pipelined.sync(); - } - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - /** - * Update the branch transaction - * @param branchTransactionDO - * @return - */ - protected boolean updateBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String branchKey = buildBranchKey(branchTransactionDO.getBranchId()); - String branchStatus = String.valueOf(branchTransactionDO.getStatus()); - String applicationData = String.valueOf(branchTransactionDO.getApplicationData()); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - String previousBranchStatus = jedis.hget(branchKey, REDIS_KEY_BRANCH_STATUS); - if (StringUtils.isEmpty(previousBranchStatus)) { - throw new StoreException("Branch transaction is not exist, update branch transaction failed."); - } - Map map = new HashMap<>(3, 1); - map.put(REDIS_KEY_BRANCH_STATUS, branchStatus); - map.put(REDIS_KEY_BRANCH_GMT_MODIFIED, String.valueOf((new Date()).getTime())); - if (StringUtils.isNotBlank(branchTransactionDO.getApplicationData())) { - map.put(REDIS_KEY_BRANCH_APPLICATION_DATA, applicationData); - } - jedis.hmset(branchKey, map); - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - /** - * Insert the global transaction. - * @param globalTransactionDO - * @return - */ - protected boolean insertGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String globalKey = buildGlobalKeyByTransactionId(globalTransactionDO.getTransactionId()); - try (Jedis jedis = JedisPooledFactory.getJedisInstance(); Pipeline pipelined = jedis.pipelined()) { - Date now = new Date(); - globalTransactionDO.setGmtCreate(now); - globalTransactionDO.setGmtModified(now); - pipelined.hmset(globalKey, BeanUtils.objectToMap(globalTransactionDO)); - String xid = globalTransactionDO.getXid(); - pipelined.rpush(buildGlobalStatus(globalTransactionDO.getStatus()), xid); - pipelined.zadd(REDIS_SEATA_BEGIN_TRANSACTIONS_KEY, - globalTransactionDO.getBeginTime() + globalTransactionDO.getTimeout(), globalKey); - pipelined.sync(); - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - /** - * Delete the global transaction. It will operate two parts: 1.delete the global - * session map 2.remove the xid from the global status list If the operate failed,the - * succeed operates will rollback - * @param globalTransactionDO - * @return - */ - protected boolean deleteGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String globalKey = buildGlobalKeyByTransactionId(globalTransactionDO.getTransactionId()); - String globalStatus = buildGlobalStatus(globalTransactionDO.getStatus()); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - // pipeline mode - String xid = jedis.hget(globalKey, REDIS_KEY_GLOBAL_XID); - if (StringUtils.isEmpty(xid)) { - LOGGER.warn("Global transaction is not exist,xid = {}.Maybe has been deleted by another tc server", - globalTransactionDO.getXid()); - return true; - } - try (Pipeline pipelined = jedis.pipelined()) { - pipelined.lrem(globalStatus, 0, globalTransactionDO.getXid()); - pipelined.del(globalKey); - if (GlobalStatus.Begin.getCode() == globalTransactionDO.getStatus() - || GlobalStatus.UnKnown.getCode() == globalTransactionDO.getStatus()) { - pipelined.zrem(REDIS_SEATA_BEGIN_TRANSACTIONS_KEY, globalKey); - } - pipelined.sync(); - } - return true; - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - /** - * Update the global transaction. It will update two parts: 1.the global session map - * 2.the global status list If the update failed,the succeed operates will rollback - * @param globalTransactionDO 全局事务参数 - * @return 修改结果 - */ - protected boolean updateGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String xid = globalTransactionDO.getXid(); - String globalKey = buildGlobalKeyByTransactionId(globalTransactionDO.getTransactionId()); - Integer status = globalTransactionDO.getStatus(); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - // Defensive watch to prevent other TC server operating concurrently,Fail fast - jedis.watch(globalKey); - List statusAndGmtModified = jedis.hmget(globalKey, REDIS_KEY_GLOBAL_STATUS, - REDIS_KEY_GLOBAL_GMT_MODIFIED); - String previousStatus = statusAndGmtModified.get(0); - if (StringUtils.isEmpty(previousStatus)) { - jedis.unwatch(); - throw new StoreException("Global transaction is not exist, update global transaction failed."); - } - if (previousStatus.equals(String.valueOf(status))) { - jedis.unwatch(); - return true; - } - GlobalStatus before = GlobalStatus.get(Integer.parseInt(previousStatus)); - GlobalStatus after = GlobalStatus.get(status); - if (!SessionStatusValidator.validateUpdateStatus(before, after)) { - throw new StoreException( - "Illegal changing of global status, update global transaction failed." + " beforeStatus[" - + before.name() + "] cannot be changed to afterStatus[" + after.name() + "]"); - } - - String previousGmtModified = statusAndGmtModified.get(1); - Transaction multi = jedis.multi(); - Map map = new HashMap<>(2); - map.put(REDIS_KEY_GLOBAL_STATUS, String.valueOf(globalTransactionDO.getStatus())); - map.put(REDIS_KEY_GLOBAL_GMT_MODIFIED, String.valueOf((new Date()).getTime())); - multi.hmset(globalKey, map); - multi.lrem(buildGlobalStatus(Integer.valueOf(previousStatus)), 0, xid); - multi.rpush(buildGlobalStatus(globalTransactionDO.getStatus()), xid); - multi.zrem(REDIS_SEATA_BEGIN_TRANSACTIONS_KEY, globalKey); - List exec = multi.exec(); - if (CollectionUtils.isEmpty(exec)) { - // The data has changed by another tc, so we still think the modification - // is successful. - LOGGER.warn( - "The global transaction xid = {}, maybe changed by another TC. It does not affect the results", - xid); - return true; - } - String hmset = exec.get(0).toString(); - long lrem = (long) exec.get(1); - long rpush = (long) exec.get(2); - if (OK.equalsIgnoreCase(hmset) && lrem > 0 && rpush > 0) { - return true; - } - else { - // pipeline mode - if (OK.equalsIgnoreCase(hmset)) { - // Defensive watch to prevent other TC server operating - // concurrently,give up this operate - jedis.watch(globalKey); - String xid2 = jedis.hget(globalKey, REDIS_KEY_GLOBAL_XID); - if (StringUtils.isNotEmpty(xid2)) { - Map mapPrevious = new HashMap<>(2, 1); - mapPrevious.put(REDIS_KEY_GLOBAL_STATUS, previousStatus); - mapPrevious.put(REDIS_KEY_GLOBAL_GMT_MODIFIED, previousGmtModified); - Transaction multi2 = jedis.multi(); - multi2.hmset(globalKey, mapPrevious); - multi2.exec(); - } - } - if (lrem > 0) { - jedis.rpush(buildGlobalStatus(Integer.valueOf(previousStatus)), xid); - } - if (rpush > 0) { - jedis.lrem(buildGlobalStatus(status), 0, xid); - } - return false; - } - } - catch (Exception ex) { - throw new RedisException(ex); - } - } - - /** - * Read session global session. - * @param xid the xid - * @param withBranchSessions the withBranchSessions - * @return the global session - */ - @Override - public GlobalSession readSession(String xid, boolean withBranchSessions) { - String transactionId = String.valueOf(XID.getTransactionId(xid)); - String globalKey = buildGlobalKeyByTransactionId(transactionId); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - Map map = jedis.hgetAll(globalKey); - if (CollectionUtils.isEmpty(map)) { - return null; - } - GlobalTransactionDO globalTransactionDO = (GlobalTransactionDO) BeanUtils.mapToObject(map, - GlobalTransactionDO.class); - List branchTransactionDOs = null; - if (withBranchSessions) { - branchTransactionDOs = this.readBranchSessionByXid(jedis, xid); - } - GlobalSession session = getGlobalSession(globalTransactionDO, branchTransactionDOs, withBranchSessions); - return session; - } - } - - /** - * Read session global session. - * @param xid the xid - * @return the global session - */ - @Override - public GlobalSession readSession(String xid) { - return this.readSession(xid, true); - } - - /** - * Read globalSession list by global status - * @param statuses the statuses - * @return the list - */ - @Override - public List readSession(GlobalStatus[] statuses, boolean withBranchSessions) { - List globalSessions = Collections.synchronizedList(new ArrayList<>()); - List statusKeys = convertStatusKeys(statuses); - Map targetMap = calculateStatuskeysHasData(statusKeys); - if (targetMap.size() == 0 || logQueryLimit <= 0) { - return globalSessions; - } - int perStatusLimit = resetLogQueryLimit(targetMap); - final long countGlobalSessions = targetMap.values() - .stream() - .collect(Collectors.summarizingInt(Integer::intValue)) - .getSum(); - // queryCount. - final long queryCount = Math.min(logQueryLimit, countGlobalSessions); - List> list = new ArrayList<>(); - dogetXidsForTargetMapRecursive(targetMap, 0L, perStatusLimit - 1, queryCount, list); - if (CollectionUtils.isNotEmpty(list)) { - List xids = list.stream().flatMap(Collection::stream).collect(Collectors.toList()); - xids.parallelStream().forEach(xid -> { - GlobalSession globalSession = this.readSession(xid, withBranchSessions); - if (globalSession != null) { - globalSessions.add(globalSession); - } - }); - } - return globalSessions; - } - - @Override - public List readSortByTimeoutBeginSessions(boolean withBranchSessions) { - List list = Collections.emptyList(); - List statusKeys = convertStatusKeys(GlobalStatus.Begin); - Map targetMap = calculateStatuskeysHasData(statusKeys); - if (targetMap.size() == 0 || logQueryLimit <= 0) { - return list; - } - final long countGlobalSessions = targetMap.values() - .stream() - .collect(Collectors.summarizingInt(Integer::intValue)) - .getSum(); - // queryCount - final long queryCount = Math.min(logQueryLimit, countGlobalSessions); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - Set values = jedis.zrangeByScore(REDIS_SEATA_BEGIN_TRANSACTIONS_KEY, 0, System.currentTimeMillis(), - 0, (int) queryCount); - List> rep; - try (Pipeline pipeline = jedis.pipelined()) { - for (String value : values) { - pipeline.hgetAll(value); - } - rep = (List>) (List) pipeline.syncAndReturnAll(); - } - list = rep.stream().map(map -> { - GlobalTransactionDO globalTransactionDO = (GlobalTransactionDO) BeanUtils.mapToObject(map, - GlobalTransactionDO.class); - if (globalTransactionDO != null) { - String xid = globalTransactionDO.getXid(); - List branchTransactionDOs = new ArrayList<>(); - if (withBranchSessions) { - branchTransactionDOs = this.readBranchSessionByXid(jedis, xid); - } - return getGlobalSession(globalTransactionDO, branchTransactionDOs, withBranchSessions); - } - return null; - }).filter(Objects::nonNull).collect(Collectors.toList()); - } - return list; - } - - /** - * get everyone keys limit - * @param targetMap - * @return - */ - private int resetLogQueryLimit(Map targetMap) { - int resetLimitQuery = logQueryLimit; - if (targetMap.size() > 1) { - int size = targetMap.size(); - resetLimitQuery = (logQueryLimit / size) == 0 ? 1 : (logQueryLimit / size); - } - return resetLimitQuery; - } - - /** - * read the global session list by different condition. - * @param sessionCondition the session condition - * @return the global sessions - */ - @Override - public List readSession(SessionCondition sessionCondition) { - List globalSessions = new ArrayList<>(); - if (StringUtils.isNotEmpty(sessionCondition.getXid())) { - GlobalSession globalSession = this.readSession(sessionCondition.getXid(), - !sessionCondition.isLazyLoadBranch()); - if (globalSession != null) { - globalSessions.add(globalSession); - } - return globalSessions; - } - else if (sessionCondition.getTransactionId() != null) { - GlobalSession globalSession = this.readSessionByTransactionId( - sessionCondition.getTransactionId().toString(), !sessionCondition.isLazyLoadBranch()); - if (globalSession != null) { - globalSessions.add(globalSession); - } - return globalSessions; - } - else if (CollectionUtils.isNotEmpty(sessionCondition.getStatuses())) { - if (sessionCondition.getStatuses().length == 1 && sessionCondition.getStatuses()[0] == GlobalStatus.Begin) { - return this.readSortByTimeoutBeginSessions(!sessionCondition.isLazyLoadBranch()); - } - else { - return readSession(sessionCondition.getStatuses(), !sessionCondition.isLazyLoadBranch()); - } - } - return null; - } - - /** - * query GlobalSession by status with page - * @param param - * @return List - */ - public List readSessionStatusByPage(GlobalSessionParam param) { - List globalSessions = new ArrayList<>(); - - int pageNum = param.getPageNum(); - int pageSize = param.getPageSize(); - int start = Math.max((pageNum - 1) * pageSize, 0); - int end = pageNum * pageSize - 1; - - if (param.getStatus() != null) { - String statusKey = buildGlobalStatus(GlobalStatus.get(param.getStatus()).getCode()); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - final List xids = jedis.lrange(statusKey, start, end); - xids.forEach(xid -> { - GlobalSession globalSession = this.readSession(xid, param.isWithBranch()); - if (globalSession != null) { - globalSessions.add(globalSession); - } - }); - } - } - return globalSessions; - } - - /** - * assemble the global session and branch session - * @param globalTransactionDO the global transactionDo - * @param branchTransactionDOs the branch transactionDos - * @param withBranchSessions if read branch sessions - * @return the global session with branch session - */ - private GlobalSession getGlobalSession(GlobalTransactionDO globalTransactionDO, - List branchTransactionDOs, boolean withBranchSessions) { - GlobalSession globalSession = SessionConverter.convertGlobalSession(globalTransactionDO, !withBranchSessions); - if (CollectionUtils.isNotEmpty(branchTransactionDOs)) { - for (BranchTransactionDO branchTransactionDO : branchTransactionDOs) { - globalSession.add(SessionConverter.convertBranchSession(branchTransactionDO)); - } - } - return globalSession; - } - - /** - * read the global session by transactionId - * @param transactionId the transaction id - * @param withBranchSessions if read branch sessions - * @return the global session - */ - private GlobalSession readSessionByTransactionId(String transactionId, boolean withBranchSessions) { - String globalKey = buildGlobalKeyByTransactionId(transactionId); - String xid = null; - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - Map map = jedis.hgetAll(globalKey); - if (CollectionUtils.isEmpty(map)) { - return null; - } - GlobalTransactionDO globalTransactionDO = (GlobalTransactionDO) BeanUtils.mapToObject(map, - GlobalTransactionDO.class); - if (globalTransactionDO != null) { - xid = globalTransactionDO.getXid(); - } - List branchTransactionDOs = new ArrayList<>(); - if (withBranchSessions) { - branchTransactionDOs = this.readBranchSessionByXid(jedis, xid); - } - return getGlobalSession(globalTransactionDO, branchTransactionDOs, withBranchSessions); - } - } - - /** - * Read the branch session list by xid - * @param jedis the jedis - * @param xid the xid - * @return the branch transactionDo list - */ - private List readBranchSessionByXid(Jedis jedis, String xid) { - List branchTransactionDOs = new ArrayList<>(); - String branchListKey = buildBranchListKeyByXid(xid); - List branchKeys = lRange(jedis, branchListKey); - if (CollectionUtils.isNotEmpty(branchKeys)) { - try (Pipeline pipeline = jedis.pipelined()) { - branchKeys.stream().forEach(branchKey -> pipeline.hgetAll(branchKey)); - List branchInfos = pipeline.syncAndReturnAll(); - for (Object branchInfo : branchInfos) { - if (branchInfo != null) { - Map branchInfoMap = (Map) branchInfo; - Optional branchTransactionDO = Optional.ofNullable( - (BranchTransactionDO) BeanUtils.mapToObject(branchInfoMap, BranchTransactionDO.class)); - branchTransactionDO.ifPresent(branchTransactionDOs::add); - } - } - } - } - if (CollectionUtils.isNotEmpty(branchTransactionDOs)) { - Collections.sort(branchTransactionDOs); - } - return branchTransactionDOs; - } - - private List lRange(Jedis jedis, String key) { - List keys = new ArrayList<>(); - List values; - int limit = 20; - int start = 0; - int stop = limit; - for (;;) { - values = jedis.lrange(key, start, stop); - keys.addAll(values); - if (CollectionUtils.isEmpty(values) || values.size() < limit) { - break; - } - start = keys.size(); - stop = start + limit; - } - return keys; - } - - public List findBranchSessionByXid(String xid) { - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - return readBranchSessionByXid(jedis, xid); - } - } - - /** - * query globalSession by page - * @param pageNum - * @param pageSize - * @param withBranchSessions - * @return List - */ - public List findGlobalSessionByPage(int pageNum, int pageSize, boolean withBranchSessions) { - List globalSessions = new ArrayList<>(); - int start = Math.max((pageNum - 1) * pageSize, 0); - int end = pageNum * pageSize - 1; - - List statusKeys = convertStatusKeys(GlobalStatus.values()); - Map stringLongMap = calculateStatuskeysHasData(statusKeys); - - List> list = dogetXidsForTargetMap(stringLongMap, start, end, pageSize); - - if (CollectionUtils.isNotEmpty(list)) { - List xids = list.stream().flatMap(Collection::stream).collect(Collectors.toList()); - xids.forEach(xid -> { - if (globalSessions.size() < pageSize) { - GlobalSession globalSession = this.readSession(xid, withBranchSessions); - if (globalSession != null) { - globalSessions.add(globalSession); - } - } - }); - } - return globalSessions; - } - - /** - * query and sort existing values - * @param statusKeys - * @return - */ - private Map calculateStatuskeysHasData(List statusKeys) { - Map resultMap = new LinkedHashMap<>(); - Map keysMap = new HashMap<>(statusKeys.size()); - try (Jedis jedis = JedisPooledFactory.getJedisInstance(); Pipeline pipelined = jedis.pipelined()) { - statusKeys.forEach(key -> pipelined.llen(key)); - List counts = (List) pipelined.syncAndReturnAll(); - for (int i = 0; i < counts.size(); i++) { - if (counts.get(i) > 0) { - keysMap.put(statusKeys.get(i), counts.get(i).intValue()); - } - } - } - - // sort - List> list = new ArrayList<>(keysMap.entrySet()); - list.sort((o1, o2) -> o2.getValue() - o1.getValue()); - list.forEach(e -> resultMap.put(e.getKey(), e.getValue())); - - return resultMap; - } - - /** - * count GlobalSession total by status - * @param values - * @return Long - */ - public Long countByGlobalSessions(GlobalStatus[] values) { - List statusKeys = new ArrayList<>(); - Long total = 0L; - for (GlobalStatus status : values) { - statusKeys.add(buildGlobalStatus(status.getCode())); - } - try (Jedis jedis = JedisPooledFactory.getJedisInstance(); Pipeline pipelined = jedis.pipelined()) { - statusKeys.stream().forEach(statusKey -> pipelined.llen(statusKey)); - List list = (List) (List) pipelined.syncAndReturnAll(); - if (list.size() > 0) { - total = list.stream().mapToLong(value -> value).sum(); - } - return total; - } - } - - private List convertStatusKeys(GlobalStatus... statuses) { - List statusKeys = new ArrayList<>(); - for (int i = 0; i < statuses.length; i++) { - statusKeys.add(buildGlobalStatus(statuses[i].getCode())); - } - return statusKeys; - } - - private void dogetXidsForTargetMapRecursive(Map targetMap, long start, long end, long queryCount, - List> listList) { - - long total = listList.stream().mapToLong(List::size).sum(); - - if (total >= queryCount) { - return; - } - // when start greater than offset(totalCount) - if (start >= queryCount) { - return; - } - - if (targetMap.size() == 0) { - return; - } - - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - Iterator> iterator = targetMap.entrySet().iterator(); - while (iterator.hasNext()) { - String key = iterator.next().getKey(); - final long sum = listList.stream().mapToLong(List::size).sum(); - final long diffCount = queryCount - sum; - if (diffCount <= 0) { - return; - } - List list; - if (end - start >= diffCount) { - long endNew = start + diffCount - 1; - list = jedis.lrange(key, start, endNew); - } - else { - list = jedis.lrange(key, start, end); - } - - if (list.size() > 0) { - listList.add(list); - } - else { - iterator.remove(); - } - } - } - long startNew = end + 1; - long endNew = startNew + end - start; - dogetXidsForTargetMapRecursive(targetMap, startNew, endNew, queryCount, listList); - } - - private List> dogetXidsForTargetMap(Map targetMap, int start, int end, - int totalCount) { - List> listList = new ArrayList<>(); - try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { - for (String key : targetMap.keySet()) { - final List list = jedis.lrange(key, start, end); - final long sum = listList.stream().mapToLong(List::size).sum(); - if (list.size() > 0 && sum < totalCount) { - listList.add(list); - } - else { - start = 0; - end = totalCount - 1; - } - } - } - return listList; - } - - protected String buildBranchListKeyByXid(String xid) { - return REDIS_SEATA_BRANCHES_PREFIX + xid; - } - - protected String buildGlobalKeyByTransactionId(Object transactionId) { - return REDIS_SEATA_GLOBAL_PREFIX + transactionId; - } - - protected String buildBranchKey(Long branchId) { - return REDIS_SEATA_BRANCH_PREFIX + branchId; - } - - protected String buildGlobalStatus(Integer status) { - return REDIS_SEATA_STATUS_PREFIX + status; - } - - /** - * Sets log query limit. - * @param logQueryLimit the log query limit - */ - public void setLogQueryLimit(int logQueryLimit) { - this.logQueryLimit = logQueryLimit; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManagerFactory.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManagerFactory.java deleted file mode 100644 index c4149608e5..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManagerFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.storage.redis.store; - -import io.seata.common.ConfigurationKeys; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; - -import static io.seata.common.Constants.STORE_REDIS_TYPE_PIPELINE; - -/** - * @author conghuhu - */ -public class RedisTransactionStoreManagerFactory { - - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - private static volatile RedisTransactionStoreManager instance; - - /** - * Get the instance. - */ - public static RedisTransactionStoreManager getInstance() { - if (instance == null) { - synchronized (RedisTransactionStoreManagerFactory.class) { - if (instance == null) { - String storeRedisType = CONFIG.getConfig(ConfigurationKeys.STORE_REDIS_TYPE, - STORE_REDIS_TYPE_PIPELINE); - instance = STORE_REDIS_TYPE_PIPELINE.equals(storeRedisType) ? new RedisTransactionStoreManager() - : new RedisLuaTransactionStoreManager(); - } - } - } - return instance; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/AbstractTransactionStoreManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/AbstractTransactionStoreManager.java deleted file mode 100644 index 1dda47e055..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/AbstractTransactionStoreManager.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import io.seata.core.model.GlobalStatus; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; - -import java.util.Collections; -import java.util.List; - -/** - * The type Abstract transaction store manager. - * - * @author zhangsen - */ -public abstract class AbstractTransactionStoreManager implements TransactionStoreManager { - - @Override - public GlobalSession readSession(String xid) { - return null; - } - - @Override - public GlobalSession readSession(String xid, boolean withBranchSessions) { - return null; - } - - @Override - public List readSortByTimeoutBeginSessions(boolean withBranchSessions) { - return Collections.emptyList(); - } - - @Override - public List readSession(GlobalStatus[] statuses, boolean withBranchSessions) { - return Collections.emptyList(); - } - - @Override - public List readSession(SessionCondition sessionCondition) { - return Collections.emptyList(); - } - - @Override - public void shutdown() { - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java deleted file mode 100644 index b4e10ab7e6..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import io.seata.common.loader.LoadLevel; -import io.seata.core.store.db.AbstractDataSourceProvider; -import org.apache.commons.dbcp2.BasicDataSource; - -import javax.sql.DataSource; -import java.sql.Connection; - -/** - * The dbcp datasource provider. - * - * @author zhangsen - * @author ggndnn - * @author will - */ -@LoadLevel(name = "dbcp") -public class DbcpDataSourceProvider extends AbstractDataSourceProvider { - - @Override - public DataSource generate() { - BasicDataSource ds = new BasicDataSource(); - ds.setDriverClassName(getDriverClassName()); - // DriverClassLoader works if upgrade commons-dbcp to at least 1.3.1. - // https://issues.apache.org/jira/browse/DBCP-333 - ds.setDriverClassLoader(getDriverClassLoader()); - ds.setUrl(getUrl()); - ds.setUsername(getUser()); - - ds.setPassword(getPassword()); - ds.setInitialSize(getMinConn()); - ds.setMaxTotal(getMaxConn()); - ds.setMinIdle(getMinConn()); - ds.setMaxIdle(getMinConn()); - ds.setMaxWaitMillis(getMaxWait()); - ds.setTimeBetweenEvictionRunsMillis(120000); - ds.setNumTestsPerEvictionRun(1); - ds.setTestWhileIdle(true); - ds.setValidationQuery(getValidationQuery(getDBType())); - ds.setConnectionProperties("useUnicode=yes;characterEncoding=utf8;socketTimeout=5000;connectTimeout=500"); - ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); - return ds; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/DruidDataSourceProvider.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/DruidDataSourceProvider.java deleted file mode 100644 index 29b8b41d70..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/DruidDataSourceProvider.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import javax.sql.DataSource; - -import io.seata.common.loader.LoadLevel; -import io.seata.core.store.db.AbstractDataSourceProvider; -import com.alibaba.druid.pool.DruidDataSource; - -import java.sql.Connection; - -/** - * The druid datasource provider. - * - * @author zhangsen - * @author ggndnn - * @author will - */ -@LoadLevel(name = "druid") -public class DruidDataSourceProvider extends AbstractDataSourceProvider { - - @Override - public DataSource generate() { - DruidDataSource ds = new DruidDataSource(); - ds.setDriverClassName(getDriverClassName()); - ds.setDriverClassLoader(getDriverClassLoader()); - ds.setUrl(getUrl()); - ds.setUsername(getUser()); - ds.setPassword(getPassword()); - ds.setInitialSize(getMinConn()); - ds.setMaxActive(getMaxConn()); - ds.setMinIdle(getMinConn()); - ds.setMaxWait(getMaxWait()); - ds.setTimeBetweenEvictionRunsMillis(120000); - ds.setMinEvictableIdleTimeMillis(300000); - ds.setTestWhileIdle(true); - ds.setTestOnBorrow(false); - ds.setPoolPreparedStatements(true); - ds.setMaxPoolPreparedStatementPerConnectionSize(20); - ds.setValidationQuery(getValidationQuery(getDBType())); - ds.setDefaultAutoCommit(true); - // fix issue 5030 - ds.setUseOracleImplicitCache(false); - ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); - return ds; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/HikariDataSourceProvider.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/HikariDataSourceProvider.java deleted file mode 100644 index 8f0e2795ac..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/HikariDataSourceProvider.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import com.zaxxer.hikari.util.IsolationLevel; -import io.seata.common.loader.LoadLevel; -import io.seata.core.store.db.AbstractDataSourceProvider; - -import javax.sql.DataSource; -import java.util.Properties; - -/** - * The hikari datasource provider. - * - * @author diguage - * @author will - */ -@LoadLevel(name = "hikari") -public class HikariDataSourceProvider extends AbstractDataSourceProvider { - - @Override - public DataSource generate() { - Properties properties = new Properties(); - properties.setProperty("dataSource.cachePrepStmts", "true"); - properties.setProperty("dataSource.prepStmtCacheSize", "250"); - properties.setProperty("dataSource.prepStmtCacheSqlLimit", "2048"); - properties.setProperty("dataSource.useServerPrepStmts", "true"); - properties.setProperty("dataSource.useLocalSessionState", "true"); - properties.setProperty("dataSource.rewriteBatchedStatements", "true"); - properties.setProperty("dataSource.cacheResultSetMetadata", "true"); - properties.setProperty("dataSource.cacheServerConfiguration", "true"); - properties.setProperty("dataSource.elideSetAutoCommits", "true"); - properties.setProperty("dataSource.maintainTimeStats", "false"); - - HikariConfig config = new HikariConfig(properties); - config.setDriverClassName(getDriverClassName()); - config.setJdbcUrl(getUrl()); - config.setUsername(getUser()); - config.setPassword(getPassword()); - config.setMaximumPoolSize(getMaxConn()); - config.setMinimumIdle(getMinConn()); - config.setAutoCommit(true); - config.setConnectionTimeout(getMaxWait()); - config.setInitializationFailTimeout(-1); - config.setTransactionIsolation(IsolationLevel.TRANSACTION_READ_COMMITTED.name()); - return new HikariDataSource(config); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/SessionStorable.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/SessionStorable.java deleted file mode 100644 index 727c6f94c7..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/SessionStorable.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -/** - * The interface Session storable. - * - * @author slievrly - */ -public interface SessionStorable { - - /** - * Encode byte [ ]. - * @return the byte [ ] - */ - byte[] encode(); - - /** - * Decode. - * @param src the src - */ - void decode(byte[] src); - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/StoreConfig.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/StoreConfig.java deleted file mode 100644 index ad09993d74..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/StoreConfig.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.server.env.ContainerHelper; -import io.seata.server.storage.file.FlushDiskMode; - -import static io.seata.common.DefaultValues.SERVER_DEFAULT_STORE_MODE; -import static io.seata.core.constants.ConfigurationKeys.STORE_FILE_PREFIX; - -/** - * @author lizhao - */ -public class StoreConfig { - - private static final Configuration CONFIGURATION = ConfigurationFactory.getInstance(); - - private static StoreMode storeMode; - - private static SessionMode sessionMode; - - private static LockMode lockMode; - - /** - * set storeMode sessionMode lockMode from StartupParameter. - * @param storeMode storeMode - * @param sessionMode sessionMode - * @param lockMode lockMode - */ - public static void setStartupParameter(String storeMode, String sessionMode, String lockMode) { - if (StringUtils.isNotBlank(storeMode)) { - StoreConfig.storeMode = StoreMode.get(storeMode); - } - if (StringUtils.isNotBlank(sessionMode)) { - StoreConfig.sessionMode = SessionMode.get(sessionMode); - } - if (StringUtils.isNotBlank(lockMode)) { - StoreConfig.lockMode = LockMode.get(lockMode); - } - } - - /** - * Default 16kb. - */ - private static final int DEFAULT_MAX_BRANCH_SESSION_SIZE = 1024 * 16; - - /** - * Default 512b. - */ - private static final int DEFAULT_MAX_GLOBAL_SESSION_SIZE = 512; - - /** - * Default 16kb. - */ - private static final int DEFAULT_WRITE_BUFFER_SIZE = 1024 * 16; - - public static int getMaxBranchSessionSize() { - return CONFIGURATION.getInt(STORE_FILE_PREFIX + "maxBranchSessionSize", DEFAULT_MAX_BRANCH_SESSION_SIZE); - } - - public static int getMaxGlobalSessionSize() { - return CONFIGURATION.getInt(STORE_FILE_PREFIX + "maxGlobalSessionSize", DEFAULT_MAX_GLOBAL_SESSION_SIZE); - } - - public static int getFileWriteBufferCacheSize() { - return CONFIGURATION.getInt(STORE_FILE_PREFIX + "fileWriteBufferCacheSize", DEFAULT_WRITE_BUFFER_SIZE); - } - - public static FlushDiskMode getFlushDiskMode() { - return FlushDiskMode.findDiskMode(CONFIGURATION.getConfig(STORE_FILE_PREFIX + "flushDiskMode")); - } - - /** - * only for inner call. - * @return StoreMode - */ - private static StoreMode getStoreMode() { - // startup - if (null != storeMode) { - return storeMode; - } - // env - String storeModeEnv = ContainerHelper.getStoreMode(); - if (StringUtils.isNotBlank(storeModeEnv)) { - return StoreMode.get(storeModeEnv); - } - // config - String storeModeConfig = CONFIGURATION.getConfig(ConfigurationKeys.STORE_MODE, SERVER_DEFAULT_STORE_MODE); - return StoreMode.get(storeModeConfig); - } - - public static SessionMode getSessionMode() { - // startup - if (null != sessionMode) { - return sessionMode; - } - // env - String sessionModeEnv = ContainerHelper.getSessionStoreMode(); - if (StringUtils.isNotBlank(sessionModeEnv)) { - return SessionMode.get(sessionModeEnv); - } - // config - String sessionModeConfig = CONFIGURATION.getConfig(ConfigurationKeys.STORE_SESSION_MODE); - if (StringUtils.isNotBlank(sessionModeConfig)) { - return SessionMode.get(sessionModeConfig); - } - // complication old config - return SessionMode.get(getStoreMode().name()); - } - - public static LockMode getLockMode() { - // startup - if (null != lockMode) { - return lockMode; - } - // env - String lockModeEnv = ContainerHelper.getLockStoreMode(); - if (StringUtils.isNotBlank(lockModeEnv)) { - return LockMode.get(lockModeEnv); - } - // config - String lockModeConfig = CONFIGURATION.getConfig(ConfigurationKeys.STORE_LOCK_MODE); - if (StringUtils.isNotBlank(lockModeConfig)) { - return LockMode.get(lockModeConfig); - } - // complication old config - return LockMode.get(getStoreMode().name()); - } - - public enum StoreMode { - - /** - * The File store mode. - */ - FILE("file"), - /** - * The Db store mode. - */ - DB("db"), - /** - * The Redis store mode. - */ - REDIS("redis"), - /** - * The Raft store mode. - */ - RAFT("raft"); - - private String name; - - StoreMode(String name) { - this.name = name; - } - - public static StoreMode get(String name) { - for (StoreMode mode : StoreMode.values()) { - if (mode.getName().equalsIgnoreCase(name)) { - return mode; - } - } - throw new IllegalArgumentException("unknown store mode:" + name); - } - - public String getName() { - return name; - } - - } - - public enum SessionMode { - - /** - * The File store mode. - */ - FILE("file"), - /** - * The Db store mode. - */ - DB("db"), - /** - * The Redis store mode. - */ - REDIS("redis"), - /** - * raft store. - */ - RAFT("raft"); - - private String name; - - SessionMode(String name) { - this.name = name; - } - - public static SessionMode get(String name) { - for (SessionMode mode : SessionMode.values()) { - if (mode.getName().equalsIgnoreCase(name)) { - return mode; - } - } - throw new IllegalArgumentException("unknown session mode:" + name); - } - - public String getName() { - return name; - } - - } - - public enum LockMode { - - /** - * The File store mode. - */ - FILE("file"), - /** - * The Db store mode. - */ - DB("db"), - /** - * The Redis store mode. - */ - REDIS("redis"), - /** - * raft store. - */ - RAFT("raft"); - - private String name; - - LockMode(String name) { - this.name = name; - } - - public static LockMode get(String name) { - for (LockMode mode : LockMode.values()) { - if (mode.getName().equalsIgnoreCase(name)) { - return mode; - } - } - throw new IllegalArgumentException("unknown lock mode:" + name); - } - - public String getName() { - return name; - } - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/TransactionStoreManager.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/TransactionStoreManager.java deleted file mode 100644 index 197582ad4e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/store/TransactionStoreManager.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import io.seata.core.model.GlobalStatus; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; - -import java.util.List; - -/** - * The interface Transaction store manager. - * - * @author slievrly - */ -public interface TransactionStoreManager { - - /** - * Write session boolean. - * @param logOperation the log operation - * @param session the session - * @return the boolean - */ - boolean writeSession(LogOperation logOperation, SessionStorable session); - - /** - * Read global session global session. - * @param xid the xid - * @return the global session - */ - GlobalSession readSession(String xid); - - /** - * Read session global session. - * @param xid the xid - * @param withBranchSessions the withBranchSessions - * @return the global session - */ - GlobalSession readSession(String xid, boolean withBranchSessions); - - /** - * Read session global session by sort by timeout begin status. - * @param withBranchSessions the withBranchSessions - * @return the global session - */ - List readSortByTimeoutBeginSessions(boolean withBranchSessions); - - /** - * Read session global session. - * @param statuses the statuses - * @param withBranchSessions the withBranchSessions - * @return the global session list - */ - List readSession(GlobalStatus[] statuses, boolean withBranchSessions); - - /** - * Read session by status list. - * @param sessionCondition the session condition - * @return the list - */ - List readSession(SessionCondition sessionCondition); - - /** - * Shutdown. - */ - void shutdown(); - - /** - * The enum Log operation. - */ - enum LogOperation { - - /** - * Global add log operation. - */ - GLOBAL_ADD((byte) 1), - /** - * Global update log operation. - */ - GLOBAL_UPDATE((byte) 2), - /** - * Global remove log operation. - */ - GLOBAL_REMOVE((byte) 3), - /** - * Branch add log operation. - */ - BRANCH_ADD((byte) 4), - /** - * Branch update log operation. - */ - BRANCH_UPDATE((byte) 5), - /** - * Branch remove log operation. - */ - BRANCH_REMOVE((byte) 6); - - private byte code; - - LogOperation(byte code) { - this.code = code; - } - - /** - * Gets code. - * @return the code - */ - public byte getCode() { - return this.code; - } - - /** - * Gets log operation by code. - * @param code the code - * @return the log operation by code - */ - public static LogOperation getLogOperationByCode(byte code) { - for (LogOperation temp : values()) { - if (temp.getCode() == code) { - return temp; - } - } - throw new IllegalArgumentException("Unknown LogOperation[" + code + "]"); - } - - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/at/ATCore.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/at/ATCore.java deleted file mode 100644 index 2606d6a785..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/at/ATCore.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.transaction.at; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.seata.common.exception.StoreException; -import io.seata.common.util.StringUtils; -import io.seata.core.exception.BranchTransactionException; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchType; -import io.seata.core.rpc.RemotingServer; -import io.seata.server.coordinator.AbstractCore; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; - -import static io.seata.common.Constants.AUTO_COMMIT; -import static io.seata.common.Constants.SKIP_CHECK_LOCK; -import static io.seata.core.exception.TransactionExceptionCode.LockKeyConflict; - -/** - * The type at core. - * - * @author ph3636 - */ -public class ATCore extends AbstractCore { - - private final ObjectMapper objectMapper = new ObjectMapper(); - - public ATCore(RemotingServer remotingServer) { - super(remotingServer); - } - - @Override - public BranchType getHandleBranchType() { - return BranchType.AT; - } - - @Override - protected void branchSessionLock(GlobalSession globalSession, BranchSession branchSession) - throws TransactionException { - String applicationData = branchSession.getApplicationData(); - boolean autoCommit = true; - boolean skipCheckLock = false; - if (StringUtils.isNotBlank(applicationData)) { - try { - Map data = objectMapper.readValue(applicationData, HashMap.class); - Object clientAutoCommit = data.get(AUTO_COMMIT); - if (clientAutoCommit != null && !(boolean) clientAutoCommit) { - autoCommit = (boolean) clientAutoCommit; - } - Object clientSkipCheckLock = data.get(SKIP_CHECK_LOCK); - if (clientSkipCheckLock instanceof Boolean) { - skipCheckLock = (boolean) clientSkipCheckLock; - } - } - catch (IOException e) { - LOGGER.error("failed to get application data: {}", e.getMessage(), e); - } - } - try { - if (!branchSession.lock(autoCommit, skipCheckLock)) { - throw new BranchTransactionException(LockKeyConflict, - String.format("Global lock acquire failed xid = %s branchId = %s", globalSession.getXid(), - branchSession.getBranchId())); - } - } - catch (StoreException e) { - Throwable cause = e.getCause(); - if (cause instanceof BranchTransactionException) { - throw new BranchTransactionException(((BranchTransactionException) cause).getCode(), - String.format("Global lock acquire failed xid = %s branchId = %s", globalSession.getXid(), - branchSession.getBranchId())); - } - throw e; - } - } - - @Override - protected void branchSessionUnlock(BranchSession branchSession) throws TransactionException { - branchSession.unlock(); - } - - @Override - public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys) - throws TransactionException { - return lockManager.isLockable(xid, resourceId, lockKeys); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/saga/SagaCore.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/saga/SagaCore.java deleted file mode 100644 index f96da096cc..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/saga/SagaCore.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.transaction.saga; - -import io.netty.channel.Channel; -import io.seata.common.util.CollectionUtils; -import io.seata.core.exception.GlobalTransactionException; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.core.protocol.transaction.BranchCommitRequest; -import io.seata.core.protocol.transaction.BranchCommitResponse; -import io.seata.core.protocol.transaction.BranchRollbackRequest; -import io.seata.core.protocol.transaction.BranchRollbackResponse; -import io.seata.core.rpc.RemotingServer; -import io.seata.core.rpc.netty.ChannelManager; -import io.seata.server.coordinator.AbstractCore; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHelper; -import io.seata.server.session.SessionHolder; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.TimeoutException; - -/** - * The type saga core. - * - * @author ph3636 - */ -public class SagaCore extends AbstractCore { - - public SagaCore(RemotingServer remotingServer) { - super(remotingServer); - } - - @Override - public BranchType getHandleBranchType() { - return BranchType.SAGA; - } - - @Override - public void globalSessionStatusCheck(GlobalSession globalSession) throws GlobalTransactionException { - // SAGA type accept forward(retry) operation on timeout or commit fail, forward - // operation will register remaining branches - } - - @Override - public BranchStatus branchCommitSend(BranchCommitRequest request, GlobalSession globalSession, - BranchSession branchSession) throws IOException, TimeoutException { - Map channels = ChannelManager.getRmChannels(); - if (CollectionUtils.isEmpty(channels)) { - LOGGER.error("Failed to commit SAGA global[" + globalSession.getXid() + ", RM channels is empty."); - return BranchStatus.PhaseTwo_CommitFailed_Retryable; - } - String sagaResourceId = getSagaResourceId(globalSession); - Channel sagaChannel = channels.get(sagaResourceId); - if (sagaChannel == null) { - LOGGER.error("Failed to commit SAGA global[" + globalSession.getXid() - + ", cannot find channel by resourceId[" + sagaResourceId + "]"); - return BranchStatus.PhaseTwo_CommitFailed_Retryable; - } - BranchCommitResponse response = (BranchCommitResponse) remotingServer.sendSyncRequest(sagaChannel, request); - return response.getBranchStatus(); - } - - @Override - public BranchStatus branchRollbackSend(BranchRollbackRequest request, GlobalSession globalSession, - BranchSession branchSession) throws IOException, TimeoutException { - Map channels = ChannelManager.getRmChannels(); - if (CollectionUtils.isEmpty(channels)) { - LOGGER.error("Failed to rollback SAGA global[" + globalSession.getXid() + ", RM channels is empty."); - return BranchStatus.PhaseTwo_RollbackFailed_Retryable; - } - String sagaResourceId = getSagaResourceId(globalSession); - Channel sagaChannel = channels.get(sagaResourceId); - if (sagaChannel == null) { - LOGGER.error("Failed to rollback SAGA global[" + globalSession.getXid() - + ", cannot find channel by resourceId[" + sagaResourceId + "]"); - return BranchStatus.PhaseTwo_RollbackFailed_Retryable; - } - BranchRollbackResponse response = (BranchRollbackResponse) remotingServer.sendSyncRequest(sagaChannel, request); - return response.getBranchStatus(); - } - - @Override - public boolean doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException { - try { - BranchStatus branchStatus = branchCommit(globalSession, SessionHelper.newBranch(BranchType.SAGA, - globalSession.getXid(), -1, getSagaResourceId(globalSession), globalSession.getStatus().name())); - - switch (branchStatus) { - case PhaseTwo_Committed: - SessionHelper.removeAllBranch(globalSession, !retrying); - LOGGER.info("Successfully committed SAGA global[" + globalSession.getXid() + "]"); - break; - case PhaseTwo_Rollbacked: - LOGGER.info("Successfully rollbacked SAGA global[" + globalSession.getXid() + "]"); - SessionHelper.removeAllBranch(globalSession, !retrying); - SessionHelper.endRollbacked(globalSession, retrying); - return false; - case PhaseTwo_RollbackFailed_Retryable: - LOGGER.error("By [{}], failed to rollback SAGA global [{}], will retry later.", branchStatus, - globalSession.getXid()); - SessionHolder.getRootSessionManager().removeGlobalSession(globalSession); - globalSession.queueToRetryRollback(); - return false; - case PhaseOne_Failed: - LOGGER.error("By [{}], finish SAGA global [{}]", branchStatus, globalSession.getXid()); - SessionHelper.removeAllBranch(globalSession, !retrying); - globalSession.changeGlobalStatus(GlobalStatus.Finished); - globalSession.end(); - return false; - case PhaseTwo_CommitFailed_Unretryable: - if (globalSession.canBeCommittedAsync()) { - LOGGER.error("By [{}], failed to commit SAGA global [{}]", branchStatus, - globalSession.getXid()); - break; - } - else { - SessionHelper.endCommitFailed(globalSession, retrying); - LOGGER.error("Finally, failed to commit SAGA global[{}]", globalSession.getXid()); - return false; - } - default: - if (!retrying) { - globalSession.queueToRetryCommit(); - } - else { - LOGGER.error("Failed to commit SAGA global[{}], will retry later.", globalSession.getXid()); - } - return false; - } - } - catch (Exception ex) { - LOGGER.error("Failed to commit global[" + globalSession.getXid() + "]", ex); - - if (!retrying) { - globalSession.queueToRetryRollback(); - } - throw new TransactionException(ex); - } - return true; - } - - @Override - public boolean doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException { - try { - BranchStatus branchStatus = branchRollback(globalSession, SessionHelper.newBranch(BranchType.SAGA, - globalSession.getXid(), -1, getSagaResourceId(globalSession), globalSession.getStatus().name())); - - switch (branchStatus) { - case PhaseTwo_Rollbacked: - SessionHelper.removeAllBranch(globalSession, !retrying); - LOGGER.info("Successfully rollbacked SAGA global[{}]", globalSession.getXid()); - break; - case PhaseTwo_RollbackFailed_Unretryable: - SessionHelper.endRollbackFailed(globalSession, retrying); - LOGGER.error("Failed to rollback SAGA global[{}]", globalSession.getXid()); - return false; - case PhaseTwo_CommitFailed_Retryable: - SessionHolder.getRootSessionManager().removeGlobalSession(globalSession); - globalSession.queueToRetryCommit(); - LOGGER.warn("Retry by custom recover strategy [Forward] on timeout, SAGA global[{}]", - globalSession.getXid()); - return false; - default: - LOGGER.error("Failed to rollback SAGA global[{}]", globalSession.getXid()); - if (!retrying) { - globalSession.queueToRetryRollback(); - } - return false; - } - } - catch (Exception ex) { - LOGGER.error("Failed to rollback global[{}]", globalSession.getXid(), ex); - if (!retrying) { - globalSession.queueToRetryRollback(); - } - throw new TransactionException(ex); - } - return true; - } - - @Override - public void doGlobalReport(GlobalSession globalSession, String xid, GlobalStatus globalStatus) - throws TransactionException { - if (GlobalStatus.Committed.equals(globalStatus)) { - SessionHelper.removeAllBranch(globalSession, false); - SessionHelper.endCommitted(globalSession, false); - LOGGER.info("Global[{}] committed", globalSession.getXid()); - } - else if (GlobalStatus.Rollbacked.equals(globalStatus) || GlobalStatus.Finished.equals(globalStatus)) { - SessionHelper.removeAllBranch(globalSession, false); - SessionHelper.endRollbacked(globalSession, false); - LOGGER.info("Global[{}] rollbacked", globalSession.getXid()); - } - else { - globalSession.changeGlobalStatus(globalStatus); - LOGGER.info("Global[{}] reporting is successfully done. status[{}]", globalSession.getXid(), - globalSession.getStatus()); - - if (GlobalStatus.RollbackRetrying.equals(globalStatus) - || GlobalStatus.TimeoutRollbackRetrying.equals(globalStatus) - || GlobalStatus.UnKnown.equals(globalStatus)) { - globalSession.queueToRetryRollback(); - LOGGER.info("Global[{}] will retry rollback", globalSession.getXid()); - } - else if (GlobalStatus.CommitRetrying.equals(globalStatus)) { - globalSession.queueToRetryCommit(); - LOGGER.info("Global[{}] will retry commit", globalSession.getXid()); - } - } - } - - /** - * get saga ResourceId. - * @param globalSession the globalSession - * @return sagaResourceId - */ - private String getSagaResourceId(GlobalSession globalSession) { - return globalSession.getApplicationId() + "#" + globalSession.getTransactionServiceGroup(); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/tcc/TccCore.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/tcc/TccCore.java deleted file mode 100644 index 6302c18d40..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/tcc/TccCore.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.transaction.tcc; - -import io.seata.core.model.BranchType; -import io.seata.core.rpc.RemotingServer; -import io.seata.server.coordinator.AbstractCore; - -/** - * The type tcc core. - * - * @author ph3636 - */ -public class TccCore extends AbstractCore { - - public TccCore(RemotingServer remotingServer) { - super(remotingServer); - } - - @Override - public BranchType getHandleBranchType() { - return BranchType.TCC; - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/xa/XACore.java b/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/xa/XACore.java deleted file mode 100644 index 5034b9cb72..0000000000 --- a/laokou-cloud/laokou-seata/src/main/java/io/seata/server/transaction/xa/XACore.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.transaction.xa; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.rpc.RemotingServer; -import io.seata.server.coordinator.AbstractCore; - -/** - * The type XA core. - * - * @author sharajava - */ -public class XACore extends AbstractCore { - - public XACore(RemotingServer remotingServer) { - super(remotingServer); - } - - @Override - public BranchType getHandleBranchType() { - return BranchType.XA; - } - - @Override - public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status, - String applicationData) throws TransactionException { - super.branchReport(branchType, xid, branchId, status, applicationData); - } - -} diff --git a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.rpc.RegisterCheckAuthHandler b/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.rpc.RegisterCheckAuthHandler deleted file mode 100644 index 1a54728bca..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.rpc.RegisterCheckAuthHandler +++ /dev/null @@ -1 +0,0 @@ -io.seata.server.auth.DefaultCheckAuthHandler \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.serializer.Serializer b/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.serializer.Serializer deleted file mode 100644 index 750cbc7d7d..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.serializer.Serializer +++ /dev/null @@ -1 +0,0 @@ -io.seata.server.cluster.raft.serializer.JacksonSerializer \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.store.DistributedLocker b/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.store.DistributedLocker deleted file mode 100644 index 8ce77186f8..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.store.DistributedLocker +++ /dev/null @@ -1,3 +0,0 @@ -io.seata.server.storage.redis.lock.RedisDistributedLocker -io.seata.server.storage.db.lock.DataBaseDistributedLocker -io.seata.server.storage.raft.lock.RaftDistributedLocker \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceProvider b/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceProvider deleted file mode 100644 index ac04a85e02..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceProvider +++ /dev/null @@ -1,3 +0,0 @@ -io.seata.server.store.DbcpDataSourceProvider -io.seata.server.store.DruidDataSourceProvider -io.seata.server.store.HikariDataSourceProvider \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.coordinator.AbstractCore b/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.coordinator.AbstractCore deleted file mode 100644 index a80662b025..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.coordinator.AbstractCore +++ /dev/null @@ -1,4 +0,0 @@ -io.seata.server.transaction.at.ATCore -io.seata.server.transaction.tcc.TccCore -io.seata.server.transaction.saga.SagaCore -io.seata.server.transaction.xa.XACore \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.lock.LockManager b/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.lock.LockManager deleted file mode 100644 index 2a1cfb1acc..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.lock.LockManager +++ /dev/null @@ -1,4 +0,0 @@ -io.seata.server.storage.db.lock.DataBaseLockManager -io.seata.server.storage.file.lock.FileLockManager -io.seata.server.storage.redis.lock.RedisLockManager -io.seata.server.storage.raft.lock.RaftLockManager \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.session.SessionManager b/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.session.SessionManager deleted file mode 100644 index 13b37775e3..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/META-INF/services/io.seata.server.session.SessionManager +++ /dev/null @@ -1,4 +0,0 @@ -io.seata.server.storage.file.session.FileSessionManager -io.seata.server.storage.db.session.DataBaseSessionManager -io.seata.server.storage.redis.session.RedisSessionManager -io.seata.server.storage.raft.session.RaftSessionManager \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/META-INF/spring-configuration-metadata.json b/laokou-cloud/laokou-seata/src/main/resources/META-INF/spring-configuration-metadata.json deleted file mode 100644 index 0544917752..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/META-INF/spring-configuration-metadata.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "groups": [], - "properties": [ - { - "name": "logging.extend.kafka-appender.bootstrap-servers", - "type": "java.lang.String", - "defaultValue": "localhost:9092" - }, - { - "name": "logging.extend.kafka-appender.topic", - "type": "java.lang.String", - "defaultValue": "logback_to_logstash" - }, - { - "name": "logging.extend.logstash-appender.destination", - "type": "java.lang.String", - "defaultValue": "localhost:4560" - } - ], - "hints": [ - ] -} \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/META-INF/spring.factories b/laokou-cloud/laokou-seata/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 3384008bf8..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,4 +0,0 @@ -org.springframework.context.ApplicationListener=\ -io.seata.server.spring.listener.ServerApplicationListener -org.springframework.context.ApplicationContextInitializer=\ -io.seata.server.spring.listener.SeataPropertiesLoader \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/application.yml b/laokou-cloud/laokou-seata/src/main/resources/application.yml deleted file mode 100644 index 601cbe9110..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/application.yml +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 1999-2019 Seata.io Group. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or ag`reed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -server: - port: ${SERVER_PORT:7091} - ssl: - # 开启证书 - enabled: @SSL-ENABLED@ - # 证书位置 - key-store: classpath:scg-keystore.p12 - # 证书别名 - key-alias: ${spring.application.name} - # 秘钥类型 - key-store-type: PKCS12 - # 证书密码 - key-store-password: laokou - http2: - enabled: @SSL-ENABLED@ - shutdown: graceful - undertow: - threads: - # 设置IO线程数,来执行非阻塞任务,负责多个连接数 - io: 16 - # 工作线程数 - worker: 256 - # 每块buffer的空间大小 - buffer-size: 1024 - # 分配堆外内存 - direct-buffers: true - accesslog: - enabled: true -jasypt: - encryptor: - algorithm: PBEWithMD5AndDES - iv-generator-classname: org.jasypt.iv.NoIvGenerator - password: @JASYPT-ENCRYPTOR-PASSWORD@ - -spring: - application: - name: @pom.artifactId@ - profiles: - active: @PROFILE-ACTIVE@ - -logging: - # config: classpath:logback-spring.xml - file: - path: @SEATA-LOG-PATH@ - extend: - logstash-appender: - destination: 127.0.0.1:4560 - kafka-appender: - bootstrap-servers: 127.0.0.1:9092 - topic: logback_to_logstash - -console: - user: - username: @SEATA-USERNAME@ - password: @SEATA-PASSWORD@ - -seata: - config: - type: nacos - nacos: - server-addr: @NACOS-CONFIG-ADDRESS@ - namespace: @NACOS-NAMESPACE@ - group: @SEATA-GROUP@ - username: @NACOS-USERNAME@ - password: @NACOS-PASSWORD@ - data-id: seataServer.properties - registry: - type: nacos - nacos: - server-addr: @NACOS-DISCOVERY-ADDRESS@ - group: @SEATA-GROUP@ - namespace: @NACOS-NAMESPACE@ - username: @NACOS-USERNAME@ - password: @NACOS-PASSWORD@ - security: - secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017 - tokenValidityInMilliseconds: 1800000 - ignore: - urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login diff --git a/laokou-cloud/laokou-seata/src/main/resources/banner.txt b/laokou-cloud/laokou-seata/src/main/resources/banner.txt deleted file mode 100644 index e561e763b5..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/banner.txt +++ /dev/null @@ -1,7 +0,0 @@ -███████╗███████╗ █████╗ ████████╗ █████╗ -██╔════╝██╔════╝██╔══██╗╚══██╔══╝██╔══██╗ -███████╗█████╗ ███████║ ██║ ███████║ -╚════██║██╔══╝ ██╔══██║ ██║ ██╔══██║ -███████║███████╗██║ ██║ ██║ ██║ ██║ -╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ - diff --git a/laokou-cloud/laokou-seata/src/main/resources/docker/seata-server-entrypoint.sh b/laokou-cloud/laokou-seata/src/main/resources/docker/seata-server-entrypoint.sh deleted file mode 100644 index af0f6934c9..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/docker/seata-server-entrypoint.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# Copyright 1999-2019 Seata.io Group. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# entrypoint for server - -. /seata-setup.sh -JAVA_OPT=${JAVA_OPT//"//"/"/"} -echo "Affected JVM parameters:$JAVA_OPT" -exec java $JAVA_OPT \ - -cp $( cat /seata-server/jib-classpath-file ) \ - $( cat /seata-server/jib-main-class-file ) diff --git a/laokou-cloud/laokou-seata/src/main/resources/logback-spring.xml b/laokou-cloud/laokou-seata/src/main/resources/logback-spring.xml deleted file mode 100644 index 490141ac6c..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - 0 - 2048 - true - - - - - true - 0 - 2048 - true - - - - true - 0 - 1024 - true - - - - true - 0 - 1024 - true - - - - - - - - - - - - - - - - - - - diff --git a/laokou-cloud/laokou-seata/src/main/resources/logback/console-appender.xml b/laokou-cloud/laokou-seata/src/main/resources/logback/console-appender.xml deleted file mode 100644 index 542b1b46af..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/logback/console-appender.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - ${CONSOLE_LOG_PATTERN} - UTF-8 - - - diff --git a/laokou-cloud/laokou-seata/src/main/resources/logback/file-appender.xml b/laokou-cloud/laokou-seata/src/main/resources/logback/file-appender.xml deleted file mode 100644 index 9225d75efc..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/logback/file-appender.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - ${LOG_FILE_PATH}/${APPLICATION_NAME:-seata-server}.${RPC_PORT}.all.log - true - - ${LOG_FILE_PATH}/history/${APPLICATION_NAME:-seata-server}.${RPC_PORT}.all.%d{yyyy-MM-dd}.%i.log.gz - 2GB - 7 - 7GB - true - - - ${FILE_LOG_PATTERN} - UTF-8 - - - - - - - WARN - ACCEPT - DENY - - ${LOG_FILE_PATH}/${APPLICATION_NAME:-seata-server}.${RPC_PORT}.warn.log - true - - ${LOG_FILE_PATH}/history/${APPLICATION_NAME:-seata-server}.${RPC_PORT}.warn.%d{yyyy-MM-dd}.%i.log.gz - 2GB - 7 - 7GB - true - - - ${FILE_LOG_PATTERN} - UTF-8 - - - - - - - ERROR - ACCEPT - DENY - - ${LOG_FILE_PATH}/${APPLICATION_NAME:-seata-server}.${RPC_PORT}.error.log - true - - ${LOG_FILE_PATH}/history/${APPLICATION_NAME:-seata-server}.${RPC_PORT}.error.%d{yyyy-MM-dd}.%i.log.gz - 2GB - 7 - 7GB - true - - - ${FILE_LOG_PATTERN} - UTF-8 - - - diff --git a/laokou-cloud/laokou-seata/src/main/resources/logback/kafka-appender.xml b/laokou-cloud/laokou-seata/src/main/resources/logback/kafka-appender.xml deleted file mode 100644 index a13000a237..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/logback/kafka-appender.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - { - "@timestamp": "%d{yyyy-MM-dd HH:mm:ss.SSS}", - "level":"%p", - "app_name":"${APPLICATION_NAME:-seata-server}", - "PORT": ${RPC_PORT:-0}, - "thread_name": "%t", - "logger_name": "%logger", - "X-TX-XID": "%X{X-TX-XID:-}", - "X-TX-BRANCH-ID": "%X{X-TX-BRANCH-ID:-}", - "message": "%m", - "stack_trace": "%wex" -} - - - ${KAFKA_TOPIC} - - - bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS} - acks=0 - linger.ms=1000 - max.block.ms=0 - - diff --git a/laokou-cloud/laokou-seata/src/main/resources/logback/logstash-appender.xml b/laokou-cloud/laokou-seata/src/main/resources/logback/logstash-appender.xml deleted file mode 100644 index 2c2f972157..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/logback/logstash-appender.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - ${LOGSTASH_DESTINATION} - - - - - - { - "app_name": "${APPLICATION_NAME:-seata-server}" - } - - - - net.logstash.logback.composite.LogstashVersionJsonProvider - - net.logstash.logback.composite.loggingevent.JsonMessageJsonProvider - net.logstash.logback.composite.loggingevent.TagsJsonProvider - net.logstash.logback.composite.loggingevent.LogstashMarkersJsonProvider - net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider - - - diff --git a/laokou-cloud/laokou-seata/src/main/resources/logback/metric-appender.xml b/laokou-cloud/laokou-seata/src/main/resources/logback/metric-appender.xml deleted file mode 100644 index 5527239e18..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/logback/metric-appender.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - diff --git a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/deleteTransactionDO.lua b/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/deleteTransactionDO.lua deleted file mode 100644 index 9845198e4d..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/deleteTransactionDO.lua +++ /dev/null @@ -1,56 +0,0 @@ --- Copyright 1999-2019 Seata.io Group. --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - --- User: conghuhu --- Date: 2022/7/25 - --- param description --- KEYS[1] branchOrGlobalKey --- KEYS[2] listKey --- KEYS[3] REDIS_KEY_BRANCH_XID/REDIS_KEY_GLOBAL_XID --- KEYS[4] REDIS_SEATA_BEGIN_TRANSACTIONS_KEY (only type is global) --- ARGV[1] type: global or branch --- ARGV[2] globalTransactionDO xid (only type is global) --- ARGV[3] globalTransactionDO status (only type is global) - --- init data -local branchOrGlobalKey = KEYS[1]; -local listKey = KEYS[2]; -local redisKeyXID = KEYS[3]; - -local type = ARGV[1]; - -local existedXid = redis.call('HGET', branchOrGlobalKey, redisKeyXID); - -if (not existedXid or string.len(tostring(existedXid)) == 0) -then - return 'true'; -end - -if (type == 'branch') then - redis.call('LREM', listKey, 0, branchOrGlobalKey); - redis.call('DEL', branchOrGlobalKey); -elseif (type == 'global') then - local xid = ARGV[2]; - local status = tonumber(ARGV[3]); - local REDIS_SEATA_BEGIN_TRANSACTIONS_KEY = KEYS[4]; - redis.call('LREM', listKey, 0, xid); - redis.call('DEL', branchOrGlobalKey); - -- GlobalStatus.Begin or GlobalStatus.UnKnown - if (status == 1 or status == 0) then - redis.call('ZREM', REDIS_SEATA_BEGIN_TRANSACTIONS_KEY, branchOrGlobalKey); - end -end - -return 'true'; diff --git a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/insertTransactionDO.lua b/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/insertTransactionDO.lua deleted file mode 100644 index 75388ea68a..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/insertTransactionDO.lua +++ /dev/null @@ -1,49 +0,0 @@ --- Copyright 1999-2019 Seata.io Group. --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - --- User: conghuhu --- Date: 2022/7/25 - --- param description --- KEYS[1] branchOrGlobalKey --- KEYS[2] listKey --- KEYS[3~-2] transactionDOMap.keys --- KEYS[-1] REDIS_SEATA_BEGIN_TRANSACTIONS_KEY (only type is global) --- ARGV[1] type: global or branch --- ARGV[2] transactionDOMap.size() --- ARGV[3~-2] transactionDOMap.values --- ARGV[-2] xid (only type is global) --- ARGV[-1] beginTime+timeout (only type is global) - --- init data -local branchOrGlobalKey = KEYS[1]; -local listKey = KEYS[2]; - -local type = ARGV[1]; -local keySize = tonumber(ARGV[2]); - -for i = 1, keySize do - redis.call('HSET', branchOrGlobalKey, KEYS[i + 2], ARGV[i + 2]); -end - -if type == 'branch' then - redis.call('RPUSH', listKey, branchOrGlobalKey); -elseif type == 'global' then - local REDIS_SEATA_BEGIN_TRANSACTIONS_KEY = KEYS[keySize + 3]; - redis.call('RPUSH', listKey, ARGV[keySize + 3]); - redis.call('ZADD', REDIS_SEATA_BEGIN_TRANSACTIONS_KEY, ARGV[keySize + 4], branchOrGlobalKey) -end - -return 'true'; - diff --git a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/rollbackGlobalTransactionDO.lua b/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/rollbackGlobalTransactionDO.lua deleted file mode 100644 index 5e6c4a6a05..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/rollbackGlobalTransactionDO.lua +++ /dev/null @@ -1,57 +0,0 @@ --- Copyright 1999-2019 Seata.io Group. --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - --- User: conghuhu --- Date: 2022/7/27 - --- param description --- KEYS[1] globalKey --- KEYS[2] REDIS_KEY_GLOBAL_XID --- KEYS[3] REDIS_KEY_GLOBAL_STATUS --- KEYS[4] REDIS_KEY_GLOBAL_GMT_MODIFIED --- KEYS[5] status --- ARGV[1] previousStatus --- ARGV[2] previousGmtModified --- ARGV[3] xid --- ARGV[4] hmset --- ARGV[5] lrem --- ARGV[6] rpush - --- init data -local globalKey = KEYS[1]; -local REDIS_KEY_GLOBAL_XID = KEYS[2]; -local REDIS_KEY_GLOBAL_STATUS = KEYS[3]; -local REDIS_KEY_GLOBAL_GMT_MODIFIED = KEYS[4]; -local status = KEYS[5]; -local previousStatus = ARGV[1]; -local previousGmtModified = ARGV[2]; -local xid = ARGV[3]; -local hmset = ARGV[4]; -local lrem = ARGV[5]; -local rpush = ARGV[6]; - -if string.upper(hmset) == "OK" then - local xid2 = redis.call('HGET', globalKey, REDIS_KEY_GLOBAL_XID); - if (xid2 and string.len(tostring(xid2)) ~= 0) then - redis.call('HMSET', globalKey, REDIS_KEY_GLOBAL_STATUS, previousStatus, REDIS_KEY_GLOBAL_GMT_MODIFIED, previousGmtModified); - end -end - -if tonumber(lrem) > 0 then - redis.call('RPUSH', 'SEATA_STATUS_' .. previousStatus, xid); -end - -if tonumber(rpush) then - redis.call('LREM', 'SEATA_STATUS_' .. status, 0, xid); -end \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/updateBranchTransactionDO.lua b/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/updateBranchTransactionDO.lua deleted file mode 100644 index 24e3083cde..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/updateBranchTransactionDO.lua +++ /dev/null @@ -1,55 +0,0 @@ --- Copyright 1999-2019 Seata.io Group. --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - --- User: conghuhu --- Date: 2022/7/27 - --- param description --- KEYS[1] branchKey --- KEYS[2] REDIS_KEY_BRANCH_STATUS --- KEYS[3] REDIS_KEY_BRANCH_GMT_MODIFIED --- KEYS[4] REDIS_KEY_BRANCH_APPLICATION_DATA --- ARGV[1] branchStatus --- ARGV[2] nowTime --- ARGV[3] applicationData - --- init data -local branchKey = KEYS[1]; -local REDIS_KEY_BRANCH_STATUS = KEYS[2]; -local REDIS_KEY_BRANCH_GMT_MODIFIED = KEYS[3]; -local REDIS_KEY_BRANCH_APPLICATION_DATA = KEYS[4]; -local branchStatus = ARGV[1]; -local nowTime = ARGV[2]; -local applicationData = ARGV[3]; -local result = {}; - -local previousBranchStatus = redis.call('HGET', branchKey, REDIS_KEY_BRANCH_STATUS); -if (not previousBranchStatus or string.len(tostring(previousBranchStatus)) == 0) -then - result['success'] = false; - result['status'] = ''; - result['data'] = ''; - return cjson.encode(result); -end - -redis.call('HSET', branchKey, REDIS_KEY_BRANCH_STATUS, branchStatus); -redis.call('HSET', branchKey, REDIS_KEY_BRANCH_GMT_MODIFIED, nowTime); -if (applicationData and string.len(tostring(applicationData)) ~= 0) then - redis.call('HSET', branchKey, REDIS_KEY_BRANCH_APPLICATION_DATA, applicationData); -end - -result['success'] = true; -result['status'] = ''; -result['data'] = ''; -return cjson.encode(result); \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/updateGlobalTransactionDO.lua b/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/updateGlobalTransactionDO.lua deleted file mode 100644 index 438029625c..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/lua/redisStore/updateGlobalTransactionDO.lua +++ /dev/null @@ -1,109 +0,0 @@ --- Copyright 1999-2019 Seata.io Group. --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - --- User: conghuhu --- Date: 2022/7/27 - --- param description --- KEYS[1] globalKey --- KEYS[2] REDIS_KEY_GLOBAL_STATUS --- KEYS[3] REDIS_KEY_GLOBAL_GMT_MODIFIED --- KEYS[4] REDIS_SEATA_BEGIN_TRANSACTIONS_KEY --- ARGV[1] status --- ARGV[2] nowTime --- ARGV[3] xid - --- init data -local globalKey = KEYS[1]; -local REDIS_KEY_GLOBAL_STATUS = KEYS[2]; -local REDIS_KEY_GLOBAL_GMT_MODIFIED = KEYS[3]; -local REDIS_SEATA_BEGIN_TRANSACTIONS_KEY = KEYS[4]; - -local status = ARGV[1]; -local nowTime = ARGV[2]; -local xid = ARGV[3]; - -local result = {}; - --- is timeout global status -local function isTimeoutGlobalStatus(s) - local globalStatus = tonumber(s); - return globalStatus == 13 or globalStatus == 14 or globalStatus == 6 or globalStatus == 7; -end - --- is rollback global status -local function isRollbackGlobalStatus(s) - local globalStatus = tonumber(s); - return globalStatus == 4 or globalStatus == 5 or globalStatus == 11 or globalStatus == 12 or globalStatus == 17; -end - -local function isCommitGlobalStatus(s) - local globalStatus = tonumber(s); - return globalStatus == 2 or globalStatus == 8 or globalStatus == 3 or globalStatus == 9 or globalStatus == 10 or globalStatus == 16; -end - --- check the relation of before status and after status -local function validateUpdateStatus(before, after) - if isTimeoutGlobalStatus(before) and isCommitGlobalStatus(after) then - return false; - end - if isCommitGlobalStatus(before) and isTimeoutGlobalStatus(after) then - return false; - end - if isRollbackGlobalStatus(before) and isCommitGlobalStatus(after) then - return false; - end - if isCommitGlobalStatus(before) and isRollbackGlobalStatus(after) then - return false; - end - return true; -end - -local statusAndGmtModified = redis.call('HMGET', globalKey, REDIS_KEY_GLOBAL_STATUS, REDIS_KEY_GLOBAL_GMT_MODIFIED); -local previousStatus = statusAndGmtModified[1]; -local previousGmtModified = statusAndGmtModified[2]; - -if (not previousStatus and string.len(tostring(previousStatus)) ~= 0) then - result['success'] = false; - result['status'] = 'NotExisted'; - result['data'] = ''; - return cjson.encode(result); -end - -if previousStatus == status then - result['success'] = true; - result['status'] = ''; - result['data'] = ''; - return cjson.encode(result); -end - -if not validateUpdateStatus(previousStatus, status) then - result['success'] = false; - result['status'] = 'ChangeStatusFail'; - result['data'] = previousGmtModified; - return cjson.encode(result); -end - -local data = {}; -data[1] = redis.call('HMSET', globalKey, REDIS_KEY_GLOBAL_STATUS, status, REDIS_KEY_GLOBAL_GMT_MODIFIED, nowTime)['ok']; -data[2] = tostring(redis.call('LREM', 'SEATA_STATUS_' .. previousStatus, 0, xid)); -data[3] = tostring(redis.call('RPUSH', 'SEATA_STATUS_' .. status, xid)); -data[4] = tostring(redis.call('ZREM', REDIS_SEATA_BEGIN_TRANSACTIONS_KEY, globalKey)); -data[5] = previousStatus; -data[6] = previousGmtModified; - -result['success'] = true; -result['status'] = ''; -result['data'] = cjson.encode(data); -return cjson.encode(result); \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/acquireRedisLock.lua b/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/acquireRedisLock.lua deleted file mode 100644 index cb1668cf6e..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/acquireRedisLock.lua +++ /dev/null @@ -1,98 +0,0 @@ --- Copyright 1999-2019 Seata.io Group. --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - --- User: tianyu.li;conghuhu --- Date: 2022/7/1 - --- param description --- ARGV[1] needLockDOs.size() --- ARGV[2] argSize --- ARGV[3] needLockXid --- ARGV[-1] localKeysString --- KEYS[1 ~ needLockKeys.size()] needLockKeys --- KEYS[-2] xidLockKey --- KEYS[-1] branchId - --- init data -local array = {}; -local result = {}; -local keySize = ARGV[1]; -local argSize = ARGV[2]; --- Loop through all keys to see if they can be used , when a key is not available, exit -for i = 1, keySize do - local needLockKey = KEYS[i] - -- search lock xid - local existedLockXid = redis.call('HGET', needLockKey, 'xid'); - -- query lockStatus - local status = redis.call('HGET', needLockKey, 'status'); - - -- if a global lock is found in the Rollbacking state,the fail-fast code is returned directly - if (status == '1' or tonumber(status) == 1) - then - result["success"] = false - result['status'] = 'AnotherRollbackIng' - result["data"] = existedLockXid - return cjson.encode(result) - end - - -- if lock xid is nil - if (not existedLockXid) - -- set 'no' mean There is need to store lock information - then - array[i] = 'no' - else - if (existedLockXid ~= ARGV[3]) - then - -- return fail - result['success'] = false - result['status'] = 'AnotherHoldIng' - result["data"] = existedLockXid - return cjson.encode(result) - else - -- set 'yes' mean There is not need to store lock information - array[i] = 'yes' - end - end -end --- Loop through array -for i = 1, keySize do - -- if is no ,The lock information is stored - if (array[i] == 'no') - then - -- set xid - redis.call('HSET', KEYS[i], 'xid', ARGV[3]); - -- set transactionId - redis.call('HSET', KEYS[i], 'transactionId', ARGV[(i - 1) * 6 + 4]); - -- set branchId - redis.call('HSET', KEYS[i], 'branchId', ARGV[(i - 1) * 6 + 5]); - -- set resourceId - redis.call('HSET', KEYS[i], 'resourceId', ARGV[(i - 1) * 6 + 6]); - -- set tableName - redis.call('HSET', KEYS[i], 'tableName', ARGV[(i - 1) * 6 + 7]); - -- set rowKey - redis.call('HSET', KEYS[i], 'rowKey', ARGV[(i - 1) * 6 + 8]); - -- set pk - redis.call('HSET', KEYS[i], 'pk', ARGV[(i - 1) * 6 + 9]); - -- exit if - end - -- exit for -end --- set SEATA_GLOBAL_LOCK -redis.call('HSET', KEYS[(keySize + 1)], KEYS[(keySize + 2)], ARGV[(argSize + 0)]); - --- return success -result['success'] = true -result['status'] = 'GetLock' -result['data'] = ARGV[3] -return cjson.encode(result) diff --git a/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/isLockable.lua b/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/isLockable.lua deleted file mode 100644 index 7325966f27..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/isLockable.lua +++ /dev/null @@ -1,33 +0,0 @@ --- Copyright 1999-2019 Seata.io Group. --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - --- User: conghuhu --- Date: 2022/7/7 - --- param description --- KEYS[1] lockKeys.size() --- KEYS[2~lockKeys.size()+1] lockKey --- ARGV[1] xid - --- init data -local lockKeysSize = tonumber(KEYS[1]); -local xid = tostring(ARGV[1]); -for i = 1, lockKeysSize do - local lockKey = KEYS[i + 1] - local existedXid = redis.call('HGET', lockKey, 'xid') - if (existedXid == nil or xid == tostring(existedXid)) then - return 'true' - end -end -return 'false' \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/releaseRedisLock.lua b/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/releaseRedisLock.lua deleted file mode 100644 index 72176dcdd5..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/releaseRedisLock.lua +++ /dev/null @@ -1,117 +0,0 @@ --- Copyright 1999-2019 Seata.io Group. --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - --- User: conghuhu --- Date: 2022/7/7 - --- param description --- KEYS[1] xidLockKey --- KEYS[2] branchId - --- init data -local xidLockKey = KEYS[1]; -local branchId = KEYS[2]; - -local rowKeys = {} - --- get table length -local function table_len(t) - local len = 0 - for _, _ in pairs(t) do - len = len + 1 - end - return len; -end - --- split -local function split(target, sep) - local str = tostring(target) - local separator = tostring(sep) - local strB, arrayIndex = 1, 1 - local targetArray = {} - if (separator == nil) - then - return false - end - local condition = true - while (condition) - do - local si, sd = string.find(str, separator, strB) - if (si) - then - targetArray[arrayIndex] = string.sub(str, strB, si - 1) - arrayIndex = arrayIndex + 1 - strB = sd + 1 - else - targetArray[arrayIndex] = string.sub(str, strB, string.len(str)) - condition = false - end - end - return targetArray -end - --- start -if (not branchId) -then - local rowKeyMap = redis.call('HGETALL', xidLockKey) - for i = 1, table_len(rowKeyMap) do - if (i % 2 == 0) - then - rowKeys[i / 2] = rowKeyMap[i] - end - end -else - local rowKey = redis.call('HGET', xidLockKey, branchId) - rowKeys[1] = rowKey -end - -if (table_len(rowKeys) == 0) --- rowKeys is empty -then - return true -end - -if (not branchId) --- branchId is null -then - redis.call('DEL', xidLockKey) -else - redis.call('HDEL', xidLockKey, branchId) -end - -for _, value in pairs(rowKeys) do - local rowKeyStr = tostring(value) - if (string.len(rowKeyStr) == 0) - -- rowKeyStr is empty - then - return true - end - - local start, _ = string.find(rowKeyStr, ';') - if (start) - -- rowKeyStr contains ';' - then - local keys = split(rowKeyStr, ';') - redis.call('DEL', unpack(keys)) - else - redis.call('DEL', rowKeyStr) - end -end - -return true - - - - - diff --git a/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/updateLockStatus.lua b/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/updateLockStatus.lua deleted file mode 100644 index d3170d3395..0000000000 --- a/laokou-cloud/laokou-seata/src/main/resources/lua/redislocker/updateLockStatus.lua +++ /dev/null @@ -1,82 +0,0 @@ --- Copyright 1999-2019 Seata.io Group. --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - --- User: conghuhu --- Date: 2022/7/7 - --- param description --- KEYS[1] xidLockKey --- KEYS[2] status --- ARGV[1] code - --- init data -local xidLockKey = KEYS[1]; -local status = KEYS[2]; -local code = ARGV[1]; - --- get table length -local function table_len(t) - local len = 0 - for _, _ in pairs(t) do - len = len + 1 - end - return len; -end - --- split -local function split(target, sep) - local str = tostring(target) - local separator = tostring(sep) - local strB, arrayIndex = 1, 1 - local targetArray = {} - if (separator == nil) - then - return false - end - local condition = true - while (condition) - do - local si, sd = string.find(str, separator, strB) - if (si) - then - targetArray[arrayIndex] = string.sub(str, strB, si - 1) - arrayIndex = arrayIndex + 1 - strB = sd + 1 - else - targetArray[arrayIndex] = string.sub(str, strB, string.len(str)) - condition = false - end - end - return targetArray -end - -local branchAndLockKeys = redis.call('HGETALL', xidLockKey) -for i = 1, table_len(branchAndLockKeys) do - if (i % 2 == 0) - then - local k = tostring(branchAndLockKeys[i]) - local start, _ = string.find(k, ';') - if (start) - -- k contains ';' - then - local keys = split(k, ';') - for _, key in pairs(keys) - do - redis.call('HSET', key, status, code) - end - else - redis.call('HSET', k, status, code) - end - end -end \ No newline at end of file diff --git a/laokou-cloud/laokou-seata/src/main/resources/scg-keystore.p12 b/laokou-cloud/laokou-seata/src/main/resources/scg-keystore.p12 deleted file mode 100644 index fdcde6ba69ed76cc2aa6882287e8a54872220f97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2756 zcma)8c{J1u8=e_6maz=kxpuOQ@TJCW_; zNQ^8I5;cbGlPKAjy1w&$r+dD?zVDCcyytzE_s{3N01n;-0W$$Ocpx*I65b5I%L!%y z7vtcrP#oOpguV>mV6Fcp!789Q*qAW9L(T^)CK&0C19L@Gl2SM z3*z6Bm8PC2!=2yUO(3{UBv@SJPp-I}{l5#-kQ`;mA5+f_0xGE@^;G+`fq zm~!ZgPAKsh(G|HpJ83VjJR@k_DKtHoh3|W<99-7-`%PO|GqrdzyUJWnY9p7)ihm)vam+L2%uS|Y&Y)M{ zAZeK1CzC@L#a)wb*sujm`30-R)gm}ty?8$p&%IZ(Vk{=rI~B_OTx&UM=B0Gpu(`3+ zFxXB9U0k_gLNN5K)WljFaUpl#WKWK*Q*`t3r&&Yaev_fs{;FDfHwA4B{TcqN%TV@)fE z5!GU_t+0{38x5k`p+TKixfq zH?<;9ffqPx!o+?4t7^@RwAqOXRZL3{kE7rp``pC}Uv5mAvuma6S9j!QL33J%kMT_)N3aBL%jn-;omGvY|00_1lEqG#hEVZu>*%wi*lmgGi< zJWGw9WQ+2)L@*-YS{K*4%he-mMSO1SGz%TO`Do3?0MeL$7|vnA$_ams>?*fSOpAzK=ojSaW8~zoRrJ1%J*uouo=CUiN=}&gwa|Z zp&AFab>|^;d@ANmp{OX$xPL%aIYej`JM^@F-b)Yuz^U)GY`YbTXp;QNaJJvf<4AQ=S=4ZR&Gx)sDiRzd>WH z_y3>DW-C2)ZRq>QAJNLsSXf)<5&b3)Hl`NV)zb z?0Ah)MnPE$O)F@h^BkXIN7XKS&uTq|$^6CLv3mtpFIkK~u}Mre+n;(EFFnbKOrZFj)t2Dj5-*{FyKCz7 zrq1HJ6gy1nZq7}2cj`G{o>m8YX~3_j_HVh-T8l=H>uyETN(rK-?IVt)kv>Ou^;?~X zFL@pZetA`0Y|v~w7G&w6ea9brQ1ZsR^ZU3-VwB6D);dE}iICaXp2{UT0Ox%^b&EX?k#>ddi^hLQ_6LqkI8sM*$;;hciBK-vAQz7kMO6Xbq@Np9{= z7-^6|i{xYTEesvspdNMRIgR?^O*bfzKXS}Q-6}mk*-h3pOi0Qv9AXygkEVcvlo?t zq3ix;pEH^y3i%=XSA2!NG$WS(kaE$%RUxh>$dXF;!g11Z_GUSiv zcBtl5hZ#)c1!8uXAL`x9K}X`#-*zX!aR}sOhtm22r+9j1+anum(_^U}YLKI`Lbv5_ z-5Fty93(G>IlNliy*^{vlvk^=Ld1K%_&xWw$D5Z3ybI#fIxVL!IHz(3&oaXuN@F+PLk*nU|zBXa*5 zux;Y}uDqxYum)5C&R?G$1PlW~C1JejFtYLSiui-Y%Oxd#S;%AF?qP3KUP*|PzR~4c eG?Z`lDBUasa(^kaMUc-~h7}b?_H_PN1^o?KjPb|- diff --git a/laokou-cloud/pom.xml b/laokou-cloud/pom.xml index 26413a1a43..0903d1cb00 100644 --- a/laokou-cloud/pom.xml +++ b/laokou-cloud/pom.xml @@ -17,7 +17,7 @@ * */ --> - org.laokou @@ -33,7 +33,6 @@ laokou-gateway laokou-monitor laokou-register - laokou-seata laokou-sentinel laokou-snail-job diff --git a/laokou-common/laokou-common-bom/pom.xml b/laokou-common/laokou-common-bom/pom.xml index 6d63687bcd..533a3d293a 100644 --- a/laokou-common/laokou-common-bom/pom.xml +++ b/laokou-common/laokou-common-bom/pom.xml @@ -120,12 +120,26 @@ 5.0 - 1.65.1 + 1.64.2 + + 2.29.0 + + 2.23.0 + + com.google.errorprone + error_prone_annotations + ${error_prone_annotations.version} + + + com.google.api.grpc + proto-google-common-protos + ${proto-google-common-protos.version} + io.grpc grpc-netty @@ -599,11 +613,6 @@ laokou-common-cors ${laokou.version} - - org.laokou - laokou-common-seata - ${laokou.version} - com.google.guava guava @@ -679,11 +688,6 @@ laokou-common-openapi-doc ${laokou.version} - - org.laokou - laokou-seata - ${laokou.version} - org.laokou laokou-auth-client diff --git a/laokou-common/laokou-common-core/pom.xml b/laokou-common/laokou-common-core/pom.xml index fec37fb94d..83300ce376 100644 --- a/laokou-common/laokou-common-core/pom.xml +++ b/laokou-common/laokou-common-core/pom.xml @@ -36,6 +36,12 @@ com.google.code.gson gson + + + com.google.errorprone + error_prone_annotations + + com.fasterxml.jackson.datatype @@ -104,6 +110,12 @@ com.google.guava guava + + + com.google.errorprone + error_prone_annotations + + com.alibaba @@ -114,5 +126,9 @@ jakarta.servlet-api provided + + com.google.errorprone + error_prone_annotations + diff --git a/laokou-common/laokou-common-i18n/src/main/java/org/laokou/common/i18n/common/exception/SystemException.java b/laokou-common/laokou-common-i18n/src/main/java/org/laokou/common/i18n/common/exception/SystemException.java index 5e23df6df6..d31a913673 100644 --- a/laokou-common/laokou-common-i18n/src/main/java/org/laokou/common/i18n/common/exception/SystemException.java +++ b/laokou-common/laokou-common-i18n/src/main/java/org/laokou/common/i18n/common/exception/SystemException.java @@ -64,16 +64,6 @@ public final class SystemException extends GlobalException { */ public static final String FLOWED = "S_Sentinel_Flowed"; - /** - * 分布式事务已宕机. - */ - public static final String DISTRIBUTED_TRANSACTION_DOWNTIME = "S_Seata_TransactionDowntime"; - - /** - * 分布式事务已超时. - */ - public static final String DISTRIBUTED_TRANSACTION_TIMEOUT = "S_Seata_TransactionTimeout"; - /** * 表不存在. */ diff --git a/laokou-common/laokou-common-i18n/src/main/resources/i18n/message.properties b/laokou-common/laokou-common-i18n/src/main/resources/i18n/message.properties index 625d0324c6..299a23a4c4 100644 --- a/laokou-common/laokou-common-i18n/src/main/resources/i18n/message.properties +++ b/laokou-common/laokou-common-i18n/src/main/resources/i18n/message.properties @@ -41,8 +41,6 @@ S_Sentinel_SystemBlocked=\u7CFB\u7EDF\u89C4\u5219\u9519\u8BEF S_Sentinel_ParamFlowed=\u70ED\u70B9\u53C2\u6570\u5DF2\u9650\u6D41 S_Sentinel_Degraded=\u5DF2\u964D\u7EA7 S_Sentinel_Flowed=\u5DF2\u9650\u6D41 -S_Seata_TransactionDowntime=\u5206\u5E03\u5F0F\u4E8B\u52A1\u5DF2\u5B95\u673A -S_Seata_TransactionTimeout=\u5206\u5E03\u5F0F\u4E8B\u52A1\u5DF2\u8D85\u65F6 S_DS_TableNotExist=\u8868 {0} \u4E0D\u5B58\u5728 A_OAuth2_SourceNotExist=\u6570\u636E\u6E90\u4E0D\u5B58\u5728 S_User_AESDecryptUsernameFail=\u7528\u6237\u540D\u89E3\u5BC6\u5931\u8D25 diff --git a/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_en.properties b/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_en.properties index 79480854bc..1c642c0425 100644 --- a/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_en.properties +++ b/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_en.properties @@ -40,8 +40,6 @@ S_Sentinel_SystemBlocked=System rule error S_Sentinel_ParamFlowed=Hot spot parameters are restricted S_Sentinel_Degraded=Degraded S_Sentinel_Flowed=Flowed -S_Seata_TransactionDowntime=Distributed transaction has crashed -S_Seata_TransactionTimeout=Distributed transaction has timed out S_DS_TableNotExist=Table {0} does not exist A_OAuth2_SourceNotExist=The data source does not exist S_User_AESDecryptUsernameFail=User name decryption failed diff --git a/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_en_US.properties b/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_en_US.properties index 79480854bc..1c642c0425 100644 --- a/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_en_US.properties +++ b/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_en_US.properties @@ -40,8 +40,6 @@ S_Sentinel_SystemBlocked=System rule error S_Sentinel_ParamFlowed=Hot spot parameters are restricted S_Sentinel_Degraded=Degraded S_Sentinel_Flowed=Flowed -S_Seata_TransactionDowntime=Distributed transaction has crashed -S_Seata_TransactionTimeout=Distributed transaction has timed out S_DS_TableNotExist=Table {0} does not exist A_OAuth2_SourceNotExist=The data source does not exist S_User_AESDecryptUsernameFail=User name decryption failed diff --git a/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_zh_CN.properties b/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_zh_CN.properties index 7db106cfea..97bff6d32b 100644 --- a/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_zh_CN.properties +++ b/laokou-common/laokou-common-i18n/src/main/resources/i18n/message_zh_CN.properties @@ -40,8 +40,6 @@ S_Sentinel_SystemBlocked=\u7CFB\u7EDF\u89C4\u5219\u9519\u8BEF S_Sentinel_ParamFlowed=\u70ED\u70B9\u53C2\u6570\u5DF2\u9650\u6D41 S_Sentinel_Degraded=\u5DF2\u964D\u7EA7 S_Sentinel_Flowed=\u5DF2\u9650\u6D41 -S_Seata_TransactionDowntime=\u5206\u5E03\u5F0F\u4E8B\u52A1\u5DF2\u5B95\u673A -S_Seata_TransactionTimeout=\u5206\u5E03\u5F0F\u4E8B\u52A1\u5DF2\u8D85\u65F6 S_DS_TableNotExist=\u8868 {0} \u4E0D\u5B58\u5728 A_OAuth2_SourceNotExist=\u6570\u636E\u6E90\u4E0D\u5B58\u5728 S_User_AESDecryptUsernameFail=\u7528\u6237\u540D\u89E3\u5BC6\u5931\u8D25 diff --git a/laokou-common/laokou-common-nacos/pom.xml b/laokou-common/laokou-common-nacos/pom.xml index b3ff71c34a..0828314421 100644 --- a/laokou-common/laokou-common-nacos/pom.xml +++ b/laokou-common/laokou-common-nacos/pom.xml @@ -76,6 +76,12 @@ com.alibaba.nacos nacos-api + + + com.google.api.grpc + proto-google-common-protos + + com.alibaba.nacos @@ -90,6 +96,11 @@ jakarta.servlet-api provided + + com.google.api.grpc + proto-google-common-protos + 2.29.0 + diff --git a/laokou-common/laokou-common-seata/pom.xml b/laokou-common/laokou-common-seata/pom.xml deleted file mode 100644 index 29b3f66859..0000000000 --- a/laokou-common/laokou-common-seata/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - laokou-common - org.laokou - 3.3.2 - - 4.0.0 - - laokou-common-seata - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-seata - - - com.alibaba - druid - - - - - org.laokou - laokou-common-i18n - - - - diff --git a/laokou-common/laokou-common-seata/src/main/java/org/laokou/common/seata/handler/SeataExceptionHandler.java b/laokou-common/laokou-common-seata/src/main/java/org/laokou/common/seata/handler/SeataExceptionHandler.java deleted file mode 100644 index 8038b5f163..0000000000 --- a/laokou-common/laokou-common-seata/src/main/java/org/laokou/common/seata/handler/SeataExceptionHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2022-2024 KCloud-Platform-IoT Author or Authors. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.laokou.common.seata.handler; - -import io.seata.common.exception.FrameworkException; -import io.seata.core.exception.RmTransactionException; -import org.laokou.common.i18n.dto.Result; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import static org.laokou.common.i18n.common.exception.StatusCode.INTERNAL_SERVER_ERROR; -import static org.laokou.common.i18n.common.exception.SystemException.DISTRIBUTED_TRANSACTION_DOWNTIME; -import static org.laokou.common.i18n.common.exception.SystemException.DISTRIBUTED_TRANSACTION_TIMEOUT; - -/** - * @author laokou - */ -@Component -@ResponseBody -@RestControllerAdvice -public class SeataExceptionHandler { - - @ExceptionHandler({ RmTransactionException.class, FrameworkException.class }) - public Result handle(Exception ex) { - if (ex instanceof RmTransactionException) { - return Result.fail(DISTRIBUTED_TRANSACTION_TIMEOUT); - } - else if (ex instanceof FrameworkException) { - return Result.fail(DISTRIBUTED_TRANSACTION_DOWNTIME); - } - return Result.fail(INTERNAL_SERVER_ERROR); - } - -} diff --git a/laokou-common/laokou-common-seata/src/main/java/org/laokou/common/seata/handler/package-info.java b/laokou-common/laokou-common-seata/src/main/java/org/laokou/common/seata/handler/package-info.java deleted file mode 100644 index 7d223c9fec..0000000000 --- a/laokou-common/laokou-common-seata/src/main/java/org/laokou/common/seata/handler/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2022-2024 KCloud-Platform-IoT Author or Authors. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * @author laokou - */ -package org.laokou.common.seata.handler; diff --git a/laokou-common/pom.xml b/laokou-common/pom.xml index 717e61c5c6..7f1250327e 100644 --- a/laokou-common/pom.xml +++ b/laokou-common/pom.xml @@ -17,7 +17,7 @@ * */ --> - org.laokou @@ -49,7 +49,6 @@ laokou-common-prometheus laokou-common-kafka laokou-common-cors - laokou-common-seata laokou-common-log4j2 laokou-common-trace laokou-common-algorithm diff --git a/laokou-service/laokou-admin/laokou-admin-infrastructure/pom.xml b/laokou-service/laokou-admin/laokou-admin-infrastructure/pom.xml index 97592102ac..79190cd5e6 100644 --- a/laokou-service/laokou-admin/laokou-admin-infrastructure/pom.xml +++ b/laokou-service/laokou-admin/laokou-admin-infrastructure/pom.xml @@ -1,6 +1,6 @@ - org.laokou @@ -49,16 +49,6 @@ org.laokou laokou-admin-domain - - org.laokou - laokou-common-seata - - - org.springframework.boot - spring-boot-starter-web - - - org.laokou laokou-common-openfeign diff --git a/laokou-service/laokou-admin/laokou-admin-start/src/main/resources/bootstrap.yml b/laokou-service/laokou-admin/laokou-admin-start/src/main/resources/bootstrap.yml index cbe503d752..93b4b84c68 100644 --- a/laokou-service/laokou-admin/laokou-admin-start/src/main/resources/bootstrap.yml +++ b/laokou-service/laokou-admin/laokou-admin-start/src/main/resources/bootstrap.yml @@ -48,9 +48,6 @@ spring: - data-id: application-common.yaml group: ${NACOS-GROUP} refresh: true - - data-id: application-common-seata.yaml - group: ${NACOS-GROUP} - refresh: true - data-id: application-common-elasticsearch.yaml group: ${NACOS-GROUP} refresh: true diff --git a/pom.xml b/pom.xml index 1a6953e9e4..61895c76b0 100644 --- a/pom.xml +++ b/pom.xml @@ -189,10 +189,6 @@ LAOKOU_GROUP nacos nacos - SEATA_GROUP - seata - seata - ./logs/seata sentinel sentinel dev @@ -235,10 +231,6 @@ LAOKOU_GROUP nacos nacos - SEATA_GROUP - seata - seata - ./logs/seata sentinel sentinel test @@ -310,14 +302,6 @@ ${NACOS_PASSWORD:nacos} - ${SEATA_GROUP:SEATA_GROUP} - - ${SEATA_USERNAME:seata} - - ${SEATA_PASSWORD:seata} - - ${SEATA_LOG_PATH:/opt} - ${SENTINEL_USERNAME:sentinel} ${SENTINEL_PASSWORD:sentinel} diff --git "a/src/docs/asciidoc/\345\274\200\347\257\207.adoc" "b/src/docs/asciidoc/\345\274\200\347\257\207.adoc" index fc0e5da730..2f4df88ef7 100644 --- "a/src/docs/asciidoc/\345\274\200\347\257\207.adoc" +++ "b/src/docs/asciidoc/\345\274\200\347\257\207.adoc" @@ -46,7 +46,7 @@ |负载均衡 |Spring Cloud Loadbalancer |服务熔断&降级&限流 |Sentinel |分库分表 |Mybatis Plus -|分布式事务 |Seata & RocketMQ +|分布式事务 |RocketMQ |消息队列 |RocketMQ & Kafka & MQTT |服务监控 |Spring Boot Admin & Prometheus |高亮搜索 |Elasticsearch diff --git a/test_error b/test_error index 34f30574f0..39e039cf39 100644 --- a/test_error +++ b/test_error @@ -6,9 +6,6 @@ S_Sentinel_SystemBlocked S_Sentinel_ParamFlowed S_Sentinel_Authority -S_Seata_TransactionTimeout -S_Seata_TransactionDowntime - S_Ip_Blacked S_Ip_Restricted

  • 10}vN75Z?aKOV-aGEFC1!)3Xgv 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