diff --git a/CHANGELOG.md b/CHANGELOG.md index d9e23d636..05a7ae911 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +# v1.10.50 +## 11/14/2025 + +1. [](#new) + * Support for 'safe-upgrade' installation + * Support for safe-upgrade restore functionality in Tools +1. [](#improved) + * Improved session expiration/logout handling + * Various minor CSS fixes +1. [](#bugfix) + * Fix for deeply nested sortable fields (at last!) + * Restore admin session timeout modal by returning 401 for timed-out AJAX requests + * Honor `system.updates.safe_upgrade` so legacy Grav installs keep the classic updater + # v1.10.49.1 ## 09/03/2025 diff --git a/admin.php b/admin.php index 305b76838..52683621d 100644 --- a/admin.php +++ b/admin.php @@ -32,6 +32,7 @@ use Grav\Plugin\Admin\Router; use Grav\Plugin\Admin\Themes; use Grav\Plugin\Admin\AdminController; +use Grav\Plugin\Admin\SafeUpgradeManager; use Grav\Plugin\Admin\Twig\AdminTwigExtension; use Grav\Plugin\Admin\WhiteLabel; use Grav\Plugin\Form\Form; @@ -383,6 +384,34 @@ public function onAdminTools(Event $event) 'reports' => [['admin.super'], 'PLUGIN_ADMIN.REPORTS'], 'direct-install' => [['admin.super'], 'PLUGIN_ADMIN.DIRECT_INSTALL'], ]); + + $config = $this->grav['config'] ?? null; + if (!SafeUpgradeManager::configAllowsSafeUpgrade($config)) { + return; + } + + try { + $manifestFiles = glob(GRAV_ROOT . '/user/data/upgrades/*.json') ?: []; + + if (!$manifestFiles) { + $manager = new SafeUpgradeManager(Grav::instance()); + $manifestFiles = $manager->hasSnapshots() ? [true] : []; + } + + $tools = $event['tools']; + Grav::instance()['log']->debug('[Admin] Tools before restore grav: ' . implode(',', array_keys($tools))); + + if ($manifestFiles) { + $tools['restore-grav'] = [['admin.super'], 'PLUGIN_ADMIN.RESTORE_GRAV']; + Grav::instance()['log']->debug('[Admin] Restore Grav tool enabled'); + } + + $event['tools'] = $tools; + Grav::instance()['log']->debug('[Admin] Tools after register: ' . implode(',', array_keys($tools))); + } catch (\Throwable $e) { + // ignore availability errors, snapshots tool will simply stay hidden + Grav::instance()['log']->warning('[Admin] Restore Grav detection failed: ' . $e->getMessage()); + } } /** diff --git a/admin.yaml b/admin.yaml index c23f95b15..e364694a4 100644 --- a/admin.yaml +++ b/admin.yaml @@ -23,6 +23,7 @@ pages: show_modular: true session: timeout: 1800 + keep_alive: true edit_mode: normal frontend_preview_target: inline show_github_msg: true diff --git a/blueprints.yaml b/blueprints.yaml index 2a6b0384b..1dd8f50d3 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -1,7 +1,7 @@ name: Admin Panel slug: admin type: plugin -version: 1.10.49.1 +version: 1.10.50 description: Adds an advanced administration panel to manage your site icon: empire author: @@ -224,6 +224,18 @@ form: type: number min: 1 + session.keep_alive: + type: toggle + label: Keep Alive Ping + help: "Periodically pings to keep your admin session alive. Turn OFF to allow the session to expire while idle (useful for testing timeouts)." + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + hide_page_types: type: select size: large diff --git a/classes/plugin/Admin.php b/classes/plugin/Admin.php index 56958e5cf..8ede98ba6 100644 --- a/classes/plugin/Admin.php +++ b/classes/plugin/Admin.php @@ -341,6 +341,31 @@ public static function toolsPermissions() return array_unique($perms); } + /** + * @return array + */ + public function safeUpgradeSnapshots(): array + { + try { + $manager = new SafeUpgradeManager(); + + return $manager->listSnapshots(); + } catch (\Throwable $e) { + return []; + } + } + + public function safeUpgradeHasSnapshots(): bool + { + try { + $manager = new SafeUpgradeManager(); + + return $manager->hasSnapshots(); + } catch (\Throwable $e) { + return false; + } + } + /** * Return the languages available in the site * diff --git a/classes/plugin/AdminBaseController.php b/classes/plugin/AdminBaseController.php index 100b6eb03..6ce6df43e 100644 --- a/classes/plugin/AdminBaseController.php +++ b/classes/plugin/AdminBaseController.php @@ -96,6 +96,8 @@ public function execute() // Make sure that user is logged into admin. if (!$this->admin->authorize()) { + $this->respondUnauthorizedIfAjax(); + return false; } @@ -236,6 +238,31 @@ protected function sendJsonResponse(array $json, $code = 200): void $this->close($response); } + /** + * Return a JSON 401 response when an unauthenticated request was clearly triggered via AJAX. + * + * @return void + */ + protected function respondUnauthorizedIfAjax(): void + { + $uri = $this->grav['uri'] ?? null; + $extension = $uri ? $uri->extension() : null; + $accept = $_SERVER['HTTP_ACCEPT'] ?? ''; + $requestedWith = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''; + + $acceptsJson = is_string($accept) && (stripos($accept, 'application/json') !== false || stripos($accept, 'text/json') !== false); + $isAjax = ($extension === 'json') || $acceptsJson || (is_string($requestedWith) && strtolower($requestedWith) === 'xmlhttprequest'); + + if (!$isAjax) { + return; + } + + $this->sendJsonResponse([ + 'status' => 'unauthenticated', + 'message' => Admin::translate('PLUGIN_ADMIN.SESSION_EXPIRED_DESC') + ], 401); + } + /** * @param ResponseInterface $response * @return never-return diff --git a/classes/plugin/AdminController.php b/classes/plugin/AdminController.php index 36b56c0ed..23b8c1f48 100644 --- a/classes/plugin/AdminController.php +++ b/classes/plugin/AdminController.php @@ -54,6 +54,9 @@ */ class AdminController extends AdminBaseController { + /** @var SafeUpgradeManager|null */ + protected $safeUpgradeManager; + /** * @param Grav|null $grav * @param string|null $view @@ -750,6 +753,18 @@ public function taskActivate() // INSTALL & UPGRADE + /** + * @return SafeUpgradeManager + */ + protected function getSafeUpgradeManager() + { + if (null === $this->safeUpgradeManager) { + $this->safeUpgradeManager = new SafeUpgradeManager(); + } + + return $this->safeUpgradeManager; + } + /** * Handles updating Grav * @@ -791,6 +806,273 @@ public function taskUpdategrav() $this->sendJsonResponse($json_response); } + /** + * Safe upgrade preflight endpoint. + * + * Route: GET /update.json/task:safeUpgradePreflight (AJAX call) + * + * @return bool + */ + public function taskSafeUpgradePreflight() + { + if (!$this->authorizeTask('install grav', ['admin.super'])) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') + ]; + + return false; + } + + $post = $this->getPost($_POST ?? []); + $force = !empty($post['force']); + + $result = $this->getSafeUpgradeManager()->preflight($force); + + $status = $result['status'] ?? 'ready'; + $response = [ + 'status' => $status === 'error' ? 'error' : 'success', + 'data' => $result, + ]; + + if (!empty($result['message'])) { + $response['message'] = $result['message']; + } + + $this->sendJsonResponse($response); + + return true; + } + + /** + * Start safe upgrade process. + * + * Route: POST /update.json/task:safeUpgradeStart (AJAX call) + * + * @return bool + */ + public function taskSafeUpgradeStart() + { + if (!$this->authorizeTask('install grav', ['admin.super'])) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') + ]; + + return false; + } + + $post = $this->getPost($_POST ?? []); + $options = [ + 'force' => !empty($post['force']), + 'timeout' => isset($post['timeout']) ? (int)$post['timeout'] : 30, + 'overwrite' => !empty($post['overwrite']), + 'decisions' => isset($post['decisions']) && is_array($post['decisions']) ? $post['decisions'] : [], + ]; + + $manager = $this->getSafeUpgradeManager(); + $result = $manager->queue($options); + $status = $result['status'] ?? 'error'; + + if ($status === 'error') { + $manager->clearJobContext(); + $result = $manager->run($options); + $status = $result['status'] ?? 'error'; + $result['fallback'] = true; + } + + $response = [ + 'status' => $status === 'error' ? 'error' : 'success', + 'data' => $result, + ]; + + if (!empty($result['message'])) { + $response['message'] = $result['message']; + } + + $this->sendJsonResponse($response); + + return true; + } + + /** + * Poll safe upgrade progress. + * + * Route: GET /update.json/task:safeUpgradeStatus (AJAX call) + * + * @return bool + */ + public function taskSafeUpgradeStatus() + { + if (!$this->authorizeTask('install grav', ['admin.super'])) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') + ]; + + return false; + } + + $manager = $this->getSafeUpgradeManager(); + $jobId = isset($_GET['job']) ? (string)$_GET['job'] : ''; + + if ($jobId !== '') { + $data = $manager->getJobStatus($jobId); + } else { + $data = [ + 'job' => null, + 'progress' => $manager->getProgress(), + ]; + } + + $this->sendJsonResponse([ + 'status' => 'success', + 'data' => $data, + ]); + + return true; + } + + /** + * Restore a safe-upgrade snapshot via Tools. + * + * Route: POST /tools/restore-grav?task:safeUpgradeRestore + * + * @return bool + */ + public function taskSafeUpgradeRestore() + { + if (!$this->authorizeTask('install grav', ['admin.super'])) { + $this->sendJsonResponse([ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') + ]); + + return false; + } + + $post = $this->getPost($_POST ?? []); + $snapshotId = isset($post['snapshot']) ? (string)$post['snapshot'] : ''; + + if ($snapshotId === '') { + $this->sendJsonResponse([ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.RESTORE_GRAV_INVALID') + ]); + + return true; + } + + $manager = $this->getSafeUpgradeManager(); + $result = $manager->queueRestore($snapshotId); + $status = $result['status'] ?? 'error'; + + $response = [ + 'status' => $status === 'error' ? 'error' : 'success', + 'data' => $result, + ]; + + if (!empty($result['message'])) { + $response['message'] = $result['message']; + } + + $this->sendJsonResponse($response); + + return true; + } + + /** + * Create a manual safe-upgrade snapshot via Tools. + * + * Route: POST /tools/restore-grav?task:safeUpgradeSnapshot + * + * @return bool + */ + public function taskSafeUpgradeSnapshot() + { + if (!$this->authorizeTask('install grav', ['admin.super'])) { + $this->sendJsonResponse([ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') + ]); + + return false; + } + + $post = $this->getPost($_POST ?? []); + $label = isset($post['label']) ? (string)$post['label'] : null; + + $manager = $this->getSafeUpgradeManager(); + $result = $manager->queueSnapshot($label); + $status = $result['status'] ?? 'error'; + + $response = [ + 'status' => $status === 'error' ? 'error' : 'success', + 'data' => $result, + ]; + + if (!empty($result['message'])) { + $response['message'] = $result['message']; + } + + $this->sendJsonResponse($response); + + return true; + } + + /** + * Delete one or more safe-upgrade snapshots via Tools. + * + * Route: POST /tools/restore-grav?task:safeUpgradeDelete + * + * @return bool + */ + public function taskSafeUpgradeDelete() + { + if (!$this->authorizeTask('install grav', ['admin.super'])) { + return false; + } + + $post = $this->getPost($_POST ?? []); + $snapshots = $post['snapshots'] ?? []; + if (is_string($snapshots)) { + $snapshots = [$snapshots]; + } + + if (empty($snapshots)) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.RESTORE_GRAV_INVALID'), 'error'); + $this->setRedirect('/tools/restore-grav'); + + return false; + } + + $manager = $this->getSafeUpgradeManager(); + $results = $manager->deleteSnapshots($snapshots); + + $success = array_filter($results, static function ($item) { + return ($item['status'] ?? 'error') === 'success'; + }); + $failed = array_filter($results, static function ($item) { + return ($item['status'] ?? 'error') !== 'success'; + }); + + if ($success) { + $this->admin->setMessage( + sprintf($this->admin::translate('PLUGIN_ADMIN.RESTORE_GRAV_DELETE_SUCCESS'), count($success)), + 'info' + ); + } + + foreach ($failed as $entry) { + $message = $entry['message'] ?? $this->admin::translate('PLUGIN_ADMIN.RESTORE_GRAV_DELETE_FAILED'); + $this->admin->setMessage($message, 'error'); + } + + $this->setRedirect('/tools/restore-grav'); + + return true; + } + /** * Handles uninstalling plugins and themes * @@ -2144,6 +2426,7 @@ protected function taskListmedia() * @var string $name * @var Medium|ImageMedium $medium */ + $this->grav['log']->debug('[AI Pro][listmedia] route=' . $this->route . ' path=' . ($media->getPath() ?: 'n/a') . ' count=' . count($media->all())); foreach ($media->all() as $name => $medium) { $metadata = []; diff --git a/classes/plugin/Controllers/Login/LoginController.php b/classes/plugin/Controllers/Login/LoginController.php index 2c7bc2f46..da18e3e02 100644 --- a/classes/plugin/Controllers/Login/LoginController.php +++ b/classes/plugin/Controllers/Login/LoginController.php @@ -231,6 +231,34 @@ public function taskLogout(): ResponseInterface return $this->createRedirectResponse('/'); } + /** + * Return a fresh login nonce and keep anonymous session alive while on the login screen. + * + * Route: GET /login.json/task:nonce + * + * @return ResponseInterface + */ + public function taskNonce(): ResponseInterface + { + // Touch the anonymous session to prevent immediate expiry on the login page. + $session = $this->getSession(); + if (!$session->isStarted()) { + $session->start(); + } + $session->__set('admin_login_keepalive', time()); + + // Generate a fresh nonce for the login form. + $nonce = Admin::getNonce($this->nonce_action); + + return $this->createJsonResponse([ + 'status' => 'success', + 'message' => null, + 'nonce_name' => $this->nonce_name, + 'nonce_action' => $this->nonce_action, + 'nonce' => $nonce + ]); + } + /** * Handle 2FA verification. * diff --git a/classes/plugin/Routers/LoginRouter.php b/classes/plugin/Routers/LoginRouter.php index c027d0287..ae5a599f3 100644 --- a/classes/plugin/Routers/LoginRouter.php +++ b/classes/plugin/Routers/LoginRouter.php @@ -47,8 +47,9 @@ public function matchServerRequest(ServerRequestInterface $request): array ]; } - $httpMethod = $request->getMethod(); - $template = $this->taskTemplates[$task] ?? $adminInfo['view']; + $httpMethod = $request->getMethod() ?? ''; + $template = $this->taskTemplates[$task ?? ''] ?? $adminInfo['view']; + $params = []; switch ($template) { diff --git a/classes/plugin/SafeUpgradeManager.php b/classes/plugin/SafeUpgradeManager.php new file mode 100644 index 000000000..6d9c03855 --- /dev/null +++ b/classes/plugin/SafeUpgradeManager.php @@ -0,0 +1,1899 @@ +grav = $grav ?? Grav::instance(); + $this->recovery = $this->grav['recovery']; + $this->logger = $this->grav['log'] ?? null; + + $locator = $this->grav['locator']; + $this->progressDir = $locator->findResource('user://data/upgrades', true, true); + $this->jobsDir = $this->progressDir . '/jobs'; + + Folder::create($this->jobsDir); + + $this->setJobId(null); + } + + protected function setJobId(?string $jobId): void + { + $this->jobId = $jobId ?: null; + + if ($this->jobId) { + $jobDir = $this->getJobDir($this->jobId); + Folder::create($jobDir); + $this->jobManifestPath = $jobDir . '/' . self::JOB_MANIFEST; + $this->progressPath = $jobDir . '/' . self::JOB_PROGRESS; + $this->log(sprintf('Safe upgrade job %s activated', $this->jobId), 'debug'); + } else { + $this->jobManifestPath = null; + $this->progressPath = $this->progressDir . '/' . self::PROGRESS_FILENAME; + $this->log('Safe upgrade job context cleared', 'debug'); + } + } + + public function clearJobContext(): void + { + $this->setJobId(null); + } + + /** + * @return array + */ + public function listSnapshots(): array + { + $manifestDir = GRAV_ROOT . '/user/data/upgrades'; + if (!is_dir($manifestDir)) { + return []; + } + + $files = glob($manifestDir . '/*.json') ?: []; + rsort($files); + + $snapshots = []; + foreach ($files as $file) { + $decoded = json_decode(file_get_contents($file) ?: '', true); + if (!is_array($decoded) || empty($decoded['id'])) { + continue; + } + + $createdAt = isset($decoded['created_at']) ? (int)$decoded['created_at'] : 0; + + $snapshots[] = [ + 'id' => (string)$decoded['id'], + 'label' => isset($decoded['label']) && $decoded['label'] !== '' ? (string)$decoded['label'] : null, + 'source_version' => $decoded['source_version'] ?? null, + 'target_version' => $decoded['target_version'] ?? null, + 'created_at' => $createdAt, + 'created_at_iso' => $createdAt > 0 ? date('c', $createdAt) : null, + 'backup_path' => $decoded['backup_path'] ?? null, + 'package_path' => $decoded['package_path'] ?? null, + ]; + } + + return $snapshots; + } + + public function hasSnapshots(): bool + { + return !empty($this->listSnapshots()); + } + + /** + * @param string $snapshotId + * @return array{status:string,message:?string,manifest:array|null} + */ + public function restoreSnapshot(string $snapshotId): array + { + if (!$this->isSafeUpgradeEnabled()) { + return [ + 'status' => 'error', + 'message' => 'Safe upgrade is disabled in configuration.', + 'manifest' => null, + ]; + } + + try { + $safeUpgrade = $this->getSafeUpgradeService(); + $manifest = $safeUpgrade->rollback($snapshotId); + } catch (RuntimeException $e) { + return [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'manifest' => null, + ]; + } catch (Throwable $e) { + return [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'manifest' => null, + ]; + } + + if (!$manifest) { + return [ + 'status' => 'error', + 'message' => sprintf('Snapshot %s not found.', $snapshotId), + 'manifest' => null, + ]; + } + + return [ + 'status' => 'success', + 'message' => null, + 'manifest' => $manifest, + ]; + } + + public function queueRestore(string $snapshotId): array + { + $snapshotId = trim($snapshotId); + if ($snapshotId === '') { + return [ + 'status' => 'error', + 'message' => 'Snapshot identifier is required.', + ]; + } + + $manifestPath = GRAV_ROOT . '/user/data/upgrades/' . $snapshotId . '.json'; + if (!is_file($manifestPath)) { + return [ + 'status' => 'error', + 'message' => sprintf('Snapshot %s not found.', $snapshotId), + ]; + } + + return $this->queue([ + 'operation' => 'restore', + 'snapshot_id' => $snapshotId, + ]); + } + + public function queueSnapshot(?string $label = null): array + { + $options = [ + 'operation' => 'snapshot', + ]; + + if (null !== $label) { + $label = trim((string)$label); + if ($label !== '') { + $options['label'] = $label; + } + } + + return $this->queue($options); + } + + /** + * @param array $snapshotIds + * @return array + */ + public function deleteSnapshots(array $snapshotIds): array + { + $ids = array_values(array_unique(array_filter(array_map('strval', $snapshotIds)))); + $results = []; + + foreach ($ids as $id) { + $results[] = $this->deleteSnapshot($id); + } + + return $results; + } + + /** + * @param string $snapshotId + * @return array{id:string,status:string,message:?string} + */ + protected function deleteSnapshot(string $snapshotId): array + { + $manifestDir = GRAV_ROOT . '/user/data/upgrades'; + $manifestPath = $manifestDir . '/' . $snapshotId . '.json'; + + if (!is_file($manifestPath)) { + return [ + 'id' => $snapshotId, + 'status' => 'error', + 'message' => sprintf('Snapshot %s not found.', $snapshotId), + ]; + } + + $manifest = json_decode(file_get_contents($manifestPath) ?: '', true); + if (!is_array($manifest)) { + return [ + 'id' => $snapshotId, + 'status' => 'error', + 'message' => sprintf('Snapshot %s manifest is corrupted.', $snapshotId), + ]; + } + + $errors = []; + foreach (['package_path', 'backup_path'] as $key) { + $path = isset($manifest[$key]) ? (string)$manifest[$key] : ''; + if ($path === '' || !file_exists($path)) { + continue; + } + + try { + if (is_dir($path)) { + Folder::delete($path); + } else { + @unlink($path); + } + } catch (Throwable $e) { + $errors[] = $e->getMessage(); + } + } + + if (!@unlink($manifestPath)) { + $errors[] = sprintf('Unable to delete manifest file %s.', $manifestPath); + } + + if ($errors) { + return [ + 'id' => $snapshotId, + 'status' => 'error', + 'message' => implode(' ', $errors), + ]; + } + + return [ + 'id' => $snapshotId, + 'status' => 'success', + 'message' => sprintf('Snapshot %s removed.', $snapshotId), + ]; + } + + protected function getJobDir(string $jobId): string + { + return $this->jobsDir . '/' . $jobId; + } + + protected function generateJobId(): string + { + return 'job-' . gmdate('YmdHis') . '-' . substr(md5(uniqid('', true)), 0, 8); + } + + protected function log(string $message, string $level = 'info'): void + { + if (!$this->logger) { + return; + } + + try { + if (method_exists($this->logger, $level)) { + $this->logger->$level('[SafeUpgrade] ' . $message); + } else { + $this->logger->info('[SafeUpgrade] ' . $message); + } + } catch (Throwable $e) { + // ignore logging errors + } + } + + protected function writeManifest(array $data): void + { + if (!$this->jobManifestPath) { + return; + } + + try { + $existing = []; + if (is_file($this->jobManifestPath)) { + $decoded = json_decode((string)file_get_contents($this->jobManifestPath), true); + if (is_array($decoded)) { + $existing = $decoded; + } + } + + $payload = $existing + [ + 'id' => $this->jobId, + 'created_at' => time(), + ]; + + $payload = array_merge($payload, $data, [ + 'updated_at' => time(), + ]); + + Folder::create(dirname($this->jobManifestPath)); + file_put_contents($this->jobManifestPath, json_encode($payload, JSON_PRETTY_PRINT)); + if (!empty($data['status'])) { + $this->log(sprintf('Job %s status -> %s', $payload['id'] ?? $this->jobId ?? 'unknown', $data['status']), 'debug'); + } + } catch (Throwable $e) { + // ignore manifest write failures + } + } + + public function updateJob(array $data): void + { + $this->writeManifest($data); + } + + public function ensureJobResult(array $result): void + { + if (!$this->jobManifestPath) { + return; + } + + $status = $result['status'] ?? null; + $progress = $this->getProgress(); + + if ($status === 'success') { + $targetVersion = $result['version'] ?? ($result['manifest']['target_version'] ?? null); + $manifest = $result['manifest'] ?? null; + + if (($progress['stage'] ?? null) !== 'complete') { + $extras = []; + if ($targetVersion !== null) { + $extras['target_version'] = $targetVersion; + } + if ($manifest !== null) { + $extras['manifest'] = $manifest; + } + + $this->setProgress('complete', 'Upgrade complete.', 100, $extras); + $progress = $this->getProgress(); + } + + $this->updateJob([ + 'status' => 'success', + 'completed_at' => time(), + 'result' => $result, + 'progress' => $progress, + ]); + + return; + } + + if ($status === 'error') { + $message = $result['message'] ?? 'Safe upgrade failed.'; + if (($progress['stage'] ?? null) !== 'error') { + $this->setProgress('error', $message, null, ['message' => $message]); + $progress = $this->getProgress(); + } + + $this->updateJob([ + 'status' => 'error', + 'completed_at' => time(), + 'result' => $result, + 'progress' => $progress, + 'error' => $message, + ]); + + return; + } + + if ($status === 'noop' || $status === 'finalized') { + if (($progress['stage'] ?? null) !== 'complete') { + $this->setProgress('complete', $progress['message'] ?? 'Upgrade complete.', 100, [ + 'target_version' => $result['version'] ?? null, + 'manifest' => $result['manifest'] ?? null, + ]); + $progress = $this->getProgress(); + } + + $this->updateJob([ + 'status' => $status, + 'completed_at' => time(), + 'result' => $result, + 'progress' => $progress, + ]); + } + } + + public function markJobError(string $message): void + { + $this->setProgress('error', $message, null, ['message' => $message]); + } + + protected function readManifest(?string $path = null): array + { + $target = $path ?? $this->jobManifestPath; + if (!$target || !is_file($target)) { + return []; + } + + $decoded = json_decode((string)file_get_contents($target), true); + + return is_array($decoded) ? $decoded : []; + } + + public function loadJob(string $jobId): array + { + $this->setJobId($jobId); + + return $this->readManifest(); + } + + public function getJobStatus(string $jobId): array + { + $manifest = $this->loadJob($jobId); + $progress = $this->getProgress(); + + $result = [ + 'job' => $manifest ?: null, + 'progress' => $progress, + 'context' => $this->buildStatusContext(), + ]; + + $this->clearJobContext(); + + return $result; + } + + public function queue(array $options = []): array + { + $operation = $options['operation'] ?? 'upgrade'; + $options['operation'] = $operation; + + $this->resetProgress(); + $jobId = $this->generateJobId(); + $this->setJobId($jobId); + + $jobDir = $this->getJobDir($jobId); + Folder::create($jobDir); + + $logPath = $jobDir . '/worker.log'; + + $timestamp = time(); + + $manifest = [ + 'id' => $jobId, + 'status' => 'queued', + 'options' => $options, + 'log' => $logPath, + 'created_at' => $timestamp, + 'started_at' => null, + 'completed_at' => null, + ]; + $this->writeManifest($manifest); + + try { + file_put_contents($logPath, '[' . gmdate('c') . "] Job {$jobId} queued\n"); + } catch (Throwable $e) { + // ignore log write failures + } + + $this->log(sprintf('Queued safe upgrade job %s', $jobId)); + + if ($operation === 'restore') { + $queueMessage = 'Waiting for restore worker...'; + } elseif ($operation === 'snapshot') { + $queueMessage = 'Waiting for snapshot worker...'; + } else { + $queueMessage = 'Waiting for upgrade worker...'; + } + $queuedExtras = [ + 'job_id' => $jobId, + 'status' => 'queued', + 'operation' => $operation, + ]; + if ($operation === 'snapshot') { + if (isset($options['label']) && is_string($options['label'])) { + $queuedExtras['label'] = $options['label']; + } + $queuedExtras['mode'] = 'manual'; + } + $this->setProgress('queued', $queueMessage, 0, $queuedExtras); + + if (!function_exists('proc_open')) { + $message = 'proc_open() is disabled on this server; unable to run safe upgrade worker.'; + $this->writeManifest([ + 'status' => 'error', + 'error' => $message, + ]); + $this->setProgress('error', $message, null, ['job_id' => $jobId, 'operation' => $operation]); + $this->clearJobContext(); + + return [ + 'status' => 'error', + 'message' => $message, + 'operation' => $operation, + ]; + } + + try { + $finder = new PhpExecutableFinder(); + $phpPath = $finder->find(false) ?: PHP_BINARY; + if (!$phpPath) { + throw new RuntimeException('Unable to locate PHP CLI to start safe upgrade worker.'); + } + + $gravPath = Utils::isWindows() + ? GRAV_ROOT . '\\bin\\grav' + : GRAV_ROOT . '/bin/grav'; + + if (!is_file($gravPath)) { + throw new RuntimeException('Unable to locate Grav CLI binary.'); + } + + if (Utils::isWindows()) { + $commandLine = sprintf( + 'start /B "" %s %s safe-upgrade:run --job=%s >> %s 2>&1', + escapeshellarg($phpPath), + escapeshellarg($gravPath), + escapeshellarg($jobId), + escapeshellarg($logPath) + ); + } else { + $commandLine = sprintf( + 'nohup %s %s safe-upgrade:run --job=%s >> %s 2>&1 &', + escapeshellarg($phpPath), + escapeshellarg($gravPath), + escapeshellarg($jobId), + escapeshellarg($logPath) + ); + } + + try { + file_put_contents($logPath, '[' . gmdate('c') . "] Command: {$commandLine}\n", FILE_APPEND); + } catch (Throwable $e) { + // ignore log write failures + } + + $this->log(sprintf('Spawn command for job %s: %s', $jobId, $commandLine), 'debug'); + + $process = Process::fromShellCommandline($commandLine, GRAV_ROOT, null, null, 3); + $process->disableOutput(); + $process->run(); + } catch (Throwable $e) { + $message = $e->getMessage(); + $this->writeManifest([ + 'status' => 'error', + 'error' => $message, + ]); + $this->setProgress('error', $message, null, ['job_id' => $jobId, 'operation' => $operation]); + $this->clearJobContext(); + + return [ + 'status' => 'error', + 'message' => $message, + 'operation' => $operation, + ]; + } + + $this->writeManifest([ + 'status' => 'running', + 'started_at' => time(), + ]); + + $this->log(sprintf('Safe upgrade job %s worker started', $jobId)); + + return [ + 'status' => 'queued', + 'job_id' => $jobId, + 'log' => $logPath, + 'progress' => $this->getProgress(), + 'job' => $this->readManifest(), + 'context' => $this->buildStatusContext(), + 'operation' => $operation, + ]; + } + + /** + * Execute preflight checks and return upgrade readiness data. + * + * @param bool $force + * @return array + */ + public function preflight(bool $force = false): array + { + $this->resetProgress(); + + if (!class_exists(ZipArchive::class)) { + return [ + 'status' => 'error', + 'message' => 'php-zip extension needs to be enabled.', + ]; + } + + try { + $this->upgrader = new Upgrader($force); + } catch (Throwable $e) { + return [ + 'status' => 'error', + 'message' => $e->getMessage(), + ]; + } + + $local = $this->upgrader->getLocalVersion(); + $remote = $this->upgrader->getRemoteVersion(); + $releaseDate = $this->upgrader->getReleaseDate(); + $assets = $this->upgrader->getAssets(); + $package = $this->resolveAsset($assets, 'grav-update'); + + $payload = [ + 'status' => 'ready', + 'version' => [ + 'local' => $local, + 'remote' => $remote, + 'release_date' => $releaseDate ? strftime('%c', strtotime($releaseDate)) : null, + 'package_size' => $package['size'] ?? null, + ], + 'upgrade_available' => $this->upgrader->isUpgradable(), + 'requirements' => [ + 'meets' => $this->upgrader->meetsRequirements(), + 'minimum_php' => $this->upgrader->minPHPVersion(), + ], + 'symlinked' => false, + 'safe_upgrade' => [ + 'enabled' => $this->isSafeUpgradeEnabled(), + 'staging_ready' => true, + 'error' => null, + ], + 'preflight' => [ + 'warnings' => [], + 'plugins_pending' => [], + 'psr_log_conflicts' => [], + 'monolog_conflicts' => [], + ], + ]; + + $report = $this->collectLocalPreflightReport($remote ?? $local); + $payload['preflight'] = $report; + $payload['preflight']['blocking'] = $report['blocking'] ?? []; + + Installer::isValidDestination(GRAV_ROOT . '/system'); + $payload['symlinked'] = Installer::IS_LINK === Installer::lastErrorCode(); + + return $payload; + } + + /** + * Run the safe upgrade lifecycle. + * + * @param array $options + * @return array + */ + public function run(array $options = []): array + { + $operation = isset($options['operation']) ? (string)$options['operation'] : 'upgrade'; + if ($operation === 'restore') { + return $this->runRestore($options); + } + + if ($operation === 'snapshot') { + return $this->runSnapshot($options); + } + + $force = (bool)($options['force'] ?? false); + $timeout = (int)($options['timeout'] ?? 30); + $overwrite = (bool)($options['overwrite'] ?? false); + $decisions = is_array($options['decisions'] ?? null) ? $options['decisions'] : []; + $this->preflightDecisions = $decisions; + + $this->setProgress('initializing', 'Preparing safe upgrade...', null); + + if (!class_exists(ZipArchive::class)) { + return $this->errorResult('php-zip extension needs to be enabled.'); + } + + try { + $this->upgrader = new Upgrader($force); + } catch (Throwable $e) { + return $this->errorResult($e->getMessage()); + } + + $safeUpgradeEnabled = $this->isSafeUpgradeEnabled(); + if (!$safeUpgradeEnabled) { + return $this->errorResult('Safe upgrade is disabled in configuration.'); + } + + $remoteVersion = $this->upgrader->getRemoteVersion(); + $localVersion = $this->upgrader->getLocalVersion(); + + if (!$this->upgrader->meetsRequirements()) { + $minPhp = $this->upgrader->minPHPVersion(); + $message = sprintf( + 'Grav requires PHP %s, current PHP version is %s.', + $minPhp, + PHP_VERSION + ); + + return $this->errorResult($message, [ + 'minimum_php' => $minPhp, + 'current_php' => PHP_VERSION, + ]); + } + + if (!$overwrite && !$this->upgrader->isUpgradable()) { + $result = $this->runFinalizeIfNeeded($localVersion); + if ($result) { + return $result; + } + + return [ + 'status' => 'noop', + 'version' => $localVersion, + 'message' => 'Grav is already up to date.', + 'context' => $this->buildStatusContext(), + ]; + } + + Installer::isValidDestination(GRAV_ROOT . '/system'); + if (Installer::IS_LINK === Installer::lastErrorCode()) { + return $this->errorResult('Grav installation is symlinked, cannot perform upgrade.'); + } + + // NOTE: We no longer create SafeUpgradeService here because it would load the OLD class. + // Preflight checks are now run in Install.php AFTER downloading, using the NEW code. + + if (defined('Monolog\\Logger::API') && \Monolog\Logger::API < 3) { + class_exists(\Monolog\Logger::class); + class_exists(\Monolog\Handler\AbstractHandler::class); + class_exists(\Monolog\Handler\AbstractProcessingHandler::class); + class_exists(\Monolog\Handler\StreamHandler::class); + class_exists(\Monolog\Formatter\LineFormatter::class); + } + + // NOTE: Preflight checks are now run in Install.php AFTER downloading the package. + // This ensures we use the NEW SafeUpgradeService from the package, not the old one. + // Running preflight here would load the OLD class into memory and prevent the new one from loading. + + $assets = $this->upgrader->getAssets(); + $package = $this->resolveAsset($assets, 'grav-update'); + if (!$package) { + return $this->errorResult('Unable to locate Grav update package information.'); + } + + if ($this->recovery && method_exists($this->recovery, 'markUpgradeWindow')) { + // Newer Grav exposes upgrade window helpers; guard for older cores. + $this->recovery->markUpgradeWindow('core-upgrade', [ + 'scope' => 'core', + 'target_version' => $remoteVersion, + ]); + } + + try { + $file = $this->download($package, $timeout); + $this->performInstall($file); + $this->setProgress('installing', 'Preparing promotion...', null); + } catch (Throwable $e) { + $this->setProgress('error', $e->getMessage(), null); + + return $this->errorResult($e->getMessage()); + } finally { + if ($this->tmp && is_dir($this->tmp)) { + Folder::delete($this->tmp); + } + $this->tmp = null; + $this->preflightDecisions = []; + } + + $this->setProgress('finalizing', 'Finalizing upgrade...', null); + $this->clearRecoveryFlag(); + + $this->ensureExecutablePermissions(); + $this->setProgress('finalizing', 'Finalizing upgrade...', null); + + $manifest = $this->resolveLatestManifest(); + + $this->setProgress('complete', 'Upgrade complete.', 100, [ + 'target_version' => $remoteVersion, + 'manifest' => $manifest, + ]); + + if ($this->jobManifestPath) { + $this->updateJob([ + 'result' => [ + 'status' => 'success', + 'version' => $remoteVersion, + 'previous_version' => $localVersion, + 'manifest' => $manifest, + ], + ]); + } + + return [ + 'status' => 'success', + 'version' => $remoteVersion, + 'manifest' => $manifest, + 'previous_version' => $localVersion, + 'context' => $this->buildStatusContext(), + ]; + } + + public function runRestore(array $options): array + { + $snapshotId = isset($options['snapshot_id']) ? (string)$options['snapshot_id'] : ''; + if ($snapshotId === '') { + return $this->errorResult('Snapshot identifier is required.', ['operation' => 'restore']); + } + + $this->setProgress('rollback', sprintf('Restoring snapshot %s...', $snapshotId), null, [ + 'operation' => 'restore', + 'snapshot' => $snapshotId, + ]); + + $result = $this->restoreSnapshot($snapshotId); + if (($result['status'] ?? 'error') !== 'success') { + $message = $result['message'] ?? 'Snapshot restore failed.'; + + return $this->errorResult($message, [ + 'operation' => 'restore', + 'snapshot' => $snapshotId, + ]); + } + + $manifest = $result['manifest'] ?? []; + $version = $manifest['source_version'] ?? $manifest['target_version'] ?? null; + + $this->setProgress('complete', sprintf('Snapshot %s restored.', $snapshotId), 100, [ + 'operation' => 'restore', + 'snapshot' => $snapshotId, + 'version' => $version, + ]); + + if ($this->jobManifestPath) { + $this->updateJob([ + 'result' => [ + 'status' => 'success', + 'snapshot' => $snapshotId, + 'version' => $version, + 'manifest' => $manifest, + 'label' => $label, + ], + ]); + } + + return [ + 'status' => 'success', + 'snapshot' => $snapshotId, + 'version' => $version, + 'manifest' => $manifest, + 'label' => $label, + 'context' => $this->buildStatusContext(), + ]; + } + + public function runSnapshot(array $options): array + { + if (!$this->isSafeUpgradeEnabled()) { + return $this->errorResult('Safe upgrade is disabled in configuration.', [ + 'operation' => 'snapshot' + ]); + } + + $label = isset($options['label']) ? (string)$options['label'] : null; + if ($label !== null) { + $label = trim($label); + if ($label === '') { + $label = null; + } + } + + $this->setProgress('snapshot', 'Creating manual snapshot...', null, [ + 'operation' => 'snapshot', + 'label' => $label, + 'mode' => 'manual', + ]); + + try { + $safeUpgrade = $this->getSafeUpgradeService(); + $manifest = $safeUpgrade->createSnapshot($label); + } catch (RuntimeException $e) { + return $this->errorResult($e->getMessage(), [ + 'operation' => 'snapshot', + ]); + } catch (Throwable $e) { + return $this->errorResult($e->getMessage(), [ + 'operation' => 'snapshot', + ]); + } + + $snapshotId = $manifest['id'] ?? null; + $version = $manifest['source_version'] ?? $manifest['target_version'] ?? null; + + $this->setProgress('complete', sprintf('Snapshot %s created.', $snapshotId ?? '(unknown)'), 100, [ + 'operation' => 'snapshot', + 'snapshot' => $snapshotId, + 'version' => $version, + 'label' => $label, + 'mode' => 'manual', + ]); + + if ($this->jobManifestPath) { + $this->updateJob([ + 'result' => [ + 'status' => 'success', + 'snapshot' => $snapshotId, + 'version' => $version, + 'manifest' => $manifest, + 'label' => $label, + ], + ]); + } + + return [ + 'status' => 'success', + 'snapshot' => $snapshotId, + 'version' => $version, + 'manifest' => $manifest, + 'label' => $label, + 'context' => $this->buildStatusContext(), + ]; + } + + /** + * Retrieve current progress payload. + * + * @return array + */ + public function getProgress(): array + { + if (!is_file($this->progressPath)) { + return [ + 'stage' => 'idle', + 'message' => '', + 'percent' => null, + 'timestamp' => time(), + ]; + } + + $decoded = json_decode((string)file_get_contents($this->progressPath), true); + if (!is_array($decoded)) { + return [ + 'stage' => 'idle', + 'message' => '', + 'percent' => null, + 'timestamp' => time(), + ]; + } + + return $decoded; + } + + /** + * Reset progress file to idle state. + * + * @return void + */ + public function resetProgress(): void + { + $this->setProgress('idle', '', null); + } + + /** + * @return SafeUpgradeService + */ + protected function getSafeUpgradeService(): SafeUpgradeService + { + if ($this->safeUpgrade instanceof SafeUpgradeService) { + return $this->safeUpgrade; + } + + $config = null; + try { + $config = $this->grav['config'] ?? null; + } catch (Throwable $e) { + $config = null; + } + + $this->safeUpgrade = new SafeUpgradeService([ + 'config' => $config, + ]); + if (method_exists($this->safeUpgrade, 'setProgressCallback')) { + $this->safeUpgrade->setProgressCallback(function (string $stage, string $message, ?int $percent = null, array $extra = []) { + $this->setProgress($stage, $message, $percent); + }); + } + + return $this->safeUpgrade; + } + + /** + * @return bool + */ + protected function isSafeUpgradeEnabled(): bool + { + try { + $config = $this->grav['config'] ?? null; + return self::configAllowsSafeUpgrade($config); + } catch (Throwable $e) { + return false; + } + } + + /** + * @param Config|null $config + * @return bool + */ + public static function configAllowsSafeUpgrade(?Config $config): bool + { + if ($config === null) { + return false; + } + + $value = $config->get('system.updates.safe_upgrade'); + if ($value === null) { + return false; + } + + if (is_string($value)) { + $filtered = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); + if ($filtered === null) { + return false; + } + + return $filtered; + } + + return (bool)$value; + } + + /** + * @param array $preflight + * @param array $decisions + * @return array|null + */ + protected function handleConflictDecisions(array $preflight, array $decisions): ?array + { + $psrConflicts = $preflight['psr_log_conflicts'] ?? []; + $monologConflicts = $preflight['monolog_conflicts'] ?? []; + + if ($psrConflicts) { + $decision = $decisions['psr_log'] ?? null; + $error = $this->applyConflictDecision( + $decision, + $psrConflicts, + 'Disabled before upgrade because of psr/log conflict' + ); + if ($error !== null) { + return $error; + } + } + + if ($monologConflicts) { + $decision = $decisions['monolog'] ?? null; + $error = $this->applyConflictDecision( + $decision, + $monologConflicts, + 'Disabled before upgrade because of Monolog API conflict' + ); + if ($error !== null) { + return $error; + } + } + + return null; + } + + protected function enforcePreflightReport(array $preflight, array $decisions): void + { + if (!$preflight) { + return; + } + + $pending = $preflight['plugins_pending'] ?? []; + if ($pending) { + $decision = $decisions['pending'] ?? 'abort'; + if ($decision !== 'continue') { + $list = []; + foreach ($pending as $slug => $info) { + $current = $info['current'] ?? 'unknown'; + $available = $info['available'] ?? 'unknown'; + $list[] = sprintf('%s (%s → %s)', $slug, $current, $available); + } + + throw new RuntimeException( + "Plugin/theme updates required before upgrading Grav:\n - " . implode("\n - ", $list) + ); + } + + Install::allowPendingPackageOverride(true); + $this->setProgress('warning', 'Proceeding despite pending plugin/theme updates.', null); + } + + $blocking = $preflight['blocking'] ?? []; + if ($blocking) { + throw new RuntimeException($blocking[0]); + } + + $error = $this->handleConflictDecisions($preflight, $decisions); + if ($error !== null) { + throw new RuntimeException($error['message'] ?? 'Upgrade aborted due to unresolved conflicts.'); + } + } + + /** + * @param string|null $decision + * @param array $conflicts + * @param string $disableNote + * @return array|null + */ + protected function applyConflictDecision(?string $decision, array $conflicts, string $disableNote): ?array + { + if (!$conflicts) { + return null; + } + + $choice = $decision ?: 'abort'; + if ($choice === 'abort') { + return $this->errorResult('Upgrade aborted due to unresolved conflicts.', [ + 'conflicts' => $conflicts, + ]); + } + + if ($choice === 'disable') { + foreach (array_keys($conflicts) as $slug) { + $this->recovery->disablePlugin($slug, ['message' => $disableNote]); + } + + return null; + } + + if ($choice === 'continue') { + return null; + } + + return $this->errorResult('Unknown conflict decision provided.', [ + 'conflicts' => $conflicts, + ]); + } + + protected function collectLocalPreflightReport(?string $targetVersion): array + { + $targetVersion = $targetVersion ?: GRAV_VERSION; + $report = [ + 'warnings' => [], + 'psr_log_conflicts' => [], + 'monolog_conflicts' => [], + 'plugins_pending' => [], + 'is_major_minor_upgrade' => $this->isMajorMinorUpgradeLocal($targetVersion), + 'blocking' => [], + ]; + + $report['plugins_pending'] = $this->detectPendingPackages(); + $report['psr_log_conflicts'] = $this->detectPsrLogConflictsLocal(); + $report['monolog_conflicts'] = $this->detectMonologConflictsLocal(); + + if ($report['plugins_pending'] && $report['is_major_minor_upgrade']) { + $report['blocking'][] = 'Pending plugin/theme updates detected. Because this is a major Grav upgrade, update them before continuing.'; + } + + if ($report['psr_log_conflicts']) { + $report['warnings'][] = 'Potential psr/log conflicts detected.'; + } + + if ($report['monolog_conflicts']) { + $report['warnings'][] = 'Potential Monolog API conflicts detected.'; + } + + return $report; + } + + protected function isMajorMinorUpgradeLocal(string $targetVersion): bool + { + [$currentMajor, $currentMinor] = array_map('intval', array_pad(explode('.', GRAV_VERSION), 2, 0)); + [$targetMajor, $targetMinor] = array_map('intval', array_pad(explode('.', $targetVersion), 2, 0)); + + return $currentMajor !== $targetMajor || $currentMinor !== $targetMinor; + } + + protected function detectPendingPackages(): array + { + $pending = []; + + try { + $gpm = new GPM(); + } catch (Throwable $e) { + $this->setProgress('warning', 'Unable to query GPM repository: ' . $e->getMessage(), null); + + return $pending; + } + + $repoPlugins = $this->packagesToArray($gpm->getRepositoryPlugins()); + $repoThemes = $this->packagesToArray($gpm->getRepositoryThemes()); + + $localPlugins = $this->scanLocalPackageVersions(GRAV_ROOT . '/user/plugins'); + foreach ($localPlugins as $slug => $version) { + $remote = $repoPlugins[$slug] ?? null; + if (!$this->isPackagePublished($remote)) { + continue; + } + $remoteVersion = $this->resolveRemotePackageVersion($remote); + if (!$remoteVersion || !$version) { + continue; + } + if (!$this->isPluginEnabledLocally($slug)) { + continue; + } + + if (version_compare($remoteVersion, $version, '>')) { + $pending[$slug] = [ + 'type' => 'plugin', + 'current' => $version, + 'available' => $remoteVersion, + ]; + } + } + + $localThemes = $this->scanLocalPackageVersions(GRAV_ROOT . '/user/themes'); + foreach ($localThemes as $slug => $version) { + $remote = $repoThemes[$slug] ?? null; + if (!$this->isPackagePublished($remote)) { + continue; + } + $remoteVersion = $this->resolveRemotePackageVersion($remote); + if (!$remoteVersion || !$version) { + continue; + } + if (!$this->isThemeEnabledLocally($slug)) { + continue; + } + + if (version_compare($remoteVersion, $version, '>')) { + $pending[$slug] = [ + 'type' => 'theme', + 'current' => $version, + 'available' => $remoteVersion, + ]; + } + } + + return $pending; + } + + protected function scanLocalPackageVersions(string $path): array + { + $versions = []; + if (!is_dir($path)) { + return $versions; + } + + $entries = glob($path . '/*', GLOB_ONLYDIR) ?: []; + foreach ($entries as $dir) { + $slug = basename($dir); + $version = $this->readBlueprintVersion($dir) ?? $this->readComposerVersion($dir); + if ($version !== null) { + $versions[$slug] = $version; + } + } + + return $versions; + } + + protected function readBlueprintVersion(string $dir): ?string + { + $file = $dir . '/blueprints.yaml'; + if (!is_file($file)) { + return null; + } + + try { + $contents = @file_get_contents($file); + if ($contents === false) { + return null; + } + $data = Yaml::parse($contents); + if (is_array($data) && isset($data['version'])) { + return (string)$data['version']; + } + } catch (Throwable $e) { + // ignore parse errors + } + + return null; + } + + protected function readComposerVersion(string $dir): ?string + { + $file = $dir . '/composer.json'; + if (!is_file($file)) { + return null; + } + + $data = json_decode(file_get_contents($file), true); + if (is_array($data) && isset($data['version'])) { + return (string)$data['version']; + } + + return null; + } + + protected function packagesToArray($packages): array + { + if (!$packages) { + return []; + } + + if (is_array($packages)) { + return $packages; + } + + if ($packages instanceof \Traversable) { + return iterator_to_array($packages, true); + } + + return []; + } + + protected function resolveRemotePackageVersion($package): ?string + { + if (!$package) { + return null; + } + + if (is_array($package)) { + return $package['version'] ?? null; + } + + if (is_object($package)) { + if (isset($package->version)) { + return (string)$package->version; + } + if (method_exists($package, 'offsetGet')) { + try { + return (string)$package->offsetGet('version'); + } catch (Throwable $e) { + return null; + } + } + } + + return null; + } + + protected function detectPsrLogConflictsLocal(): array + { + $conflicts = []; + $pluginRoots = glob(GRAV_ROOT . '/user/plugins/*', GLOB_ONLYDIR) ?: []; + foreach ($pluginRoots as $path) { + $composerFile = $path . '/composer.json'; + if (!is_file($composerFile)) { + continue; + } + + $json = json_decode(file_get_contents($composerFile), true); + if (!is_array($json)) { + continue; + } + + $slug = basename($path); + if (!$this->isPluginEnabledLocally($slug)) { + continue; + } + $rawConstraint = $json['require']['psr/log'] ?? ($json['require-dev']['psr/log'] ?? null); + if (!$rawConstraint) { + continue; + } + + $constraint = strtolower((string)$rawConstraint); + $compatible = $constraint === '*' + || false !== strpos($constraint, '3') + || false !== strpos($constraint, '4') + || (false !== strpos($constraint, '>=') && preg_match('/>=\s*3/', $constraint)); + + if ($compatible) { + continue; + } + + $conflicts[$slug] = [ + 'composer' => $composerFile, + 'requires' => $rawConstraint, + ]; + } + + return $conflicts; + } + + protected function detectMonologConflictsLocal(): array + { + $conflicts = []; + $pluginRoots = glob(GRAV_ROOT . '/user/plugins/*', GLOB_ONLYDIR) ?: []; + $pattern = '/->add(?:Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)\s*\(/i'; + + foreach ($pluginRoots as $path) { + $slug = basename($path); + if (!$this->isPluginEnabledLocally($slug)) { + continue; + } + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS) + ); + + foreach ($iterator as $file) { + if (!$file->isFile() || strtolower($file->getExtension()) !== 'php') { + continue; + } + + $contents = @file_get_contents($file->getPathname()); + if ($contents === false) { + continue; + } + + if (preg_match($pattern, $contents, $match)) { + $relative = str_replace(GRAV_ROOT . '/', '', $file->getPathname()); + $conflicts[$slug][] = [ + 'file' => $relative, + 'method' => trim($match[0]), + ]; + } + } + } + + return $conflicts; + } + + protected function isPluginEnabledLocally(string $slug): bool + { + $configPath = GRAV_ROOT . '/user/config/plugins/' . $slug . '.yaml'; + if (is_file($configPath)) { + try { + $contents = @file_get_contents($configPath); + if ($contents !== false) { + $data = Yaml::parse($contents); + if (is_array($data) && array_key_exists('enabled', $data)) { + return (bool)$data['enabled']; + } + } + } catch (Throwable $e) { + // ignore parse errors + } + } + + return true; + } + + protected function isThemeEnabledLocally(string $slug): bool + { + $configPath = GRAV_ROOT . '/user/config/system.yaml'; + if (is_file($configPath)) { + try { + $contents = @file_get_contents($configPath); + if ($contents !== false) { + $data = Yaml::parse($contents); + if (is_array($data)) { + $active = $data['pages']['theme'] ?? ($data['system']['pages']['theme'] ?? null); + if ($active !== null) { + return $active === $slug; + } + } + } + } catch (Throwable $e) { + // ignore parse errors + } + } + + return true; + } + + protected function isPackagePublished($package): bool + { + if (!$package) { + return false; + } + + if (is_array($package)) { + if (array_key_exists('published', $package)) { + return $package['published'] !== false; + } + + return true; + } + + if (is_object($package) && method_exists($package, 'getData')) { + $data = $package->getData(); + if ($data instanceof \Grav\Common\Data\Data) { + $published = $data->get('published'); + + return $published !== false; + } + } + + if (is_object($package) && property_exists($package, 'published')) { + return $package->published !== false; + } + + return true; + } + + + /** + * @param array $package + * @param int $timeout + * @return string + */ + protected function download(array $package, int $timeout): string + { + $tmpDir = $this->grav['locator']->findResource('tmp://', true, true); + $this->tmp = $tmpDir . '/grav-update-' . uniqid('', false); + + Folder::create($this->tmp); + + $this->setProgress('downloading', 'Downloading update...', 0, [ + 'package_size' => $package['size'] ?? null, + ]); + + $options = [ + 'timeout' => max(0, $timeout), + ]; + + $progressCallback = function (array $progress): void { + $this->setProgress('downloading', 'Downloading update...', $progress['percent'], [ + 'transferred' => $progress['transferred'], + 'filesize' => $progress['filesize'], + ]); + }; + + $output = Response::get($package['download'], $options, $progressCallback); + + $this->setProgress('downloading', 'Download complete.', 100); + + $target = $this->tmp . '/' . $package['name']; + file_put_contents($target, $output); + + return $target; + } + + /** + * @param string $zip + * @return void + */ + protected function performInstall(string $zip): void + { + $this->setProgress('installing', 'Unpacking update...', null); + $folder = Installer::unZip($zip, $this->tmp . '/zip'); + if ($folder === false) { + throw new RuntimeException(Installer::lastErrorMsg()); + } + + $script = $folder . '/system/install.php'; + if (!file_exists($script)) { + throw new RuntimeException('Downloaded archive is not a valid Grav package.'); + } + + $install = include $script; + if (!is_callable($install)) { + throw new RuntimeException('Unable to bootstrap installer from downloaded package.'); + } + + try { + if (is_object($install) && method_exists($install, 'generatePreflightReport')) { + $report = $install->generatePreflightReport(); + $this->setProgress('preflight', 'Preflight checks completed.', null, [ + 'preflight' => $report, + ]); + $this->enforcePreflightReport($report, $this->preflightDecisions); + } + if (is_object($install) && method_exists($install, 'setProgressCallback')) { + $install->setProgressCallback(function (string $stage, string $message, ?int $percent = null) { + $this->setProgress($stage, $message, $percent); + }); + } + $this->setProgress('installing', 'Running installer...', null); + $install($zip); + $this->setProgress('installing', 'Verifying files...', null); + } catch (Throwable $e) { + throw new RuntimeException($e->getMessage(), 0, $e); + } + + $errorCode = Installer::lastErrorCode(); + if ($errorCode) { + throw new RuntimeException(Installer::lastErrorMsg()); + } + } + + protected function clearRecoveryFlag(): void + { + $flag = GRAV_ROOT . '/user/data/recovery.flag'; + if (is_file($flag)) { + @unlink($flag); + } + } + + /** + * Attempt to run finalize scripts if Grav is already up to date but schema mismatched. + * + * @param string $localVersion + * @return array|null + */ + protected function runFinalizeIfNeeded(string $localVersion): ?array + { + $config = $this->grav['config']; + $schema = $config->get('versions.core.grav.schema'); + + if ($schema !== GRAV_SCHEMA && version_compare((string)$schema, GRAV_SCHEMA, '<')) { + $this->setProgress('finalizing', 'Running post-install scripts...', null); + Install::instance()->finalize(); + $this->setProgress('complete', 'Post-install scripts executed.', 100, [ + 'target_version' => $localVersion, + ]); + + return [ + 'status' => 'finalized', + 'version' => $localVersion, + 'message' => 'Post-install scripts completed.', + 'context' => $this->buildStatusContext(), + ]; + } + + return null; + } + + /** + * Fetch most recent safe upgrade manifest if available. + * + * @return array|null + */ + protected function resolveLatestManifest(): ?array + { + $store = $this->grav['locator']->findResource('user://data/upgrades', false); + if (!$store || !is_dir($store)) { + return null; + } + + $files = glob($store . '/*.json') ?: []; + if (!$files) { + return null; + } + rsort($files); + + $latest = $files[0]; + $decoded = json_decode(file_get_contents($latest), true); + + return is_array($decoded) ? $decoded : null; + } + + /** + * Persist progress payload. + * + * @param string $stage + * @param string $message + * @param int|null $percent + * @param array $extra + * @return void + */ + protected function setProgress(string $stage, string $message, ?int $percent = null, array $extra = []): void + { + $payload = [ + 'stage' => $stage, + 'message' => $message, + 'percent' => $percent, + 'timestamp' => time(), + ] + $extra; + + if ($this->jobId) { + $payload['job_id'] = $this->jobId; + } + + try { + Folder::create(dirname($this->progressPath)); + file_put_contents($this->progressPath, json_encode($payload, JSON_PRETTY_PRINT)); + if ($this->jobId) { + $this->log(sprintf('Job %s stage -> %s (%s)', $this->jobId, $stage, $message), $stage === 'error' ? 'error' : 'debug'); + } + } catch (Throwable $e) { + // ignore write failures + } + + if ($this->jobManifestPath) { + $status = 'running'; + if ($stage === 'error') { + $status = 'error'; + } elseif ($stage === 'complete') { + $status = 'success'; + } + + $manifest = [ + 'status' => $status, + 'progress' => $payload, + ]; + + if ($status === 'success') { + $manifest['completed_at'] = time(); + } + + if ($status === 'error' && isset($extra['message'])) { + $manifest['error'] = $extra['message']; + } + + $this->writeManifest($manifest); + } + } + + /** + * Helper for building an error result payload. + * + * @param string $message + * @param array $extra + * @return array + */ + protected function errorResult(string $message, array $extra = []): array + { + $extraWithMessage = ['message' => $message] + $extra; + $this->setProgress('error', $message, null, $extraWithMessage); + + if ($this->jobManifestPath) { + $this->updateJob([ + 'result' => [ + 'status' => 'error', + 'message' => $message, + 'details' => $extra, + ], + 'status' => 'error', + 'completed_at' => time(), + ]); + $this->log(sprintf('Safe upgrade job %s failed: %s', $this->jobId ?? 'n/a', $message), 'error'); + } + + return [ + 'status' => 'error', + 'message' => $message, + 'context' => $this->buildStatusContext(), + ] + $extra; + } + + protected function buildStatusContext(): ?string + { + $context = []; + + if ($this->jobManifestPath) { + $context['manifest'] = $this->convertPathForContext($this->jobManifestPath); + } + + if ($this->progressPath) { + $context['progress'] = $this->convertPathForContext($this->progressPath); + } + + if (!$context) { + return null; + } + + $encoded = json_encode($context); + + return $encoded === false ? null : base64_encode($encoded); + } + + private function convertPathForContext(string $path): string + { + $normalized = str_replace('\\', '/', $path); + $root = str_replace('\\', '/', GRAV_ROOT); + + if (strpos($normalized, $root) === 0) { + $relative = substr($normalized, strlen($root)); + + return ltrim($relative, '/'); + } + + return $normalized; + } + + protected function ensureExecutablePermissions(): void + { + $executables = [ + 'bin/grav', + 'bin/plugin', + 'bin/gpm', + 'bin/restore', + 'bin/composer.phar' + ]; + + foreach ($executables as $relative) { + $path = GRAV_ROOT . '/' . $relative; + if (!is_file($path) || is_link($path)) { + continue; + } + + $perms = @fileperms($path); + $mode = $perms !== false ? ($perms & 0777) : null; + if ($mode !== 0755) { + @chmod($path, 0755); + $this->log(sprintf('Adjusted permissions on %s to 0755', $relative), 'debug'); + } + } + } + + protected function resolveAsset(array $assets, string $prefix): ?array + { + if (isset($assets[$prefix])) { + return $assets[$prefix]; + } + + foreach ($assets as $key => $asset) { + $name = is_array($asset) ? ($asset['name'] ?? '') : ''; + $haystack = $key . ' ' . $name; + if (stripos($haystack, $prefix) === 0 || stripos($haystack, '/' . $prefix) !== false) { + return $asset; + } + } + + return null; + } +} diff --git a/languages/en.yaml b/languages/en.yaml index 9738edc24..03a0941ab 100644 --- a/languages/en.yaml +++ b/languages/en.yaml @@ -178,6 +178,11 @@ PLUGIN_ADMIN: PAGES_FILTERED: "Pages filtered" NO_PAGE_FOUND: "No Page found" INVALID_PARAMETERS: "Invalid Parameters" + + # Session expiration modal (Admin keep-alive/offline handling) + SESSION_EXPIRED: "Session Expired" + SESSION_EXPIRED_DESC: "Your admin login session has expired. Click OK to log in again." + OK: "OK" NO_FILES_SENT: "No files sent" EXCEEDED_FILESIZE_LIMIT: "Exceeded PHP configuration upload_max_filesize" EXCEEDED_POSTMAX_LIMIT: "Exceeded PHP configuration post_max_size" @@ -491,6 +496,58 @@ PLUGIN_ADMIN: UPDATE_GRAV_NOW: "Update Grav Now" GRAV_SYMBOLICALLY_LINKED: "Grav is symbolically linked. Upgrade won't be available" UPDATING_PLEASE_WAIT: "Updating... please wait, downloading" + SAFE_UPGRADE_TITLE: "Safe Upgrade" + SAFE_UPGRADE_DESC: "Run Grav core upgrades with staging, validation, and rollback support." + SAFE_UPGRADE_CHECKING: "Running preflight checks..." + SAFE_UPGRADE_GENERIC_ERROR: "Safe upgrade could not complete. See Grav logs for details." + SAFE_UPGRADE_RECHECK: "Re-run Checks" + SAFE_UPGRADE_RECHECKING: "Re-running Checks..." + SAFE_UPGRADE_SUMMARY_CURRENT: "Current Grav version: v%s" + SAFE_UPGRADE_SUMMARY_REMOTE: "Available Grav version: v%s" + SAFE_UPGRADE_RELEASED_ON: "Released on %s" + SAFE_UPGRADE_PACKAGE_SIZE: "Package size: %s" + SAFE_UPGRADE_UNKNOWN_SIZE: "unknown" + SAFE_UPGRADE_WARNINGS: "Warnings" + SAFE_UPGRADE_WARNINGS_HINT: "These items may require attention before continuing." + SAFE_UPGRADE_WARNINGS_PSR_ITEM: "Potential psr/log conflict:" + SAFE_UPGRADE_WARNINGS_MONOLOG_ITEM: "Potential Monolog conflict:" + SAFE_UPGRADE_WARNINGS_MONOLOG_UNKNOWN: "Review the plugin for potential API changes." + SAFE_UPGRADE_PENDING_UPDATES: "Pending plugin or theme updates" + SAFE_UPGRADE_PENDING_INTRO: "Because this is a major Grav upgrade, update these extensions first to ensure maximum compatibility." + SAFE_UPGRADE_PENDING_MINOR_DESC: "These updates are optional for this release; apply them at your convenience." + SAFE_UPGRADE_PENDING_HINT: "Because this is a major upgrade, update all plugins and themes before continuing to ensure maximum compatibility." + SAFE_UPGRADE_UNKNOWN_VERSION: "unknown" + SAFE_UPGRADE_REQUIREMENTS_FAIL: "PHP %s or newer is required before continuing." + SAFE_UPGRADE_DISABLED: "Safe upgrade is disabled. Enable it in Configuration ▶ System ▶ Updates." + SAFE_UPGRADE_STAGING_ERROR: "Safe upgrade staging directory is not writable." + SAFE_UPGRADE_NOT_AVAILABLE: "No Grav update is available." + SAFE_UPGRADE_CONFLICTS_PSR: "Potential psr/log compatibility issues" + SAFE_UPGRADE_CONFLICTS_REQUIRES: "Requires psr/log %s" + SAFE_UPGRADE_CONFLICTS_MONOLOG: "Potential Monolog API compatibility issues" + SAFE_UPGRADE_CONFLICTS_HINT: "Choose how to handle conflicts before starting the upgrade." + SAFE_UPGRADE_DECISION_PROMPT: "When conflicts are detected:" + SAFE_UPGRADE_DECISION_DISABLE: "Disable conflicting plugins" + SAFE_UPGRADE_DECISION_DISABLE_DESC: "Temporarily disable conflicting plugins during the upgrade." + SAFE_UPGRADE_DECISION_CONTINUE: "Continue with plugins enabled" + SAFE_UPGRADE_DECISION_CONTINUE_DESC: "Proceed with plugins enabled. This may require manual fixes." + SAFE_UPGRADE_BLOCKERS_TITLE: "Action required before continuing" + SAFE_UPGRADE_BLOCKERS_DESC: "Resolve the following items to enable the upgrade." + SAFE_UPGRADE_START: "Start Safe Upgrade" + SAFE_UPGRADE_FINISH: "Finish" + SAFE_UPGRADE_STAGE_QUEUED: "Waiting for worker" + SAFE_UPGRADE_STAGE_INITIALIZING: "Preparing upgrade" + SAFE_UPGRADE_STAGE_DOWNLOADING: "Downloading update" + SAFE_UPGRADE_STAGE_SNAPSHOT: "Creating backup snapshot" + SAFE_UPGRADE_STAGE_INSTALLING: "Installing update" + SAFE_UPGRADE_STAGE_ROLLBACK: "Restoring snapshot" + SAFE_UPGRADE_STAGE_FINALIZING: "Finalizing changes" + SAFE_UPGRADE_STAGE_COMPLETE: "Upgrade complete" + SAFE_UPGRADE_STAGE_ERROR: "Upgrade encountered an error" + SAFE_UPGRADE_RESULT_SUCCESS: "Grav Upgrade to v%s Successful!" + SAFE_UPGRADE_RESULT_MANIFEST: "Snapshot reference: %s" + SAFE_UPGRADE_RESULT_HINT: "Restore snapshots from Tools → Restore Grav." + SAFE_UPGRADE_RESULT_NOOP: "Grav is already up to date." + SAFE_UPGRADE_RESULT_FAILURE: "Safe upgrade failed" OF_THIS: "of this" OF_YOUR: "of your" HAVE_AN_UPDATE_AVAILABLE: "have an update available" @@ -787,6 +844,30 @@ PLUGIN_ADMIN: TOOLS_DIRECT_INSTALL_URL_TITLE: "Install Package via Remote URL Reference" TOOLS_DIRECT_INSTALL_URL_DESC: "Alternatively, you can also reference a full URL to the package ZIP file and install it via this remote URL." TOOLS_DIRECT_INSTALL_UPLOAD_BUTTON: "Upload and install" + RESTORE_GRAV: "Restore Grav" + RESTORE_GRAV_DESC: "Select a snapshot created by Safe Upgrade to restore your site or remove snapshots you no longer need." + RESTORE_GRAV_TABLE_SNAPSHOT: "Snapshot" + RESTORE_GRAV_TABLE_VERSION: "Version" + RESTORE_GRAV_TABLE_CREATED: "Created" + RESTORE_GRAV_TABLE_LOCATION: "Snapshot path" + RESTORE_GRAV_TABLE_ACTIONS: "Actions" + RESTORE_GRAV_RESTORE_BUTTON: "Restore" + RESTORE_GRAV_DELETE_SELECTED: "Delete Selected" + RESTORE_GRAV_NONE: "No safe upgrade snapshots are currently available." + RESTORE_GRAV_INVALID: "Select at least one snapshot before continuing." + RESTORE_GRAV_SUCCESS: "Snapshot %s restored (Grav %s)." + RESTORE_GRAV_SUCCESS_MESSAGE: "Snapshot %1$s restored (Grav %2$s)." + RESTORE_GRAV_SUCCESS_SIMPLE: "Snapshot %s restored." + RESTORE_GRAV_RUNNING: "Restoring snapshot %s..." + RESTORE_GRAV_FAILED: "Unable to restore the selected snapshot." + RESTORE_GRAV_CREATE_SNAPSHOT: "Create Snapshot" + RESTORE_GRAV_SNAPSHOT_PROMPT: "Enter an optional snapshot label" + RESTORE_GRAV_SNAPSHOT_RUNNING: "Creating snapshot %s..." + RESTORE_GRAV_SNAPSHOT_SUCCESS: "Snapshot %s created." + RESTORE_GRAV_SNAPSHOT_FAILED: "Snapshot creation failed." + RESTORE_GRAV_SNAPSHOT_FALLBACK: "Snapshot creation may have completed. Reloading..." + RESTORE_GRAV_DELETE_SUCCESS: "%d snapshot(s) deleted." + RESTORE_GRAV_DELETE_FAILED: "Failed to delete one or more snapshots." ROUTE_OVERRIDES: "Route Overrides" ROUTE_DEFAULT: "Default Route" ROUTE_CANONICAL: "Canonical Route" diff --git a/safe-upgrade-status.php b/safe-upgrade-status.php new file mode 100644 index 000000000..6158cdf1d --- /dev/null +++ b/safe-upgrade-status.php @@ -0,0 +1,179 @@ + 'error', + 'message' => 'Invalid job identifier.', + ]); + exit; +} + +$readJson = static function (string $path): ?array { + if (!is_file($path)) { + return null; + } + + $decoded = json_decode((string)file_get_contents($path), true); + + return is_array($decoded) ? $decoded : null; +}; + +$progress = null; +$manifest = null; +$manifestPath = null; +$progressPath = null; + +$normalizeDir = static function (string $path): string { + $normalized = str_replace('\\', '/', $path); + + return rtrim($normalized, '/'); +}; + +$jobsDirNormalized = $normalizeDir(realpath($jobsDir) ?: $jobsDir); +$userDataDirNormalized = $normalizeDir(realpath(dirname($jobsDir)) ?: dirname($jobsDir)); +$toRelative = static function (string $path): string { + $normalized = str_replace('\\', '/', $path); + $root = str_replace('\\', '/', GRAV_ROOT); + + if (strpos($normalized, $root) === 0) { + $relative = substr($normalized, strlen($root)); + + return ltrim($relative, '/'); + } + + return $normalized; +}; + +$contextParam = $_GET['context'] ?? ''; +if ($contextParam !== '') { + $decodedRaw = base64_decode(strtr($contextParam, ' ', '+'), true); + if ($decodedRaw !== false) { + $decoded = json_decode($decodedRaw, true); + if (is_array($decoded)) { + $validatePath = static function (string $candidate) use ($normalizeDir, $jobsDirNormalized, $userDataDirNormalized) { + if ($candidate === '') { + return null; + } + + $candidate = str_replace('\\', '/', $candidate); + + if ($candidate[0] !== '/' && !preg_match('/^[A-Za-z]:[\\\\\/]/', $candidate)) { + $candidate = GRAV_ROOT . '/' . ltrim($candidate, '/'); + $candidate = str_replace('\\', '/', $candidate); + } + + $real = realpath($candidate); + if ($real === false) { + return null; + } + + $real = $normalizeDir($real); + if (strpos($real, $jobsDirNormalized) !== 0 && strpos($real, $userDataDirNormalized) !== 0) { + return null; + } + + return $real; + }; + + if (!empty($decoded['manifest'])) { + $candidate = $validatePath((string)$decoded['manifest']); + if ($candidate) { + $manifestPath = $candidate; + if (is_file($candidate)) { + $manifest = $readJson($candidate); + } + } + } + + if (!empty($decoded['progress'])) { + $candidate = $validatePath((string)$decoded['progress']); + if ($candidate) { + $progressPath = $candidate; + if (is_file($candidate)) { + $progress = $readJson($candidate); + } + } + } + } + } +} + +if ($jobId !== '') { + $jobPath = $jobsDir . '/' . $jobId; + $progressPath = $progressPath ?: ($jobPath . '/progress.json'); + $manifestPath = $manifestPath ?: ($jobPath . '/manifest.json'); + if (is_file($progressPath)) { + $progress = $readJson($progressPath); + } + if (is_file($manifestPath)) { + $manifest = $readJson($manifestPath); + } + + if (!$progress && !$manifest && !is_dir($jobPath)) { + $progress = $readJson($fallbackProgress) ?: [ + 'stage' => 'idle', + 'message' => '', + 'percent' => null, + 'timestamp' => time(), + ]; + } +} + +if ($progress === null) { + if ($progressPath && is_file($progressPath)) { + $progress = $readJson($progressPath); + } + + if ($progress === null) { + $progress = $readJson($fallbackProgress) ?: [ + 'stage' => 'idle', + 'message' => '', + 'percent' => null, + 'timestamp' => time(), + ]; + $progressPath = $fallbackProgress; + } +} + +if ($jobId !== '' && is_array($progress) && !isset($progress['job_id'])) { + $progress['job_id'] = $jobId; +} + +$contextPayload = []; +if ($manifestPath) { + $contextPayload['manifest'] = $toRelative($manifestPath); +} +if ($progressPath) { + $contextPayload['progress'] = $toRelative($progressPath); +} + +$contextToken = $contextPayload ? base64_encode(json_encode($contextPayload)) : null; + +echo json_encode([ + 'status' => 'success', + 'data' => [ + 'job' => $manifest ?: null, + 'progress' => $progress, + 'context' => $contextToken, + ], +]); + +exit; diff --git a/themes/grav/app/forms/fields/collections.js b/themes/grav/app/forms/fields/collections.js index c9c1ee90e..81561045d 100644 --- a/themes/grav/app/forms/fields/collections.js +++ b/themes/grav/app/forms/fields/collections.js @@ -231,11 +231,15 @@ export default class CollectionsField { // special case to preserve array field index keys if (prop === 'name' && element.data('gravArrayType')) { const match_index = element.attr(prop).match(/\[[0-9]{1,}\]$/); - const pattern = element[0].closest('[data-grav-array-name]').dataset.gravArrayName; - if (match_index && pattern) { + const array_container = element[0].closest('[data-grav-array-name]'); + + if (match_index) { array_index = match_index[0]; - element.attr(prop, `${pattern}${match_index[0]}`); - return; + element.attr(prop, element.attr(prop).slice(0, array_index.length * -1)); + } + + if (array_container && array_container.dataset && array_container.dataset.gravArrayName) { + element.attr(prop, array_container.dataset.gravArrayName); } } @@ -255,14 +259,8 @@ export default class CollectionsField { let matchedKey = currentKey; let replaced = element.attr(prop).replace(regexps[0], (/* str, p1, offset */) => { - let extras = ''; - if (array_index) { - extras = array_index; - console.log(indexes, extras); - } - matchedKey = indexes.shift() || matchedKey; - return `[${matchedKey}]${extras}`; + return `[${matchedKey}]`; }); replaced = replaced.replace(regexps[1], (/* str, p1, offset */) => { @@ -270,7 +268,7 @@ export default class CollectionsField { return `.${matchedKey}.`; }); - element.attr(prop, replaced); + element.attr(prop, array_index ? `${replaced}${array_index}` : replaced); }); }); }); diff --git a/themes/grav/app/main.js b/themes/grav/app/main.js index 6edfca996..c62ff91fe 100644 --- a/themes/grav/app/main.js +++ b/themes/grav/app/main.js @@ -7,6 +7,7 @@ import 'simplebar/dist/simplebar.min.js'; import { UriToMarkdown } from './forms/fields/files.js'; import GPM, { Instance as gpm } from './utils/gpm'; import KeepAlive from './utils/keepalive'; +import { config as GravConfig } from 'grav-config'; import Updates, { Instance as updates, Notifications, Feed } from './updates'; import Dashboard from './dashboard'; import Pages from './pages'; @@ -34,9 +35,20 @@ import './utils/changelog'; // Main Sidebar import Sidebar, { Instance as sidebar } from './utils/sidebar'; +import { bindGlobalAjaxTrap, installNavigationGuard } from './utils/session-expired'; -// starts the keep alive, auto runs every X seconds -KeepAlive.start(); +// starts the keep alive (if enabled), but never on auth views like login/forgot/reset/register +const AUTH_VIEWS = ['login', 'forgot', 'reset', 'register']; +const isAuthView = AUTH_VIEWS.includes(String(GravConfig.route || '')); +if (!isAuthView && String(GravConfig.keep_alive_enabled) !== '0') { + KeepAlive.start(); +} + +// catch legacy jQuery XHR 401/403 globally +bindGlobalAjaxTrap(); + +// intercept admin nav clicks to show modal before redirect on timeout +installNavigationGuard(); // global event to catch sidebar_state changes $(global).on('sidebar_state._grav', () => { diff --git a/themes/grav/app/tools/index.js b/themes/grav/app/tools/index.js index 37d4b65eb..931c6308f 100644 --- a/themes/grav/app/tools/index.js +++ b/themes/grav/app/tools/index.js @@ -1 +1,2 @@ import './logs'; +import './restore'; diff --git a/themes/grav/app/tools/restore.js b/themes/grav/app/tools/restore.js new file mode 100644 index 000000000..8ed7a0481 --- /dev/null +++ b/themes/grav/app/tools/restore.js @@ -0,0 +1,564 @@ +import $ from 'jquery'; +import { config, translations } from 'grav-config'; +import request from '../utils/request'; +import toastr from '../utils/toastr'; + +const paramSep = config.param_sep; +const task = `task${paramSep}`; +const nonce = `admin-nonce${paramSep}${config.admin_nonce}`; +const base = `${config.base_url_relative}/update.json`; + +const urls = { + restore: `${base}/${task}safeUpgradeRestore/${nonce}`, + snapshot: `${base}/${task}safeUpgradeSnapshot/${nonce}`, + status: `${base}/${task}safeUpgradeStatus/${nonce}`, +}; + +const NICETIME_PERIODS_SHORT = [ + 'NICETIME.SEC', + 'NICETIME.MIN', + 'NICETIME.HR', + 'NICETIME.DAY', + 'NICETIME.WK', + 'NICETIME.MO', + 'NICETIME.YR', + 'NICETIME.DEC' +]; + +const NICETIME_PERIODS_LONG = [ + 'NICETIME.SECOND', + 'NICETIME.MINUTE', + 'NICETIME.HOUR', + 'NICETIME.DAY', + 'NICETIME.WEEK', + 'NICETIME.MONTH', + 'NICETIME.YEAR', + 'NICETIME.DECADE' +]; + +const NICETIME_LENGTHS = [60, 60, 24, 7, 4.35, 12, 10]; +const FAST_UPDATE_THRESHOLD_SECONDS = 60; +const FAST_REFRESH_INTERVAL_MS = 1000; +const SLOW_REFRESH_INTERVAL_MS = 60000; +const NICETIME_TRANSLATION_ROOTS = ['GRAV_CORE', 'GRAV']; + +const NICETIME_BASE_FALLBACKS = { + SECOND: 'second', + MINUTE: 'minute', + HOUR: 'hour', + DAY: 'day', + WEEK: 'week', + MONTH: 'month', + YEAR: 'year', + DECADE: 'decade', + SEC: 'sec', + MIN: 'min', + HR: 'hr', + WK: 'wk', + MO: 'mo', + YR: 'yr', + DEC: 'dec' +}; + +const NICETIME_PLURAL_FALLBACKS = { + SECOND: 'seconds', + MINUTE: 'minutes', + HOUR: 'hours', + DAY: 'days', + WEEK: 'weeks', + MONTH: 'months', + YEAR: 'years', + DECADE: 'decades', + SEC: 'secs', + MIN: 'mins', + HR: 'hrs', + WK: 'wks', + MO: 'mos', + YR: 'yrs', + DEC: 'decs' +}; + +const getTranslationKey = (key) => { + for (const root of NICETIME_TRANSLATION_ROOTS) { + const catalog = translations[root]; + if (catalog && Object.prototype.hasOwnProperty.call(catalog, key)) { + const value = catalog[key]; + if (typeof value === 'string' && value.trim() !== '') { + return value; + } + } + } + + return undefined; +}; + +const nicetimeHasKey = (key) => typeof getTranslationKey(key) === 'string'; + +const nicetimeTranslate = (key, fallback) => { + const value = getTranslationKey(key); + if (typeof value === 'string' && value.length) { + return value; + } + + return fallback; +}; + +const getFallbackForPeriodKey = (key) => { + const normalized = key.replace(/^GRAV\./, ''); + const period = normalized.replace(/^NICETIME\./, ''); + const plural = /_PLURAL/.test(period); + const baseKey = period.replace(/_PLURAL(_MORE_THAN_TWO)?$/, ''); + const base = NICETIME_BASE_FALLBACKS[baseKey] || baseKey.toLowerCase(); + + if (!plural) { + return base; + } + + const pluralKey = NICETIME_PLURAL_FALLBACKS[baseKey]; + if (pluralKey) { + return pluralKey; + } + + if (base.endsWith('y')) { + return `${base.slice(0, -1)}ies`; + } + + if (base.endsWith('s')) { + return `${base}es`; + } + + return `${base}s`; +}; + +const parseTimestampValue = (input) => { + if (input instanceof Date) { + return Math.floor(input.getTime() / 1000); + } + + if (typeof input === 'number' && Number.isFinite(input)) { + return input > 1e12 ? Math.floor(input / 1000) : Math.floor(input); + } + + if (typeof input === 'string') { + const trimmed = input.trim(); + if (!trimmed) { + return null; + } + + const numeric = Number(trimmed); + if (!Number.isNaN(numeric) && trimmed === String(numeric)) { + return numeric > 1e12 ? Math.floor(numeric / 1000) : Math.floor(numeric); + } + + const parsed = Date.parse(trimmed); + if (!Number.isNaN(parsed)) { + return Math.floor(parsed / 1000); + } + } + + return null; +}; + +const computeNicetime = (input, { longStrings = false, showTense = false } = {}) => { + if (input === null || input === undefined || input === '') { + return nicetimeTranslate('NICETIME.NO_DATE_PROVIDED', 'No date provided'); + } + + const unixDate = parseTimestampValue(input); + if (unixDate === null) { + return nicetimeTranslate('NICETIME.BAD_DATE', 'Bad date'); + } + + const now = Math.floor(Date.now() / 1000); + const periods = (longStrings ? NICETIME_PERIODS_LONG : NICETIME_PERIODS_SHORT).slice(); + + let difference; + let tense; + + if (now > unixDate) { + difference = now - unixDate; + tense = nicetimeTranslate('NICETIME.AGO', 'ago'); + } else if (now === unixDate) { + difference = 0; + tense = nicetimeTranslate('NICETIME.JUST_NOW', 'just now'); + } else { + difference = unixDate - now; + tense = nicetimeTranslate('NICETIME.FROM_NOW', 'from now'); + } + + if (now === unixDate) { + return tense; + } + + let index = 0; + while (index < NICETIME_LENGTHS.length - 1 && difference >= NICETIME_LENGTHS[index]) { + difference /= NICETIME_LENGTHS[index]; + index += 1; + } + + difference = Math.round(difference); + let periodKey = periods[index]; + + if (difference !== 1) { + periodKey += '_PLURAL'; + const moreThanTwoKey = `${periodKey}_MORE_THAN_TWO`; + if (difference > 2 && nicetimeHasKey(moreThanTwoKey)) { + periodKey = moreThanTwoKey; + } + } + + const labelFallback = periodKey.split('.').pop().toLowerCase(); + const fallbackLabel = getFallbackForPeriodKey(periodKey) || labelFallback; + const periodLabel = nicetimeTranslate(periodKey, fallbackLabel); + const timeString = `${difference} ${periodLabel}`; + + return showTense ? `${timeString} ${tense}` : timeString; +}; + +const parseBoolAttribute = (element, attributeName, defaultValue = false) => { + const rawValue = element.getAttribute(attributeName); + if (rawValue === null) { + return defaultValue; + } + + const normalized = rawValue.trim().toLowerCase(); + if (normalized === '') { + return true; + } + + return ['1', 'true', 'yes', 'on'].includes(normalized); +}; + +const initialiseNicetimeUpdater = () => { + const selector = '[data-nicetime-timestamp]'; + if (!document.querySelector(selector)) { + return null; + } + + const update = () => { + const nowSeconds = Math.floor(Date.now() / 1000); + let youngestAge = Infinity; + + document.querySelectorAll(selector).forEach((element) => { + const timestamp = element.getAttribute('data-nicetime-timestamp'); + const longStrings = parseBoolAttribute(element, 'data-nicetime-long', false); + const showTense = parseBoolAttribute(element, 'data-nicetime-tense', false); + const unixTimestamp = parseTimestampValue(timestamp); + if (unixTimestamp !== null) { + const age = Math.max(0, nowSeconds - unixTimestamp); + if (age < youngestAge) { + youngestAge = age; + } + } + + const updated = computeNicetime(timestamp, { longStrings, showTense }); + + if (updated && element.textContent !== updated) { + element.textContent = updated; + } + }); + + return youngestAge; + }; + + let timerId = null; + + const scheduleNext = (lastAge) => { + const useFastInterval = Number.isFinite(lastAge) && lastAge < FAST_UPDATE_THRESHOLD_SECONDS; + const delay = useFastInterval ? FAST_REFRESH_INTERVAL_MS : SLOW_REFRESH_INTERVAL_MS; + + timerId = window.setTimeout(() => { + const nextAge = update(); + scheduleNext(nextAge); + }, delay); + }; + + const destroy = () => { + if (timerId !== null) { + window.clearTimeout(timerId); + timerId = null; + } + }; + + const initialAge = update(); + scheduleNext(initialAge); + + window.addEventListener('beforeunload', destroy, { once: true }); + + return { update, destroy }; +}; + +class RestoreManager { + constructor() { + this.job = null; + this.pollTimer = null; + this.pollFailures = 0; + + $(document).on('click', '[data-restore-snapshot]', (event) => { + event.preventDefault(); + const button = $(event.currentTarget); + if (this.job) { + return; + } + this.startRestore(button); + }); + + $(document).on('click', '[data-create-snapshot]', (event) => { + event.preventDefault(); + const button = $(event.currentTarget); + if (this.job) { + return; + } + this.startSnapshot(button); + }); + } + + startSnapshot(button) { + let label = null; + if (typeof window !== 'undefined' && window.prompt) { + const promptMessage = translations.PLUGIN_ADMIN?.RESTORE_GRAV_SNAPSHOT_PROMPT || 'Enter an optional snapshot label'; + const input = window.prompt(promptMessage, ''); + if (input === null) { + return; + } + label = input.trim(); + if (label === '') { + label = null; + } + } + + button.prop('disabled', true).addClass('is-loading'); + + const body = {}; + if (label) { + body.label = label; + } + + request(urls.snapshot, { method: 'post', body }, (response) => { + button.prop('disabled', false).removeClass('is-loading'); + + if (!response) { + toastr.error(translations.PLUGIN_ADMIN?.RESTORE_GRAV_SNAPSHOT_FAILED || 'Snapshot creation failed.'); + return; + } + + if (response.status === 'error') { + toastr.error(response.message || translations.PLUGIN_ADMIN?.RESTORE_GRAV_SNAPSHOT_FAILED || 'Snapshot creation failed.'); + return; + } + + const data = response.data || {}; + const jobId = data.job_id || (data.job && data.job.id); + if (!jobId) { + const message = response.message || translations.PLUGIN_ADMIN?.RESTORE_GRAV_SNAPSHOT_FAILED || 'Snapshot creation failed.'; + toastr.error(message); + return; + } + + this.job = { + id: jobId, + operation: 'snapshot', + snapshot: null, + label + }; + this.pollFailures = 0; + + const descriptor = label || jobId; + const runningMessage = translations.PLUGIN_ADMIN?.RESTORE_GRAV_SNAPSHOT_RUNNING + ? translations.PLUGIN_ADMIN.RESTORE_GRAV_SNAPSHOT_RUNNING.replace('%s', descriptor) + : 'Creating snapshot...'; + toastr.info(runningMessage); + this.schedulePoll(); + }); + } + + startRestore(button) { + const snapshot = button.data('restore-snapshot'); + if (!snapshot) { + return; + } + + button.prop('disabled', true).addClass('is-loading'); + + const body = { snapshot }; + request(urls.restore, { method: 'post', body }, (response) => { + button.prop('disabled', false).removeClass('is-loading'); + + if (!response) { + toastr.error(translations.PLUGIN_ADMIN?.RESTORE_GRAV_FAILED || 'Snapshot restore failed.'); + return; + } + + if (response.status === 'error') { + toastr.error(response.message || translations.PLUGIN_ADMIN?.RESTORE_GRAV_FAILED || 'Snapshot restore failed.'); + return; + } + + const data = response.data || {}; + const jobId = data.job_id || (data.job && data.job.id); + if (!jobId) { + const message = response.message || translations.PLUGIN_ADMIN?.RESTORE_GRAV_FAILED || 'Snapshot restore failed.'; + toastr.error(message); + return; + } + + this.job = { + id: jobId, + snapshot, + operation: 'restore', + }; + this.pollFailures = 0; + + const runningMessage = translations.PLUGIN_ADMIN?.RESTORE_GRAV_RUNNING + ? translations.PLUGIN_ADMIN.RESTORE_GRAV_RUNNING.replace('%s', snapshot) + : `Restoring snapshot ${snapshot}...`; + toastr.info(runningMessage); + this.schedulePoll(); + }); + } + + schedulePoll(delay = 1200) { + this.clearPoll(); + this.pollTimer = setTimeout(() => this.pollStatus(), delay); + } + + clearPoll() { + if (this.pollTimer) { + clearTimeout(this.pollTimer); + this.pollTimer = null; + } + } + + pollStatus() { + if (!this.job) { + return; + } + + const jobId = this.job.id; + let handled = false; + + request(`${urls.status}?job=${encodeURIComponent(jobId)}`, { silentErrors: true }, (response) => { + handled = true; + this.pollFailures = 0; + + if (!response || response.status !== 'success') { + this.schedulePoll(); + return; + } + + const data = response.data || {}; + const job = data.job || {}; + const progress = data.progress || {}; + + const stage = progress.stage || null; + const status = job.status || progress.status || null; + const operation = progress.operation || this.job.operation || null; + + if (!this.job.snapshot && progress.snapshot) { + this.job.snapshot = progress.snapshot; + } else if (!this.job.snapshot && job.result && job.result.snapshot) { + this.job.snapshot = job.result.snapshot; + } + + if (!this.job.label && progress.label) { + this.job.label = progress.label; + } else if (!this.job.label && job.result && job.result.label) { + this.job.label = job.result.label; + } + + if (stage === 'error' || status === 'error') { + const message = job.error || progress.message || (operation === 'snapshot' + ? translations.PLUGIN_ADMIN?.RESTORE_GRAV_SNAPSHOT_FAILED || 'Snapshot creation failed.' + : translations.PLUGIN_ADMIN?.RESTORE_GRAV_FAILED || 'Snapshot restore failed.'); + toastr.error(message); + this.job = null; + this.clearPoll(); + return; + } + + if (stage === 'complete' || status === 'success') { + if (operation === 'snapshot') { + const snapshotId = progress.snapshot || (job.result && job.result.snapshot) || this.job.snapshot || ''; + const labelValue = progress.label || (job.result && job.result.label) || this.job.label || ''; + let displayName = labelValue || snapshotId || (translations.PLUGIN_ADMIN?.RESTORE_GRAV_TABLE_SNAPSHOT || 'snapshot'); + if (labelValue && snapshotId && labelValue !== snapshotId) { + displayName = `${labelValue} (${snapshotId})`; + } + const successMessage = translations.PLUGIN_ADMIN?.RESTORE_GRAV_SNAPSHOT_SUCCESS + ? translations.PLUGIN_ADMIN.RESTORE_GRAV_SNAPSHOT_SUCCESS.replace('%s', displayName) + : (snapshotId ? `Snapshot ${displayName} created.` : 'Snapshot created.'); + toastr.success(successMessage); + this.job = null; + this.clearPoll(); + setTimeout(() => window.location.reload(), 1500); + return; + } + + const snapshotId = progress.snapshot || this.job.snapshot || ''; + const labelValue = progress.label || (job.result && job.result.label) || this.job.label || ''; + let snapshotDisplay = snapshotId || labelValue; + if (labelValue && snapshotId && labelValue !== snapshotId) { + snapshotDisplay = `${labelValue} (${snapshotId})`; + } else if (!snapshotDisplay) { + snapshotDisplay = translations.PLUGIN_ADMIN?.RESTORE_GRAV_TABLE_SNAPSHOT || 'snapshot'; + } + const version = (job.result && job.result.version) || progress.version || ''; + let successMessage; + if (translations.PLUGIN_ADMIN?.RESTORE_GRAV_SUCCESS_MESSAGE && version) { + successMessage = translations.PLUGIN_ADMIN.RESTORE_GRAV_SUCCESS_MESSAGE.replace('%1$s', snapshotDisplay).replace('%2$s', version); + } else if (translations.PLUGIN_ADMIN?.RESTORE_GRAV_SUCCESS_SIMPLE) { + successMessage = translations.PLUGIN_ADMIN.RESTORE_GRAV_SUCCESS_SIMPLE.replace('%s', snapshotDisplay); + } else { + successMessage = version ? `Snapshot ${snapshotDisplay} restored (Grav ${version}).` : `Snapshot ${snapshotDisplay} restored.`; + } + toastr.success(successMessage); + this.job = null; + this.clearPoll(); + setTimeout(() => window.location.reload(), 1500); + return; + } + + this.schedulePoll(); + }).then(() => { + if (!handled) { + this.handleSilentFailure(); + } + }); + } + + handleSilentFailure() { + if (!this.job) { + return; + } + + this.pollFailures += 1; + const operation = this.job.operation || 'restore'; + const snapshot = this.job.snapshot || ''; + + if (this.pollFailures >= 3) { + let message; + if (operation === 'snapshot') { + message = translations.PLUGIN_ADMIN?.RESTORE_GRAV_SNAPSHOT_FALLBACK || 'Snapshot creation may have completed. Reloading...'; + } else { + message = snapshot + ? `Snapshot ${snapshot} restore is completing. Reloading...` + : 'Snapshot restore is completing. Reloading...'; + } + toastr.info(message); + this.job = null; + this.clearPoll(); + setTimeout(() => window.location.reload(), 1500); + + return; + } + + const delay = Math.min(5000, 1200 * this.pollFailures); + this.schedulePoll(delay); + } +} + +// Initialize restore manager when tools view loads. +$(document).ready(() => { + initialiseNicetimeUpdater(); + new RestoreManager(); +}); diff --git a/themes/grav/app/updates/index.js b/themes/grav/app/updates/index.js index 6284e6def..e970adff5 100644 --- a/themes/grav/app/updates/index.js +++ b/themes/grav/app/updates/index.js @@ -8,16 +8,23 @@ import Feed from './feed'; import './check'; import './update'; import './channel-switcher'; +import SafeUpgrade from './safe-upgrade'; + +const SAFE_UPGRADE_ENABLED = Number(config.safe_upgrade_enabled || 0) === 1; export default class Updates { constructor(payload = {}) { this.setPayload(payload); this.task = `task${config.param_sep}`; this.updateURL = ''; + this.safeUpgrade = SAFE_UPGRADE_ENABLED ? new SafeUpgrade(this) : null; } setPayload(payload = {}) { this.payload = payload; + if (this.safeUpgrade) { + this.safeUpgrade.setPayload(payload); + } return this; } diff --git a/themes/grav/app/updates/safe-upgrade.js b/themes/grav/app/updates/safe-upgrade.js new file mode 100644 index 000000000..25bf11491 --- /dev/null +++ b/themes/grav/app/updates/safe-upgrade.js @@ -0,0 +1,1072 @@ +import $ from 'jquery'; +import { config, translations } from 'grav-config'; +import formatBytes from '../utils/formatbytes'; +import request from '../utils/request'; + +const t = (key, fallback = '') => { + if (translations && translations.PLUGIN_ADMIN && translations.PLUGIN_ADMIN[key]) { + return translations.PLUGIN_ADMIN[key]; + } + + return fallback; +}; + +const r = (key, value, fallback = '') => { + const template = t(key, fallback); + if (!template || typeof template.replace !== 'function') { + return fallback.replace('%s', value); + } + + return template.replace('%s', value); +}; + +const STAGE_TITLES = { + queued: () => t('SAFE_UPGRADE_STAGE_QUEUED', 'Waiting for worker'), + initializing: () => t('SAFE_UPGRADE_STAGE_INITIALIZING', 'Preparing upgrade'), + downloading: () => t('SAFE_UPGRADE_STAGE_DOWNLOADING', 'Downloading update'), + snapshot: () => t('SAFE_UPGRADE_STAGE_SNAPSHOT', 'Creating backup snapshot'), + installing: () => t('SAFE_UPGRADE_STAGE_INSTALLING', 'Installing update'), + rollback: () => t('SAFE_UPGRADE_STAGE_ROLLBACK', 'Restoring snapshot'), + finalizing: () => t('SAFE_UPGRADE_STAGE_FINALIZING', 'Finalizing changes'), + complete: () => t('SAFE_UPGRADE_STAGE_COMPLETE', 'Upgrade complete'), + error: () => t('SAFE_UPGRADE_STAGE_ERROR', 'Upgrade encountered an error') +}; + +export default class SafeUpgrade { + constructor(updatesInstance) { + this.updates = updatesInstance; + this.modalElement = $('[data-remodal-id="update-grav"]'); + this.modal = this.modalElement.remodal({ hashTracking: false }); + this.steps = { + preflight: this.modalElement.find('[data-safe-upgrade-step="preflight"]'), + progress: this.modalElement.find('[data-safe-upgrade-step="progress"]'), + result: this.modalElement.find('[data-safe-upgrade-step="result"]') + }; + this.buttons = { + start: this.modalElement.find('[data-safe-upgrade-action="start"]'), + cancel: this.modalElement.find('[data-safe-upgrade-action="cancel"]'), + recheck: this.modalElement.find('[data-safe-upgrade-action="recheck"]'), + finish: this.modalElement.find('[data-safe-upgrade-action="finish"]') + }; + + this.urls = this.buildUrls(); + this.decisions = {}; + this.pollTimer = null; + this.statusRequest = null; + this.isPolling = false; + this.active = false; + this.jobId = null; + this.statusFailures = 0; + this.statusContext = null; + this.statusIdleCount = 0; + this.currentStage = null; + this.stageEnteredAt = 0; + this.directStatusUrl = this.resolveDirectStatusUrl(); + this.preferDirectStatus = !!this.directStatusUrl; + this.modalLocked = false; + this.lastOverallPercent = 0; + + this.registerEvents(); + } + + buildUrls() { + const task = `task${config.param_sep}`; + const nonce = `admin-nonce${config.param_sep}${config.admin_nonce}`; + const base = `${config.base_url_relative}/update.json`; + + return { + preflight: `${base}/${task}safeUpgradePreflight/${nonce}`, + start: `${base}/${task}safeUpgradeStart/${nonce}`, + status: `${base}/${task}safeUpgradeStatus/${nonce}` + }; + } + + registerEvents() { + $(document).on('click', '#grav-update-button', (event) => { + if ($(event.currentTarget).hasClass('pointer-events-none')) { + return; + } + event.preventDefault(); + this.open(); + }); + + this.modalElement.on('closed', () => { + this.stopPolling(); + this.active = false; + }); + + this.modalElement.on('click', '[data-safe-upgrade-action="recheck"]', (event) => { + event.preventDefault(); + if (!this.active) { + return; + } + this.fetchPreflight(true); + }); + + this.modalElement.on('click', '[data-safe-upgrade-action="start"]', (event) => { + event.preventDefault(); + if ($(event.currentTarget).prop('disabled')) { + return; + } + this.startUpgrade(); + }); + + this.modalElement.on('click', '[data-safe-upgrade-action="finish"]', (event) => { + event.preventDefault(); + const button = $(event.currentTarget); + if (button.prop('disabled')) { + return; + } + this.modalLocked = false; + this.modal.close('finish'); + setTimeout(() => window.location.reload(), 75); + }); + + this.modalElement.on('change', '[data-safe-upgrade-decision]', (event) => { + const target = $(event.currentTarget); + const decision = target.val(); + const type = target.data('safe-upgrade-decision'); + this.decisions[type] = decision; + this.updateStartButtonState(); + }); + + this.modalElement.on('closing', (event) => { + if (this.modalLocked && event.reason !== 'finish') { + event.preventDefault(); + } + }); + } + + setPayload(payload = {}) { + this.payload = payload; + } + + open() { + this.active = true; + this.decisions = {}; + this.statusFailures = 0; + this.preferDirectStatus = !!this.directStatusUrl; + this.statusContext = null; + this.statusIdleCount = 0; + this.currentStage = null; + this.stageEnteredAt = 0; + this.modalLocked = false; + this.lastOverallPercent = 0; + this.renderLoading(); + this.modal.open(); + this.fetchPreflight(); + } + + renderLoading() { + this.modalLocked = false; + this.resetFooterButtons(); + this.switchStep('preflight'); + this.steps.preflight.html(` +
+ +

${t('SAFE_UPGRADE_CHECKING', 'Running preflight checks...')}

+
+ `); + this.buttons.start.prop('disabled', true).addClass('hidden'); + this.modalElement.find('[data-safe-upgrade-footer]').removeClass('hidden'); + } + + fetchPreflight(silent = false) { + if (!silent) { + this.renderLoading(); + } else { + this.setRecheckLoading(true); + } + + const done = () => { + if (silent) { + this.setRecheckLoading(false); + } + }; + + const requestPromise = request(this.urls.preflight, (response) => { + if (!this.active) { + done(); + return; + } + + if (response.status === 'error') { + done(); + this.renderPreflightError(response.message || t('SAFE_UPGRADE_GENERIC_ERROR', 'Safe upgrade could not complete. See Grav logs for details.')); + return; + } + + this.renderPreflight(response.data || {}); + done(); + }); + + if (silent && requestPromise && typeof requestPromise.catch === 'function') { + requestPromise.catch(() => done()); + } + } + + renderPreflightError(message) { + this.switchStep('preflight'); + this.steps.preflight.html(` +
+

${message}

+ +
+ `); + this.buttons.start.prop('disabled', true).addClass('hidden'); + } + + renderPreflight(data) { + const blockers = []; + const version = data.version || {}; + const releaseDate = version.release_date || ''; + const packageSize = version.package_size ? formatBytes(version.package_size) : t('SAFE_UPGRADE_UNKNOWN_SIZE', 'unknown'); + const warnings = (data.preflight && data.preflight.warnings) || []; + const pending = (data.preflight && data.preflight.plugins_pending) || {}; + const psrConflicts = (data.preflight && data.preflight.psr_log_conflicts) || {}; + const monologConflicts = (data.preflight && data.preflight.monolog_conflicts) || {}; + const isMajorUpgrade = !!(data.preflight && data.preflight.is_major_minor_upgrade); + const hasPendingUpdates = Object.keys(pending).length > 0; + + if (data.status === 'error') { + blockers.push(data.message || t('SAFE_UPGRADE_GENERIC_ERROR', 'Safe upgrade could not complete. See Grav logs for details.')); + } + + if (!data.requirements || !data.requirements.meets) { + blockers.push(r('SAFE_UPGRADE_REQUIREMENTS_FAIL', data.requirements ? data.requirements.minimum_php : '?', 'PHP %s or newer is required before continuing.')); + } + + if (data.symlinked) { + blockers.push(t('GRAV_SYMBOLICALLY_LINKED', 'Grav is symbolically linked. Upgrade will not be available.')); + } + + if (data.safe_upgrade && data.safe_upgrade.enabled === false) { + blockers.push(t('SAFE_UPGRADE_DISABLED', 'Safe upgrade is disabled. Enable it in Configuration ▶ System ▶ Updates.')); + } + + if (!data.safe_upgrade || !data.safe_upgrade.staging_ready) { + const err = data.safe_upgrade && data.safe_upgrade.error ? data.safe_upgrade.error : t('SAFE_UPGRADE_STAGING_ERROR', 'Safe upgrade staging directory is not writable.'); + blockers.push(err); + } + + if (!data.upgrade_available) { + blockers.push(t('SAFE_UPGRADE_NOT_AVAILABLE', 'No Grav update is available.')); + } + + if (hasPendingUpdates && isMajorUpgrade) { + blockers.push(t('SAFE_UPGRADE_PENDING_HINT', 'Because this is a major upgrade, update all plugins and themes before continuing to ensure maximum compatibility.')); + } + + const psrWarningItems = Object.keys(psrConflicts).map((slug) => { + const info = psrConflicts[slug] || {}; + const requires = info.requires || '*'; + + return `
  • ${t('SAFE_UPGRADE_WARNINGS_PSR_ITEM', 'Potential psr/log conflict:')} ${slug} — ${r('SAFE_UPGRADE_CONFLICTS_REQUIRES', requires, 'Requires psr/log %s')}
  • `; + }); + + const monologWarningItems = Object.keys(monologConflicts).map((slug) => { + const entries = Array.isArray(monologConflicts[slug]) ? monologConflicts[slug] : []; + const details = entries.map((entry) => { + const method = entry.method || ''; + const file = entry.file ? basename(entry.file) : ''; + return `${method} ${file ? `${file}` : ''}`; + }).join(', '); + + const description = details || t('SAFE_UPGRADE_WARNINGS_MONOLOG_UNKNOWN', 'Review the plugin for potential API changes.'); + + return `
  • ${t('SAFE_UPGRADE_WARNINGS_MONOLOG_ITEM', 'Potential Monolog conflict:')} ${slug} — ${description}
  • `; + }); + + const filteredWarnings = warnings.filter((warning) => { + const lower = (warning || '').toLowerCase(); + const isPsrRelated = lower.includes('psr/log'); + const isMonologRelated = lower.includes('monolog'); + return !isPsrRelated && !isMonologRelated; + }); + + const warningsList = filteredWarnings.length || psrWarningItems.length || monologWarningItems.length ? ` +
    +
    +
    + +
    + ${t('SAFE_UPGRADE_WARNINGS', 'Warnings')} + ${t('SAFE_UPGRADE_WARNINGS_HINT', 'These items may require attention before continuing.')} +
    +
    +
    +
    +
      + ${filteredWarnings.map((warning) => `
    • ${warning}
    • `).join('')} + ${psrWarningItems.join('')} + ${monologWarningItems.join('')} +
    +
    +
    + ` : ''; + + const pendingList = hasPendingUpdates ? ` +
    +
    +
    + +
    + ${t('SAFE_UPGRADE_PENDING_UPDATES', 'Pending plugin or theme updates')} + ${isMajorUpgrade + ? t('SAFE_UPGRADE_PENDING_INTRO', 'Because this is a major Grav upgrade, update these extensions first to ensure maximum compatibility.') + : t('SAFE_UPGRADE_PENDING_MINOR_DESC', 'These updates are optional for this release; apply them at your convenience.') + } +
    +
    +
    +
    +
      + ${Object.keys(pending).map((slug) => { + const item = pending[slug] || {}; + const type = item.type || 'plugin'; + const current = item.current || t('SAFE_UPGRADE_UNKNOWN_VERSION', 'unknown'); + const next = item.available || t('SAFE_UPGRADE_UNKNOWN_VERSION', 'unknown'); + return `
    • ${slug} (${type}) ${current} → ${next}
    • `; + }).join('')} +
    +
    +
    + ` : ''; + + const psrList = Object.keys(psrConflicts).length ? ` +
    +
    +
    + +
    + ${t('SAFE_UPGRADE_CONFLICTS_PSR', 'Potential psr/log compatibility issues')} + ${t('SAFE_UPGRADE_CONFLICTS_HINT', 'Choose how to handle conflicts before starting the upgrade.')} +
    +
    + ${this.renderDecisionSelect('psr_log')} +
    +
    + ` : ''; + + const monologList = Object.keys(monologConflicts).length ? ` +
    +
    +
    + +
    + ${t('SAFE_UPGRADE_CONFLICTS_MONOLOG', 'Potential Monolog API compatibility issues')} + ${t('SAFE_UPGRADE_CONFLICTS_HINT', 'Choose how to handle conflicts before starting the upgrade.')} +
    +
    + ${this.renderDecisionSelect('monolog')} +
    +
    + ` : ''; + + const blockersList = blockers.length ? ` +
    +
    +
    + +
    + ${t('SAFE_UPGRADE_BLOCKERS_TITLE', 'Action required before continuing')} + ${t('SAFE_UPGRADE_BLOCKERS_DESC', 'Resolve the following items to enable the upgrade.')} +
    +
    +
    +
    +
      ${blockers.map((item) => `
    • ${item}
    • `).join('')}
    +
    +
    + ` : ''; + + const summary = ` +
    +

    ${r('SAFE_UPGRADE_SUMMARY_CURRENT', version.local || '?', 'Current Grav version: v%s')}

    +

    ${r('SAFE_UPGRADE_SUMMARY_REMOTE', version.remote || '?', 'Available Grav version: v%s')}

    +

    ${releaseDate ? r('SAFE_UPGRADE_RELEASED_ON', releaseDate, 'Released on %s') : ''}

    +

    ${r('SAFE_UPGRADE_PACKAGE_SIZE', packageSize, 'Package size: %s')}

    +
    + `; + + this.steps.preflight.html(` +
    + ${summary} + ${warningsList} + ${pendingList} + ${psrList} + ${monologList} + ${blockersList} +
    + `); + + this.switchStep('preflight'); + + const hasBlockingConflicts = (Object.keys(psrConflicts).length && !this.decisions.psr_log) || (Object.keys(monologConflicts).length && !this.decisions.monolog); + const canStart = !blockers.length && !hasBlockingConflicts; + + this.buttons.start + .removeClass('hidden') + .prop('disabled', !canStart) + .text(t('SAFE_UPGRADE_START', 'Start Safe Upgrade')); + + if (Object.keys(psrConflicts).length && !this.decisions.psr_log) { + this.decisions.psr_log = 'disable'; + } + + if (Object.keys(monologConflicts).length && !this.decisions.monolog) { + this.decisions.monolog = 'disable'; + } + + this.updateStartButtonState(); + } + + renderDecisionSelect(type) { + const currentDecision = this.decisions[type] || 'disable'; + const name = `safe-upgrade-decision-${type}`; + const ariaLabel = t('SAFE_UPGRADE_DECISION_PROMPT', 'When conflicts are detected:'); + const options = [ + { + value: 'disable', + label: t('SAFE_UPGRADE_DECISION_DISABLE', 'Disable conflicting plugins'), + description: t('SAFE_UPGRADE_DECISION_DISABLE_DESC', 'Temporarily disable conflicting plugins during the upgrade.') + }, + { + value: 'continue', + label: t('SAFE_UPGRADE_DECISION_CONTINUE', 'Continue with plugins enabled'), + description: t('SAFE_UPGRADE_DECISION_CONTINUE_DESC', 'Proceed with plugins enabled. This may require manual fixes.') + } + ]; + + return ` +
    + ${options.map((option) => ` + + `).join('')} +
    + `; + } + + updateStartButtonState() { + const decisionInputs = this.modalElement.find('[data-safe-upgrade-decision]'); + const unresolved = []; + decisionInputs.each((index, element) => { + const input = $(element); + const key = input.data('safe-upgrade-decision'); + if (!this.decisions[key]) { + unresolved.push(key); + } + }); + + const hasUnresolvedConflicts = unresolved.length > 0; + const blockers = this.steps.preflight.find('.safe-upgrade-blockers li'); + + const disabled = hasUnresolvedConflicts || blockers.length > 0; + this.buttons.start.prop('disabled', disabled); + } + + setRecheckLoading(state) { + const button = this.modalElement.find('[data-safe-upgrade-action="recheck"]'); + if (!button.length) { + return; + } + + const dataKey = 'safe-upgrade-recheck-label'; + + if (state) { + if (!button.data(dataKey)) { + button.data(dataKey, button.html()); + } + + button + .prop('disabled', true) + .addClass('is-loading') + .html(` + + ${t('SAFE_UPGRADE_RECHECKING', 'Re-running Checks...')} + `); + } else { + const original = button.data(dataKey); + button + .prop('disabled', false) + .removeClass('is-loading'); + + if (original) { + button.html(original); + button.removeData(dataKey); + } else { + button.html(t('SAFE_UPGRADE_RECHECK', 'Re-run Checks')); + } + } + } + + startUpgrade() { + this.switchStep('progress'); + this.lastOverallPercent = 0; + this.renderProgress({ + stage: 'initializing', + message: t('SAFE_UPGRADE_STAGE_INITIALIZING', 'Preparing upgrade'), + percent: 0 + }); + + this.buttons.start.prop('disabled', true); + this.buttons.finish.addClass('hidden').prop('disabled', true); + this.modalLocked = false; + this.stopPolling(); + this.jobId = null; + + const decisionFields = {}; + Object.keys(this.decisions || {}).forEach((key) => { + const value = this.decisions[key]; + if (value) { + decisionFields[`decisions[${key}]`] = value; + } + }); + + const body = decisionFields; + + request(this.urls.start, { method: 'post', body }, (response) => { + if (!this.active) { + return; + } + + if (response.status === 'error') { + this.stopPolling(); + this.renderProgress({ + stage: 'error', + message: response.message || t('SAFE_UPGRADE_GENERIC_ERROR', 'Safe upgrade could not complete. See Grav logs for details.'), + percent: null + }); + this.renderResult({ + status: 'error', + message: response.message || t('SAFE_UPGRADE_GENERIC_ERROR', 'Safe upgrade could not complete. See Grav logs for details.') + }); + return; + } + + const data = response.data || {}; + if (data.status === 'error') { + this.stopPolling(); + this.renderProgress({ + stage: 'error', + message: data.message || t('SAFE_UPGRADE_GENERIC_ERROR', 'Safe upgrade could not complete. See Grav logs for details.'), + percent: null + }); + this.renderResult(data); + return; + } + if (data.fallback) { + this.renderResult(data); + this.stopPolling(); + this.renderProgress({ + stage: data.status === 'success' ? 'complete' : 'error', + message: data.message || t('SAFE_UPGRADE_STAGE_COMPLETE', 'Upgrade complete'), + percent: data.status === 'success' ? 100 : null, + target_version: data.version || (data.manifest && data.manifest.target_version) || null, + manifest: data.manifest || null + }); + return; + } + + if (data.status === 'queued' && data.job_id) { + this.jobId = data.job_id; + if (data.progress) { + this.renderProgress(data.progress); + } + this.statusFailures = 0; + this.preferDirectStatus = !!this.directStatusUrl; + this.statusContext = data.context || null; + this.beginPolling(1200); + } else { + this.renderResult(data); + this.stopPolling(); + } + }); + } + + resolveDirectStatusUrl() { + const scriptPath = '/___safe-upgrade-status'; + const join = (base, path) => { + if (!base) { + return path; + } + const trimmed = base.endsWith('/') ? base.slice(0, -1) : base; + return `${trimmed}${path}`; + }; + const normalize = (url) => url.replace(/([^:]\/)\/+/g, '$1'); + + const candidates = [ + config.base_url_simple || '', + (config.base_url_relative || '').replace(/\/admin\/?$/, ''), + '' + ]; + + for (const base of candidates) { + if (typeof base !== 'string') { + continue; + } + const candidate = normalize(join(base, scriptPath)); + if (candidate) { + return candidate; + } + } + + return scriptPath; + } + + resolveStatusEndpoint() { + const useDirect = this.directStatusUrl && this.preferDirectStatus; + let url = useDirect ? this.directStatusUrl : this.urls.status; + const params = []; + + if (this.jobId) { + params.push(`job=${encodeURIComponent(this.jobId)}`); + } + + if (this.statusContext) { + params.push(`context=${encodeURIComponent(this.statusContext)}`); + } + + if (params.length) { + url += (url.includes('?') ? '&' : '?') + params.join('&'); + } + + return { + url, + direct: useDirect + }; + } + + beginPolling(delay = 1200) { + if (this.isPolling) { + return; + } + + this.isPolling = true; + this.schedulePoll(delay); + } + + schedulePoll(delay = 1200) { + this.clearPollTimer(); + if (!this.isPolling) { + return; + } + + this.pollTimer = setTimeout(() => this.fetchStatus(true), delay); + } + + clearPollTimer() { + if (this.pollTimer) { + clearTimeout(this.pollTimer); + this.pollTimer = null; + } + } + + fetchStatus(silent = false) { + if (this.statusRequest) { + return; + } + + this.pollTimer = null; + let nextStage = null; + let jobComplete = false; + let jobFailed = false; + let handled = false; + let lastPayload = null; + + console.debug('[SafeUpgrade] poll status'); + + const endpoint = this.resolveStatusEndpoint(); + const statusUrl = endpoint.url; + const usingDirect = endpoint.direct; + const requestOptions = { silentErrors: true }; + + this.statusRequest = request(statusUrl, requestOptions, (response) => { + console.debug('[SafeUpgrade] status response', response); + + if (!response) { + this.statusFailures += 1; + return; + } + + handled = true; + this.statusFailures = 0; + + if (response.status === 'error') { + if (!silent) { + this.renderProgress({ + stage: 'error', + message: response.message || t('SAFE_UPGRADE_GENERIC_ERROR', 'Safe upgrade could not complete. See Grav logs for details.'), + percent: null + }); + } + nextStage = 'error'; + jobFailed = true; + return; + } + + const payload = response.data || {}; + lastPayload = payload; + if (Object.prototype.hasOwnProperty.call(payload, 'context')) { + this.statusContext = payload.context || null; + } + const job = payload.job || {}; + const data = payload.progress || payload; + nextStage = data.stage || null; + + if (!job || !Object.keys(job).length) { + this.statusIdleCount += 1; + } else { + this.statusIdleCount = 0; + } + + this.renderProgress(data, job); + + if (job.status === 'error') { + nextStage = 'error'; + const message = job.error || data.message || t('SAFE_UPGRADE_GENERIC_ERROR', 'Safe upgrade could not complete. See Grav logs for details.'); + this.renderProgress({ + stage: 'error', + message, + percent: null + }, job); + jobFailed = true; + } else if (job.status === 'success') { + if (data.stage !== 'complete') { + const completePayload = { + stage: 'complete', + message: t('SAFE_UPGRADE_STAGE_COMPLETE', 'Upgrade complete'), + percent: 100, + target_version: (job.result && job.result.version) || data.target_version || null, + manifest: (job.result && job.result.manifest) || data.manifest || null + }; + + this.renderProgress(completePayload, job); + nextStage = 'complete'; + } + jobComplete = true; + } else if (!job.status && data.stage === 'complete') { + jobComplete = true; + } + }); + + const finalize = () => { + this.statusRequest = null; + + if (!this.isPolling) { + return; + } + + if (!handled) { + if (usingDirect && this.statusFailures >= 3) { + this.preferDirectStatus = false; + this.statusFailures = 0; + this.statusIdleCount = 0; + this.schedulePoll(); + } else { + const delay = Math.min(5000, 1200 * Math.max(1, this.statusFailures)); + this.schedulePoll(delay); + } + } else if ((!lastPayload || !lastPayload.job || !Object.keys(lastPayload.job).length) && usingDirect && this.statusIdleCount >= 5) { + this.preferDirectStatus = false; + this.statusFailures = 0; + this.statusIdleCount = 0; + this.schedulePoll(); + } else if (jobFailed) { + this.stopPolling(); + this.jobId = null; + } else if (jobComplete || nextStage === 'complete') { + this.stopPolling(); + this.jobId = null; + } else { + this.schedulePoll(); + } + }; + + this.statusRequest.then(finalize, finalize); + } + + renderProgress(data, job = {}) { + if (!data) { + return; + } + + const stage = data.stage || 'initializing'; + if (stage !== this.currentStage) { + this.currentStage = stage; + this.stageEnteredAt = Date.now(); + } + + const titleResolver = STAGE_TITLES[stage] || STAGE_TITLES.initializing; + const title = titleResolver(); + let percent = typeof data.percent === 'number' ? data.percent : null; + + const scaledPercent = () => { + if (stage === 'queued') { return 0; } + if (stage === 'initializing') { return percent !== null ? Math.min(Math.max(percent, 0), 5) : 5; } + if (stage === 'downloading') { + return this.scaleStagePercent(5, 45, percent, 2); + } + if (stage === 'snapshot') { + return this.scaleStagePercent(45, 70, percent, 2); + } + if (stage === 'installing') { + return this.scaleStagePercent(70, 95, percent, 3); + } + if (stage === 'rollback') { + return this.scaleStagePercent(40, 95, percent, 3); + } + if (stage === 'finalizing') { + return this.scaleStagePercent(50, 99, percent, 1.5); + } + if (stage === 'complete') { return 100; } + if (stage === 'error') { return null; } + return percent; + }; + + percent = scaledPercent(); + if (percent !== null) { + const baseline = typeof this.lastOverallPercent === 'number' ? this.lastOverallPercent : 0; + percent = Math.max(percent, baseline); + this.lastOverallPercent = percent; + } + const displayPercent = percent !== null ? Math.round(percent) : null; + const percentLabel = displayPercent !== null ? `${displayPercent}%` : ''; + + const message = typeof data.message === 'string' ? data.message : ''; + const normalize = (value) => value + .replace(/\u2026/g, '...') + .replace(/\.+$/, '') + .trim() + .toLowerCase(); + const normalizedTitle = normalize(title || ''); + const normalizedMessage = normalize(message || ''); + + const shouldShowMessage = stage === 'error' + ? message.trim().length > 0 + : ( + message && + stage !== 'installing' && + stage !== 'finalizing' && + normalizedMessage !== '' && + normalizedMessage !== normalizedTitle + ); + + const statusLine = job && job.status ? `

    ${t('SAFE_UPGRADE_JOB_STATUS', 'Status')}: ${job.status.toUpperCase()}${job.error ? ` — ${job.error}` : ''}

    ` : ''; + const animateBar = stage !== 'complete' && stage !== 'error' && percent !== null; + const barClass = `safe-upgrade-progress-bar${animateBar ? ' is-active' : ''}`; + const detailMessage = shouldShowMessage ? `

    ${message}

    ` : ''; + + this.steps.progress.html(` +
    +

    ${title}

    + ${detailMessage} + ${statusLine} + ${percentLabel ? `
    ${percentLabel}
    ` : ''} +
    + `); + + this.switchStep('progress'); + + if (stage === 'complete') { + this.renderResult({ + status: 'success', + manifest: data.manifest || null, + version: data.target_version || null + }); + } else if (stage === 'error') { + this.renderResult({ + status: 'error', + message: data.message || t('SAFE_UPGRADE_GENERIC_ERROR', 'Safe upgrade could not complete. See Grav logs for details.') + }); + } + } + + renderResult(result) { + const status = result.status || 'success'; + + if (status === 'success' || status === 'finalized') { + const manifest = result.manifest || {}; + const target = result.version || manifest.target_version || ''; + const identifier = manifest.id || ''; + this.ensureSuccessBannerStyles(); + + this.steps.result.html(` +
    +
    + +
    +

    ${t('SAFE_UPGRADE_STAGE_COMPLETE', 'Upgrade complete')}

    +

    ${r('SAFE_UPGRADE_RESULT_SUCCESS', target, 'Grav Upgrade to v%s Successful!')}

    +
    +
    +
    + ${identifier ? `

    ${r('SAFE_UPGRADE_RESULT_MANIFEST', identifier, 'Snapshot reference: %s')}

    ` : ''} +

    ${t('SAFE_UPGRADE_RESULT_HINT', 'Restore snapshots from Tools → Restore Grav.')}

    +
    +
    + `); + + this.switchStep('result'); + $('[data-gpm-grav]').remove(); + if (target) { + $('#footer .grav-version').html(`v${target}`); + } + if (this.updates) { + this.updates.fetch(true); + } + + this.prepareCompletionFooter(); + } else if (status === 'noop') { + this.steps.result.html(` +
    +

    ${t('SAFE_UPGRADE_RESULT_NOOP', 'Grav is already up to date.')}

    +
    + `); + this.switchStep('result'); + this.prepareCompletionFooter(); + } else { + this.steps.result.html(` +
    +

    ${t('SAFE_UPGRADE_RESULT_FAILURE', 'Safe upgrade failed')}

    +

    ${result.message || t('SAFE_UPGRADE_GENERIC_ERROR', 'Safe upgrade could not complete. See Grav logs for details.')}

    +
    + `); + this.switchStep('result'); + this.modalLocked = false; + this.buttons.finish.addClass('hidden').prop('disabled', true); + this.buttons.cancel.removeClass('hidden').prop('disabled', false); + this.buttons.recheck.removeClass('hidden').prop('disabled', false); + } + } + + ensureSuccessBannerStyles() { + if ($('#safe-upgrade-success-banner-styles').length) { + return; + } + + const css = ` + .safe-upgrade-result.success { + background: rgba(41, 182, 94, 0.08); + border: 1px solid rgba(41, 182, 94, 0.24); + border-radius: 12px; + padding: 1.3rem 1.4rem; + box-shadow: 0 14px 32px rgba(41, 182, 94, 0.18); + margin-bottom: 1rem; + text-align: left; + } + .safe-upgrade-result.success .safe-upgrade-result__banner { + display: flex; + align-items: center; + gap: 0.9rem; + margin-bottom: 0.85rem; + } + .safe-upgrade-result.success .safe-upgrade-result__icon { + width: 44px; + height: 44px; + border-radius: 50%; + background: #27ae60; + color: #fff; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 1.25rem; + box-shadow: 0 10px 22px rgba(39, 174, 96, 0.35); + } + .safe-upgrade-result.success .safe-upgrade-result__label { + font-size: 0.82rem; + letter-spacing: 0.08em; + text-transform: uppercase; + font-weight: 600; + margin: 0 0 0.15rem; + color: rgba(39, 174, 96, 0.85); + } + .safe-upgrade-result.success h3 { + margin: 0; + font-size: 1.2rem; + color: #14301d; + } + .safe-upgrade-result.success .safe-upgrade-result__details { + font-size: 0.95rem; + color: rgba(20, 48, 29, 0.9); + } + .safe-upgrade-result.success .safe-upgrade-result__details p { + margin: 0.4rem 0; + } + `; + + $(' - {% block body %} {% set sidebarStatus = get_cookie('grav-admin-sidebar') %} @@ -88,7 +82,18 @@ {% endblock %} - {% block modals %} +{% set safe_upgrade_enabled = config.system.updates.safe_upgrade|default(false) %} +{% block modals %} + {# Session expired blocking modal #} +
    +
    +

    {{ 'PLUGIN_ADMIN.SESSION_EXPIRED'|t|default('Session Expired') }}

    +

    {{ 'PLUGIN_ADMIN.SESSION_EXPIRED_DESC'|t|default('Your admin login session has expired. Click OK to log in again.') }}

    + +
    +

    {{ "PLUGIN_ADMIN.ERROR"|t }}

    @@ -123,6 +128,27 @@
    + {% if safe_upgrade_enabled %} +
    +
    +
    +

    {{ "PLUGIN_ADMIN.SAFE_UPGRADE_TITLE"|t }}

    +

    {{ "PLUGIN_ADMIN.SAFE_UPGRADE_DESC"|t }}

    +
    +
    +
    + + +
    +
    + + + + +
    +
    +
    + {% else %}

    {{ "PLUGIN_ADMIN.MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_TITLE"|t }}

    @@ -136,6 +162,7 @@
    + {% endif %} {% endblock %} diff --git a/themes/grav/templates/partials/dashboard-pages.html.twig b/themes/grav/templates/partials/dashboard-pages.html.twig index 501e21191..eeba3f8a7 100644 --- a/themes/grav/templates/partials/dashboard-pages.html.twig +++ b/themes/grav/templates/partials/dashboard-pages.html.twig @@ -5,7 +5,7 @@

    {{ "PLUGIN_ADMIN.LATEST_PAGE_UPDATES"|t }}

    - {% for latest in admin.latestPages if admin.latestPages %} + {% for latest in admin.latestPages|default([]) %} {% set route = latest.rawRoute %} {% for log in logs %} - + {% if log.date %} + + {% else %} + + {% endif %} {% if verbose %} diff --git a/themes/grav/templates/partials/tools-restore-grav.html.twig b/themes/grav/templates/partials/tools-restore-grav.html.twig new file mode 100644 index 000000000..9171c7ec5 --- /dev/null +++ b/themes/grav/templates/partials/tools-restore-grav.html.twig @@ -0,0 +1,71 @@ +

    {{ "PLUGIN_ADMIN.RESTORE_GRAV"|t }}

    + +
    + {% set snapshots = admin.safeUpgradeSnapshots() %} + + {% if snapshots %} +

    + {{ "PLUGIN_ADMIN.RESTORE_GRAV_DESC"|t }} +

    + +
    + + {{ nonce_field('admin-form', 'admin-nonce')|raw }} + + +
    diff --git a/themes/grav/templates/partials/javascript-config.html.twig b/themes/grav/templates/partials/javascript-config.html.twig index c0c1542aa..77bdaffb3 100644 --- a/themes/grav/templates/partials/javascript-config.html.twig +++ b/themes/grav/templates/partials/javascript-config.html.twig @@ -4,6 +4,7 @@ {% set plugins_enabled = config.plugins.admin.notifications.plugins is same as(true) or config.plugins.admin.notifications.plugins == 'true' %} {% set themes_enabled = config.plugins.admin.notifications.themes is same as(true) or config.plugins.admin.notifications.themes == 'true' %} {% set notifications = (feed_enabled or dashboard_enabled or plugins_enabled or themes_enabled) ? 1 : 0 %} +{% set safe_upgrade_enabled = config.system.updates.safe_upgrade|default(false) %} {% switch template_route %} {% case 'dashboard' %} @@ -27,6 +28,8 @@ enable_auto_updates_check: '{{ config.plugins.admin.enable_auto_updates_check }}', {% endif %} admin_timeout: '{{ config.plugins.admin.session.timeout ?: 1800 }}', + keep_alive_enabled: {{ (config.plugins.admin.session.keep_alive is defined ? config.plugins.admin.session.keep_alive : true) ? 1 : 0 }}, + safe_upgrade_enabled: {{ safe_upgrade_enabled ? 1 : 0 }}, admin_nonce: '{{ admin.getNonce }}', language: '{{ grav.user.language|default('en') }}', pro_enabled: '{{ config.plugins["admin-pro"].enabled }}', diff --git a/themes/grav/templates/partials/javascripts.html.twig b/themes/grav/templates/partials/javascripts.html.twig index 15bfec787..161084a1b 100644 --- a/themes/grav/templates/partials/javascripts.html.twig +++ b/themes/grav/templates/partials/javascripts.html.twig @@ -1,11 +1,47 @@ {% do assets.add('jquery',101) %} {% if authorize(['admin.login', 'admin.super']) %} -{% do assets.addJs(theme_url~'/js/vendor.min.js', { 'loading':'defer' }) %} -{% do assets.addJs(theme_url~'/js/admin.min.js' , { 'loading':'defer' }) %} + {% do assets.addJs(theme_url~'/js/vendor.min.js', { 'loading':'defer' }) %} + {% do assets.addJs(theme_url~'/js/admin.min.js' , { 'loading':'defer' }) %} -{% if browser.getBrowser == 'msie' or browser.getBrowser == 'edge' %} - {% do assets.addJs(theme_url~'/js/form-attr.polyfill.js') %} -{% endif %} + {% if browser.getBrowser == 'msie' or browser.getBrowser == 'edge' %} + {% do assets.addJs(theme_url~'/js/form-attr.polyfill.js') %} + {% endif %} + + {% include 'partials/javascripts-extra.html.twig' ignore missing %} +{% else %} + {# Not authorized (e.g., login page). Keep session + login nonce fresh. No session-expired overlay here. #} + {% endif %} diff --git a/themes/grav/templates/partials/tools-logs.html.twig b/themes/grav/templates/partials/tools-logs.html.twig index 70b9f9876..380b8a6bd 100644 --- a/themes/grav/templates/partials/tools-logs.html.twig +++ b/themes/grav/templates/partials/tools-logs.html.twig @@ -53,7 +53,11 @@
    {{ log.date|date }}{{ log.date|date('D, d M Y H:i:s') }}{{ log.level }} {{ log.message }}
    + + + + + + + + + + + {% for snapshot in snapshots %} + {% set version = snapshot.source_version ?: snapshot.target_version %} + + + + + + + + {% endfor %} + +
    {{ "PLUGIN_ADMIN.RESTORE_GRAV_TABLE_SNAPSHOT"|t }}{{ "PLUGIN_ADMIN.RESTORE_GRAV_TABLE_VERSION"|t }}{{ "PLUGIN_ADMIN.RESTORE_GRAV_TABLE_CREATED"|t }}{{ "PLUGIN_ADMIN.RESTORE_GRAV_TABLE_ACTIONS"|t }}
    + + + {% if snapshot.label %} + {{ snapshot.label }}
    + {{ snapshot.id }} + {% else %} + {{ snapshot.id }} + {% endif %} +
    {{ version ?: "PLUGIN_ADMIN.UNKNOWN"|t }} + {% if snapshot.created_at %} + {{ snapshot.created_at|date('Y-m-d H:i:s') }} + {{ snapshot.created_at|nicetime(false, false) }} + {% else %} + {{ "PLUGIN_ADMIN.UNKNOWN"|t }} + {% endif %} + + +
    + +
    + + +
    + {% else %} +
    +

    {{ "PLUGIN_ADMIN.RESTORE_GRAV_NONE"|t }}

    +
    + {% endif %} + diff --git a/themes/grav/templates/tools.html.twig b/themes/grav/templates/tools.html.twig index 7706707a3..7b168ef6b 100644 --- a/themes/grav/templates/tools.html.twig +++ b/themes/grav/templates/tools.html.twig @@ -2,8 +2,11 @@ {% set tools_slug = uri.basename %} {% if tools_slug == 'tools' %}{% set tools_slug = 'backups' %}{% endif %} -{% set title = "PLUGIN_ADMIN.TOOLS"|t ~ ": " ~ ("PLUGIN_ADMIN." ~ tools_slug|underscorize|upper)|t %} {% set tools = admin.tools() %} +{% if tools[tools_slug] is not defined %} + {% set tools_slug = tools|keys|first %} +{% endif %} +{% set title = "PLUGIN_ADMIN.TOOLS"|t ~ ": " ~ ("PLUGIN_ADMIN." ~ tools_slug|underscorize|upper)|t %} {% set titlebar -%} {% include 'partials/tools-' ~ tools_slug ~ '-titlebar.html.twig' ignore missing %} @@ -36,6 +39,7 @@ {% endif %} + {{ dump(tools) }} {% endblock %} {% block content %} @@ -47,4 +51,3 @@

    Unauthorized

    {% endif %} {% endblock %} - diff --git a/themes/grav/watch.sh b/themes/grav/watch.sh deleted file mode 100755 index de3654d42..000000000 --- a/themes/grav/watch.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -# -# Configuration -# - -# sass source - -SASS_SOURCE_PATH="scss" - -# sass options -SASS_OPTIONS="--source-map=true --style=nested" - -# css target -CSS_TARGET_PATH="css-compiled" - -# -# Check prerequisites -# -wtfile=$(command -v wt) || { echo "install wellington with 'brew install wellington"; exit 1; } - -# -# Watch folder for changes -# -cd -P `pwd` -$wtfile compile "$SASS_SOURCE_PATH" -b "$CSS_TARGET_PATH" $SASS_OPTIONS -$wtfile watch "$SASS_SOURCE_PATH" -b "$CSS_TARGET_PATH" $SASS_OPTIONS diff --git a/themes/grav/webpack.conf.js b/themes/grav/webpack.conf.js index cae4d262e..0a175299b 100644 --- a/themes/grav/webpack.conf.js +++ b/themes/grav/webpack.conf.js @@ -33,10 +33,7 @@ module.exports = (env, argv) => ({ jquery: 'jQuery', 'grav-config': 'GravAdmin' }, - plugins: [new ESLintPlugin({ - extensions: ['js', 'jsx'], - exclude: ['/node_modules/'] - })], + plugins: [], module: { rules: [ { enforce: 'pre', test: /\.json$/, loader: 'json-loader' }, diff --git a/themes/grav/yarn.lock b/themes/grav/yarn.lock deleted file mode 100644 index a272c8fc0..000000000 --- a/themes/grav/yarn.lock +++ /dev/null @@ -1,3201 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.0.2.tgz#f3d9760bf30588c51408dbe7c05ff2bb13069307" - integrity sha512-sE8Gx+qSDMLoJvb3QarJJlDQK7SSY4rK3hxp4XsiANeFOmjU46ZI7Y9adAQRJrmbz8zbtZkp3mJTT+rGxtF0XA== - dependencies: - "@jridgewell/trace-mapping" "^0.2.2" - sourcemap-codec "1.4.8" - -"@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4": - version "7.16.4" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz" - integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q== - -"@babel/compat-data@^7.16.8": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" - integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== - -"@babel/core@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.0.tgz#16b8772b0a567f215839f689c5ded6bb20e864d5" - integrity sha512-x/5Ea+RO5MvF9ize5DeVICJoVrNv0Mi2RnIABrZEKYvPEpldXwauPkgvYA17cKa6WpU3LoYvYbuEMFtSNFsarA== - dependencies: - "@ampproject/remapping" "^2.0.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.0" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helpers" "^7.17.0" - "@babel/parser" "^7.17.0" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" - "@babel/types" "^7.17.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - -"@babel/generator@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.16.7.tgz" - integrity sha512-/ST3Sg8MLGY5HVYmrjOgL60ENux/HfO/CsUh7y4MalThufhE/Ff/6EibFDHi4jiDCaWfJKoqbE6oTh21c5hrRg== - dependencies: - "@babel/types" "^7.16.7" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.0.tgz#7bd890ba706cd86d3e2f727322346ffdbf98f65e" - integrity sha512-I3Omiv6FGOC29dtlZhkfXO6pgkmukJSlT26QjVvS1DGZe/NzSVCPG41X0tS21oZkJYlovfj9qDWgKP+Cn4bXxw== - dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/helper-annotate-as-pure@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz" - integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz" - integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz" - integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== - dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.16.10": - version "7.17.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz#9699f14a88833a7e055ce57dcd3ffdcd25186b21" - integrity sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - -"@babel/helper-create-class-features-plugin@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz" - integrity sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - -"@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz" - integrity sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - regexpu-core "^4.7.1" - -"@babel/helper-define-polyfill-provider@^0.3.0": - version "0.3.0" - resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz" - integrity sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg== - dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" - -"@babel/helper-define-polyfill-provider@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" - integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== - dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" - -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-explode-assignable-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz" - integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== - dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-member-expression-to-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz" - integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-transforms@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz" - integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-optimise-call-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz" - integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== - -"@babel/helper-remap-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" - integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-wrap-function" "^7.16.8" - "@babel/types" "^7.16.8" - -"@babel/helper-replace-supers@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz" - integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-simple-access@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz" - integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz" - integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - -"@babel/helper-wrap-function@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" - integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== - dependencies: - "@babel/helper-function-name" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.8" - "@babel/types" "^7.16.8" - -"@babel/helpers@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.0.tgz#79cdf6c66a579f3a7b5e739371bc63ca0306886b" - integrity sha512-Xe/9NFxjPwELUvW2dsukcMZIp6XwPSbI4ojFBJuX5ramHuVE22SVcZIwqzdWo5uCgeTXW8qV97lMvSOjq+1+nQ== - dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" - "@babel/types" "^7.17.0" - -"@babel/highlight@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.7.tgz" - integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.16.7.tgz" - integrity sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA== - -"@babel/parser@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.0.tgz#f0ac33eddbe214e4105363bb17c3341c5ffcc43c" - integrity sha512-VKXSCQx5D8S04ej+Dqsr1CzYvvWgf20jIw2D+YhQCrIlr2UZGaDds23Y0xg75/skOxpLCRpUZvk/1EAVkGoDOw== - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": - version "7.16.7" - 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.16.7.tgz" - integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz" - integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" - -"@babel/plugin-proposal-async-generator-functions@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" - integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-remap-async-to-generator" "^7.16.8" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz" - integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz" - integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-proposal-dynamic-import@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz" - integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz" - integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz" - integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz" - integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz" - integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-proposal-numeric-separator@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz" - integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz" - integrity sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA== - dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.16.7" - -"@babel/plugin-proposal-optional-catch-binding@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz" - integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz" - integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-private-methods@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" - integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.10" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-proposal-private-property-in-object@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz" - integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz" - integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-syntax-async-generators@^7.8.4": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.13": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-class-static-block@^7.14.5": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-dynamic-import@^7.8.3": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-import-meta@^7.10.4": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-private-property-in-object@^7.14.5": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-top-level-await@^7.14.5": - 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== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-arrow-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz" - integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" - integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== - dependencies: - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-remap-async-to-generator" "^7.16.8" - -"@babel/plugin-transform-block-scoped-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz" - integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-block-scoping@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz" - integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-classes@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz" - integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz" - integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-destructuring@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz" - integrity sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz" - integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-duplicate-keys@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz" - integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-exponentiation-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz" - integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-for-of@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz" - integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz" - integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== - dependencies: - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz" - integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-member-expression-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz" - integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-modules-amd@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz" - integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== - dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-commonjs@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" - integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== - dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-systemjs@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz" - integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== - dependencies: - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-umd@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz" - integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== - dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" - integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - -"@babel/plugin-transform-new-target@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz" - integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-object-super@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz" - integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - -"@babel/plugin-transform-parameters@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz" - integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-property-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz" - integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-regenerator@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz" - integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-reserved-words@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz" - integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-shorthand-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz" - integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz" - integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - -"@babel/plugin-transform-sticky-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz" - integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-template-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz" - integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-typeof-symbol@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz" - integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-unicode-escapes@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz" - integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-unicode-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz" - integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/polyfill@^7.12.1": - version "7.12.1" - resolved "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz" - integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g== - dependencies: - core-js "^2.6.5" - regenerator-runtime "^0.13.4" - -"@babel/preset-env@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" - integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== - dependencies: - "@babel/compat-data" "^7.16.8" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-async-generator-functions" "^7.16.8" - "@babel/plugin-proposal-class-properties" "^7.16.7" - "@babel/plugin-proposal-class-static-block" "^7.16.7" - "@babel/plugin-proposal-dynamic-import" "^7.16.7" - "@babel/plugin-proposal-export-namespace-from" "^7.16.7" - "@babel/plugin-proposal-json-strings" "^7.16.7" - "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" - "@babel/plugin-proposal-numeric-separator" "^7.16.7" - "@babel/plugin-proposal-object-rest-spread" "^7.16.7" - "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-private-methods" "^7.16.11" - "@babel/plugin-proposal-private-property-in-object" "^7.16.7" - "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" - "@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-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-transform-arrow-functions" "^7.16.7" - "@babel/plugin-transform-async-to-generator" "^7.16.8" - "@babel/plugin-transform-block-scoped-functions" "^7.16.7" - "@babel/plugin-transform-block-scoping" "^7.16.7" - "@babel/plugin-transform-classes" "^7.16.7" - "@babel/plugin-transform-computed-properties" "^7.16.7" - "@babel/plugin-transform-destructuring" "^7.16.7" - "@babel/plugin-transform-dotall-regex" "^7.16.7" - "@babel/plugin-transform-duplicate-keys" "^7.16.7" - "@babel/plugin-transform-exponentiation-operator" "^7.16.7" - "@babel/plugin-transform-for-of" "^7.16.7" - "@babel/plugin-transform-function-name" "^7.16.7" - "@babel/plugin-transform-literals" "^7.16.7" - "@babel/plugin-transform-member-expression-literals" "^7.16.7" - "@babel/plugin-transform-modules-amd" "^7.16.7" - "@babel/plugin-transform-modules-commonjs" "^7.16.8" - "@babel/plugin-transform-modules-systemjs" "^7.16.7" - "@babel/plugin-transform-modules-umd" "^7.16.7" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" - "@babel/plugin-transform-new-target" "^7.16.7" - "@babel/plugin-transform-object-super" "^7.16.7" - "@babel/plugin-transform-parameters" "^7.16.7" - "@babel/plugin-transform-property-literals" "^7.16.7" - "@babel/plugin-transform-regenerator" "^7.16.7" - "@babel/plugin-transform-reserved-words" "^7.16.7" - "@babel/plugin-transform-shorthand-properties" "^7.16.7" - "@babel/plugin-transform-spread" "^7.16.7" - "@babel/plugin-transform-sticky-regex" "^7.16.7" - "@babel/plugin-transform-template-literals" "^7.16.7" - "@babel/plugin-transform-typeof-symbol" "^7.16.7" - "@babel/plugin-transform-unicode-escapes" "^7.16.7" - "@babel/plugin-transform-unicode-regex" "^7.16.7" - "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.16.8" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - core-js-compat "^3.20.2" - semver "^6.3.0" - -"@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/register@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.17.0.tgz#8051e0b7cb71385be4909324f072599723a1f084" - integrity sha512-UNZsMAZ7uKoGHo1HlEXfteEOYssf64n/PNLHGqOKq/bgYcu/4LrQWAHJwSCb3BRZK8Hi5gkJdRcwrGTO2wtRCg== - dependencies: - clone-deep "^4.0.1" - find-cache-dir "^2.0.0" - make-dir "^2.1.0" - pirates "^4.0.5" - source-map-support "^0.5.16" - -"@babel/runtime@^7.8.4": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz" - integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.7.tgz" - integrity sha512-8KWJPIb8c2VvY8AJrydh6+fVRo2ODx1wYBU2398xJVq0JomuLBZmVQzLPBblJgHIGYG4znCpUZUZ0Pt2vdmVYQ== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.0.tgz#3143e5066796408ccc880a33ecd3184f3e75cd30" - integrity sha512-fpFIXvqD6kC7c7PUNnZ0Z8cQXlarCLtCUpt2S1Dx7PjoRtCFffvOkHHSom+m5HIxMZn5bIBVb71lhabcmjEsqg== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.0" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.0" - "@babel/types" "^7.17.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.4.4": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.16.7.tgz" - integrity sha512-E8HuV7FO9qLpx6OtoGfUQ2cjIYnbFwvZWYBS+87EwtdMvmUPJSwykpovFB+8insbpF0uJcpr8KMUi64XZntZcg== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.16.8", "@babel/types@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@discoveryjs/json-ext@^0.5.0": - version "0.5.6" - resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz" - integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA== - -"@eslint/eslintrc@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" - integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.2.0" - globals "^13.9.0" - ignore "^4.0.6" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.0.4" - strip-json-comments "^3.1.1" - -"@humanwhocodes/config-array@^0.9.2": - version "0.9.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.3.tgz#f2564c744b387775b436418491f15fce6601f63e" - integrity sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.4.tgz#b876e3feefb9c8d3aa84014da28b5e52a0640d72" - integrity sha512-cz8HFjOFfUBtvN+NXYSFMHYRdxZMaEl0XypVrhzxBgadKIXhIkRd8aMeHhmF56Sl7SuS8OnUpQ73/k9LE4VnLg== - -"@jridgewell/trace-mapping@^0.2.2": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.2.5.tgz#d5061cc513fd3a0a949feb56b8073989865b1abe" - integrity sha512-K+Eths78fXDFOvQ2hgJhCiI5s+g81r2yXmACBpbn+f2+Qt94PNoTgUcAXPT8DZkhXCsZRsHVWVtY5KIBMcpDqQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - sourcemap-codec "1.4.8" - -"@juggle/resize-observer@^3.3.1": - version "3.3.1" - resolved "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.3.1.tgz" - integrity sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw== - -"@types/eslint-scope@^3.7.0": - version "3.7.0" - resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz" - integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "7.2.6" - resolved "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz" - integrity sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/eslint@^7.28.2": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78" - integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*", "@types/estree@^0.0.50": - version "0.0.50" - resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== - -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": - version "7.0.9" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== - -"@types/node@*": - version "17.0.8" - resolved "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz" - integrity sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg== - -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== - -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== - -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== - -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== - -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@xtuc/long" "4.2.2" - -"@webpack-cli/configtest@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.1.1.tgz#9f53b1b7946a6efc2a749095a4f450e2932e8356" - integrity sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg== - -"@webpack-cli/info@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.4.1.tgz#2360ea1710cbbb97ff156a3f0f24556e0fc1ebea" - integrity sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA== - dependencies: - envinfo "^7.7.3" - -"@webpack-cli/serve@^1.6.1": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.1.tgz#0de2875ac31b46b6c5bb1ae0a7d7f0ba5678dffe" - integrity sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw== - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - -acorn-jsx@^5.3.1: - version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.4.1, acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - -ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - 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" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - 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== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansicolors@~0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz" - integrity sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8= - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -async@^2.6.0: - version "2.6.3" - resolved "https://registry.npmjs.org/async/-/async-2.6.3.tgz" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== - dependencies: - lodash "^4.17.14" - -babel-loader@^8.2.3: - version "8.2.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" - integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== - dependencies: - find-cache-dir "^3.3.1" - loader-utils "^1.4.0" - make-dir "^3.1.0" - schema-utils "^2.6.5" - -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== - dependencies: - object.assign "^4.1.0" - -babel-plugin-polyfill-corejs2@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz" - integrity sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA== - dependencies: - "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.3.0" - semver "^6.1.1" - -babel-plugin-polyfill-corejs3@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" - integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.1" - core-js-compat "^3.21.0" - -babel-plugin-polyfill-regenerator@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz" - integrity sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.0" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -bootstrap@^3.3: - version "3.4.1" - resolved "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz" - integrity sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.14.5, browserslist@^4.17.5, browserslist@^4.19.1: - version "4.19.1" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== - dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -call-bind@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz" - integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.0" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -can-use-dom@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/can-use-dom/-/can-use-dom-0.1.0.tgz" - integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo= - -caniuse-lite@^1.0.30001286: - version "1.0.30001297" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001297.tgz" - integrity sha512-6bbIbowYG8vFs/Lk4hU9jFt7NknGDleVAciK916tp6ft1j+D//ZwwL6LbF1wXMQ32DMSjeuUV8suhh6dlmFjcA== - -cardinal@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz" - integrity sha1-UOIcGwqjdyn5N33vGWtanOyTLuk= - dependencies: - ansicolors "~0.2.1" - redeyed "~1.0.0" - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0: - version "4.1.0" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chartist@0.11.4: - version "0.11.4" - resolved "https://registry.npmjs.org/chartist/-/chartist-0.11.4.tgz" - integrity sha512-H4AimxaUD738/u9Mq8t27J4lh6STsLi4BQHt65nOtpLk3xyrBPaLiLMrHw7/WV9CmsjGA02WihjuL5qpSagLYw== - -chrome-trace-event@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz" - integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== - dependencies: - tslib "^1.9.0" - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -codemirror@^5.65.1: - version "5.65.1" - resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.1.tgz#5988a812c974c467f964bcc1a00c944e373de502" - integrity sha512-s6aac+DD+4O2u1aBmdxhB7yz2XU7tG3snOyQ05Kxifahz7hoxnfxIRHxiCSEv3TUC38dIVH8G+lZH9UWSfGQxA== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colorette@^2.0.14: - version "2.0.16" - resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== - -commander@^2.20.0: - 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== - -commander@^7.0.0: - version "7.2.0" - resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.0.tgz#bcc86aa5a589cee358e7a7fa0a4979d5a76c3885" - integrity sha512-OSXseNPSK2OPJa6GdtkMz/XxeXx8/CJvfhQWTqd6neuUraujcL4jVsjkLQz1OWnax8xVQJnRPe0V2jqNWORA+A== - dependencies: - browserslist "^4.19.1" - semver "7.0.0" - -core-js@^2.6.5: - version "2.6.11" - resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz" - integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== - -core-js@^3.0.1: - version "3.7.0" - resolved "https://registry.npmjs.org/core-js/-/core-js-3.7.0.tgz" - integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA== - -cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -css-loader@^6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" - integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.5" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" - postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" - semver "^7.3.5" - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -csv-parse@^4.6.5: - version "4.14.1" - resolved "https://registry.npmjs.org/csv-parse/-/csv-parse-4.14.1.tgz" - integrity sha512-4wmcO7QbWtDAncGFaBwlWFPhEN4Akr64IbM4zvDwEOFekI8blLc04Nw7XjQjtSNy+3AUAgBgtUa9nWo5Cq89Xg== - -debounce@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz" - integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== - -debug@^4.1.0, debug@^4.1.1: - version "4.2.0" - resolved "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== - dependencies: - ms "2.1.2" - -debug@^4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -deep-is@^0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dropzone@^5.9.3: - version "5.9.3" - resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-5.9.3.tgz#b3070ae090fa48cbc04c17535635537ca72d70d6" - integrity sha512-Azk8kD/2/nJIuVPK+zQ9sjKMRIpRvNyqn9XwbBHNq+iNuSccbJS6hwm1Woy0pMST0erSo0u4j+KJaodndDk4vA== - -electron-to-chromium@^1.4.17: - version "1.4.38" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.38.tgz" - integrity sha512-WhHt3sZazKj0KK/UpgsbGQnUUoFeAHVishzHFExMxagpZgjiGYSC9S0ZlbhCfSH2L2i+2A1yyqOIliTctMx7KQ== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -enhanced-resolve@^5.8.3: - version "5.8.3" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -envinfo@^7.7.3: - version "7.8.1" - resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz" - integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== - -eonasdan-bootstrap-datetimepicker@^4.17.49: - version "4.17.49" - resolved "https://registry.npmjs.org/eonasdan-bootstrap-datetimepicker/-/eonasdan-bootstrap-datetimepicker-4.17.49.tgz" - integrity sha512-7KZeDpkj+A6AtPR3XjX8gAnRPUkPSfW0OmMANG1dkUOPMtLSzbyoCjDIdEcfRtQPU5X0D9Gob7wWKn0h4QWy7A== - dependencies: - bootstrap "^3.3" - jquery "^3.5.1" - moment "^2.10" - moment-timezone "^0.4.0" - -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" - integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz" - integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== - -eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1" - integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ== - -eslint-webpack-plugin@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz#83dad2395e5f572d6f4d919eedaa9cf902890fcb" - integrity sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg== - dependencies: - "@types/eslint" "^7.28.2" - jest-worker "^27.3.1" - micromatch "^4.0.4" - normalize-path "^3.0.0" - schema-utils "^3.1.1" - -eslint@^8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.8.0.tgz#9762b49abad0cb4952539ffdb0a046392e571a2d" - integrity sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ== - dependencies: - "@eslint/eslintrc" "^1.0.5" - "@humanwhocodes/config-array" "^0.9.2" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.0" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.2.0" - espree "^9.3.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^6.0.1" - globals "^13.6.0" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -espree@^9.2.0, espree@^9.3.0: - version "9.3.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.0.tgz#c1240d79183b72aaee6ccfa5a90bc9111df085a8" - integrity sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ== - dependencies: - acorn "^8.7.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.1.0" - -esprima@~3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz" - integrity sha1-U88kes2ncxPlUcOqLnM0LT+099k= - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0: - version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -eventemitter3@^4.0.7: - version "4.0.7" - resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.2.0, events@^3.3.0: - version "3.3.0" - resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exif-js@^2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/exif-js/-/exif-js-2.3.0.tgz" - integrity sha1-nRCBm/Vx+HOBPnZAJBJVq5zhqBQ= - -exports-loader@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/exports-loader/-/exports-loader-3.1.0.tgz#a68040b902da8ef24f9f6db716be904ac2455284" - integrity sha512-zkMR5OHDn8qHq2w5BLv6SnLmUK5QAtPkjTA7CNIYBB9kIxBFIeA+TA1GcMw3p/vn5Avnmq80L7MviA4tZclRmQ== - dependencies: - source-map "^0.6.1" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - 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== - -fast-json-stable-stringify@^2.0.0: - 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== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fastest-levenshtein@^1.0.12: - version "1.0.12" - resolved "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz" - integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-cache-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-cache-dir@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" - integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.4" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz" - integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - -gensync@^1.0.0-beta.2: - 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== - -get-intrinsic@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz" - integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-to-regexp@^0.4.1: - 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== - -glob@^7.1.3: - version "7.1.6" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.6.0, globals@^13.9.0: - version "13.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz" - integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== - dependencies: - type-fest "^0.20.2" - -graceful-fs@^4.1.2, graceful-fs@^4.2.4: - version "4.2.4" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== - -graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -humanize@^0.0.9: - version "0.0.9" - resolved "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz" - integrity sha1-GZT/rs3+nEQe0r2sdFK3u0yeQaQ= - -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - -ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -immutable@^3.2.1: - version "3.8.2" - resolved "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz" - integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= - -immutable@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" - integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== - -immutablediff@^0.4.4: - version "0.4.4" - resolved "https://registry.npmjs.org/immutablediff/-/immutablediff-0.4.4.tgz" - integrity sha1-oBDmlI9wD+EkNkM/NsbirYaXKrE= - dependencies: - immutable "^3.2.1" - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imports-loader@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-3.1.1.tgz#3e464d9aad1e303b1b34b658eb8f8aae22f96435" - integrity sha512-3QMyGU4RTgxLf0puWkUfT5+7zJvexvB00PI5skDIcxG8O20gZCbQsaRpNBv+cIO6yy/lmlOBwaxc3uH1CV+sww== - dependencies: - source-map "^0.6.1" - strip-comments "^2.0.1" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -interpret@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz" - integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== - -is-core-module@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz" - integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== - dependencies: - has "^1.0.3" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-glob@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-object@^2.0.4: - 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== - dependencies: - isobject "^3.0.1" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -jest-worker@^27.3.1, jest-worker@^27.4.1, jest-worker@^27.4.5: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e" - integrity sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jquery@*, jquery@>=1.12.0, jquery@^3.5.1: - version "3.5.1" - resolved "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz" - integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-loader@^0.5.7: - version "0.5.7" - resolved "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz" - integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== - -json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-schema-traverse@^0.4.1: - 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== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.1.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== - dependencies: - minimist "^1.2.5" - -kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== - -loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz" - integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= - -lodash@^4.17.14: - version "4.17.20" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-dir@^2.0.0, make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-dir@^3.0.2, make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -microplugin@0.0.3: - version "0.0.3" - resolved "https://registry.npmjs.org/microplugin/-/microplugin-0.0.3.tgz" - integrity sha1-H8Lhu3yeGegr2Eu6kTe75xJQ2M0= - -mime-db@1.44.0: - version "1.44.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz" - integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== - -mime-types@^2.1.27: - version "2.1.27" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== - dependencies: - mime-db "1.44.0" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.5, minimist@~0.0.1: - version "1.2.5" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -moment-timezone@^0.4.0: - version "0.4.1" - resolved "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.4.1.tgz" - integrity sha1-gfWYw61eIs2teWtn7NjYjQ9bqgY= - dependencies: - moment ">= 2.6.0" - -"moment@>= 2.6.0", moment@^2.10: - version "2.29.1" - resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== - -mout@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/mout/-/mout-1.2.3.tgz#bd1477d8c7f2db5fcf43c91de30b6cc746b78e10" - integrity sha512-vtE+eZcSj/sBkIp6gxB87MznryWP+gHIp0XX9SKrzA5TAkvz6y7VTuNruBjYdJozd8NY5i9XVIsn8cn3SwNjzg== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -nanoid@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" - integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.0: - version "4.1.2" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^3.0.0: - 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== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parent-module@^1.0.0: - 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== - dependencies: - callsites "^3.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.2.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pirates@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" - integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-dir@^4.1.0, pkg-dir@^4.2.0: - 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== - dependencies: - find-up "^4.0.0" - -popper.js@^1.14.4: - version "1.16.1" - resolved "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== - -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== - -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== - dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" - -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== - dependencies: - postcss-selector-parser "^6.0.4" - -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== - dependencies: - icss-utils "^5.0.0" - -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: - version "6.0.4" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz" - integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== - dependencies: - cssesc "^3.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - util-deprecate "^1.0.2" - -postcss-value-parser@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz" - integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== - -postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== - -postcss@^8.4.5: - version "8.4.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" - integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== - dependencies: - nanoid "^3.2.0" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -rangetouch@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz" - integrity sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA== - -rechoir@^0.7.0: - version "0.7.0" - resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz" - integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q== - dependencies: - resolve "^1.9.0" - -redeyed@~1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz" - integrity sha1-6WwZO0DAgWsArshCaY5hGF5VSYo= - dependencies: - esprima "~3.0.0" - -regenerate-unicode-properties@^9.0.0: - version "9.0.0" - resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz" - integrity sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.4: - version "0.13.7" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz" - integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== - -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== - dependencies: - "@babel/runtime" "^7.8.4" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -regexpu-core@^4.7.1: - version "4.8.0" - resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz" - integrity sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^9.0.0" - regjsgen "^0.5.2" - regjsparser "^0.7.0" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" - -regjsgen@^0.5.2: - version "0.5.2" - resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== - -regjsparser@^0.7.0: - version "0.7.0" - resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz" - integrity sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ== - dependencies: - jsesc "~0.5.0" - -remodal@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/remodal/-/remodal-1.1.1.tgz" - integrity sha1-APWAsJQXsrfnpCWxcyfsEPPVlsM= - dependencies: - jquery "*" - -resolve-cwd@^3.0.0: - 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== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve@^1.14.2, resolve@^1.9.0: - version "1.19.0" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== - dependencies: - is-core-module "^2.1.0" - path-parse "^1.0.6" - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -safe-buffer@^5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -schema-utils@^2.6.5: - version "2.7.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" - integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== - dependencies: - "@types/json-schema" "^7.0.5" - ajv "^6.12.4" - ajv-keywords "^3.5.2" - -schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -selectize@^0.12.6: - version "0.12.6" - resolved "https://registry.npmjs.org/selectize/-/selectize-0.12.6.tgz" - integrity sha512-bWO5A7G+I8+QXyjLfQUgh31VI4WKYagUZQxAXlDyUmDDNrFxrASV0W9hxCOl0XJ/XQ1dZEu3G9HjXV4Wj0yb6w== - dependencies: - microplugin "0.0.3" - sifter "^0.5.1" - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^5.6.0: - version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.5: - version "7.3.5" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -sifter@^0.5.1: - version "0.5.4" - resolved "https://registry.npmjs.org/sifter/-/sifter-0.5.4.tgz" - integrity sha512-t2yxTi/MM/ESup7XH5oMu8PUcttlekt269RqxARgnvS+7D/oP6RyA1x3M/5w8dG9OgkOyQ8hNRWelQ8Rj4TAQQ== - dependencies: - async "^2.6.0" - cardinal "^1.0.0" - csv-parse "^4.6.5" - humanize "^0.0.9" - optimist "^0.6.1" - -signal-exit@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - -simplebar@^5.3.6: - version "5.3.6" - resolved "https://registry.yarnpkg.com/simplebar/-/simplebar-5.3.6.tgz#d9383576a09a6fd09e19543f8e9906a3e87c3896" - integrity sha512-FJUMbV+hNDd/m+1/fvD41TXKd5mSdlI5zgBygkaQIV3SffNbcLhSbJT6ufTs8ZNRLJ6i+qc/KCFMqWmvlGWMhA== - dependencies: - "@juggle/resize-observer" "^3.3.1" - can-use-dom "^0.1.0" - core-js "^3.0.1" - lodash.debounce "^4.0.8" - lodash.memoize "^4.1.2" - lodash.throttle "^4.1.1" - -sortablejs@^1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.14.0.tgz#6d2e17ccbdb25f464734df621d4f35d4ab35b3d8" - integrity sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w== - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map-support@^0.5.16, source-map-support@~0.5.20: - 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== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -sourcemap-codec@1.4.8: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - -speakingurl@^14.0.1: - version "14.0.1" - resolved "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz" - integrity sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ== - -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-comments@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz" - integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - 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== - -style-loader@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" - integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -terser-webpack-plugin@^5.1.3: - version "5.3.0" - resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.0.tgz" - integrity sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ== - dependencies: - jest-worker "^27.4.1" - schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" - -terser-webpack-plugin@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" - integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== - dependencies: - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" - -terser@^5.7.2: - version "5.10.0" - resolved "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz" - integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== - dependencies: - commander "^2.20.0" - source-map "~0.7.2" - source-map-support "~0.5.20" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toastr@^2.1.4: - version "2.1.4" - resolved "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz" - integrity sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE= - dependencies: - jquery ">=1.12.0" - -tslib@^1.9.0: - version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -unicode-canonical-property-names-ecmascript@^2.0.0: - 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== - -unicode-match-property-ecmascript@^2.0.0: - 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== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" - integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz" - integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== - dependencies: - punycode "^2.1.0" - -util-deprecate@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -v8-compile-cache@^2.0.3: - version "2.2.0" - resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz" - integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== - -watchjs@0.0.0: - version "0.0.0" - resolved "https://registry.npmjs.org/watchjs/-/watchjs-0.0.0.tgz" - integrity sha1-4SCPJbMVuaKqaonogMnGic+6F1Y= - -watchpack@^2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz" - integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -webpack-cli@^4.9.2: - version "4.9.2" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.2.tgz#77c1adaea020c3f9e2db8aad8ea78d235c83659d" - integrity sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ== - dependencies: - "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^1.1.1" - "@webpack-cli/info" "^1.4.1" - "@webpack-cli/serve" "^1.6.1" - colorette "^2.0.14" - commander "^7.0.0" - execa "^5.0.0" - fastest-levenshtein "^1.0.12" - import-local "^3.0.2" - interpret "^2.2.0" - rechoir "^0.7.0" - webpack-merge "^5.7.3" - -webpack-merge@^5.7.3: - version "5.8.0" - resolved "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== - dependencies: - clone-deep "^4.0.1" - wildcard "^2.0.0" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.68.0: - version "5.68.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.68.0.tgz#a653a58ed44280062e47257f260117e4be90d560" - integrity sha512-zUcqaUO0772UuuW2bzaES2Zjlm/y3kRBQDVFVCge+s2Y8mwuUTdperGaAv65/NtRL/1zanpSJOq/MD8u61vo6g== - dependencies: - "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.50" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-better-errors "^1.0.2" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" - webpack-sources "^3.2.3" - -whatwg-fetch@^3.6.2: - version "3.6.2" - resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz" - integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - -wrappy@1: - version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==