From e9a3d038969e00d57efde811d9964865c46fa8a8 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 15 Sep 2023 10:42:01 +0200 Subject: [PATCH 01/49] Setup NestJS with nunjucks templates --- Makefile | 143 +++--------------- server/nest-cli.json | 8 +- server/package-lock.json | 126 +++++++++++---- server/package.json | 1 + .../Controller/HomeController.ts | 15 ++ server/src/app.module.ts | 4 + server/src/main.ts | 33 ++-- server/src/public/styles.css | 4 + server/src/templates/_base.njk | 16 ++ server/src/templates/home.njk | 5 + 10 files changed, 181 insertions(+), 174 deletions(-) create mode 100644 server/src/Infrastructure/Controller/HomeController.ts create mode 100644 server/src/public/styles.css create mode 100644 server/src/templates/_base.njk create mode 100644 server/src/templates/home.njk diff --git a/Makefile b/Makefile index 613dba3d..341e37fe 100644 --- a/Makefile +++ b/Makefile @@ -4,70 +4,23 @@ help: compose = docker-compose -p permacoop # See color codes here: http://jafrog.com/2013/11/23/colors-in-terminal.html -run_api = ./tools/colorize_prefix.sh [api] 30 -run_client_legacy = ./tools/colorize_prefix.sh [client:legacy] 31 -run_client_legacy_tailwind = ./tools/colorize_prefix.sh [client:legacy:tailwind] "38;5;52" -run_client_kit = ./tools/colorize_prefix.sh [client:kit] "38;5;202" -run_client_proxy = ./tools/colorize_prefix.sh [client:proxy] 32 - -client_proxy_port = 3001 -client_legacy_port = 3002 -client_kit_port = 3003 - -install: ## Install API and client - make install-api - make install-client +run = ./tools/colorize_prefix.sh [server] 30 + +install: ## Install + cp -n server/.env.dist server/.env + make install-deps ifneq ($(ANSIBLE),1) make install-dev endif -install-api: ## Install API - cp -n server/.env.dist server/.env +install-deps: ## Install dependencies cd server && npm ci -install-client: install-client-legacy install-client-kit install-client-proxy ## Install client - -install-client-legacy: ## Install legacy client - cp -n client/legacy/.env.dist client/legacy/.env - cd client/legacy && npm ci - -install-client-kit: ## Install SvelteKit client - cd client/kit && npm ci - -install-client-proxy: ## Install client proxy - cd client/proxy && npm ci - -install-client-e2e: ## Install E2E client dependencies - cd client/kit && npx playwright install firefox - -install-dev: ## Install local development dependencies and services - make up +install-dev: up ## Install local development dependencies and services make database-test-init -start: ## Start containers, API and client - make up - make -j 2 start-api start-client - -start-api: ## Run API - ${run_api} "cd server && npm run start:dev" - -start-client: ## Run client - make -j 3 start-client-legacy start-client-kit start-client-proxy - -start-client-legacy: ## Run legacy client - make -j 2 start-client-legacy-dev start-client-legacy-tailwind - -start-client-legacy-dev: - PORT=${client_legacy_port} ${run_client_legacy} "cd client/legacy && npm run dev" - -start-client-legacy-tailwind: - ${run_client_legacy_tailwind} "cd client/legacy && npm run watch:tailwind" - -start-client-kit: ## Run SvelteKit client - PORT=${client_kit_port} ${run_client_kit} "cd client/kit && npm run dev" - -start-client-proxy: ## Start client proxy - LEGACY_PORT=${client_legacy_port} KIT_PORT=${client_kit_port} PORT=${client_proxy_port} ${run_client_proxy} "cd client/proxy && npm run dev" +start: up ## Start + ${run} "cd server && npm run start:dev" compose: ## Run Docker compose command (args: CMD) ${compose} ${CMD} @@ -87,86 +40,27 @@ rm: stop ## Stop and remove containers ps: ## Show running containers make compose CMD=ps -build: build-api build-client ## Build API and client - -build-api: ## Build API dist +build: ## Build dist cd server && npm run build -build-client: build-client-legacy build-client-kit ## Build client - -build-client-legacy: ## Build legacy client - cd client/legacy && npm run build - -build-client-kit: ## Build SvelteKit client - cd client/kit && npm run build - -start-dist: ## Serve built API and client - make -j 2 start-dist-api start-dist-client +start-dist: ## Serve built server + ${run} "cd server && npm run start:prod" -start-dist-api: ## Serve built API - ${run_api} "cd server && npm run start:prod" - -start-dist-client: ## Serve built client - make -j 3 start-dist-client-legacy start-dist-client-kit start-client-proxy - -start-dist-client-legacy: ## Serve built legacy client - PORT=${client_legacy_port} ${run_client_legacy} "cd client/legacy && npm run start" - -start-dist-client-kit: ## Serve built client - HOST=127.0.0.1 PORT=${client_kit_port} ${run_client_kit} "cd client/kit && npm run start" - -test: test-api test-client-unit ## Run test suite - -test-api: ## Run API tests +test: ## Run tests cd server && npm run test -- $(FILE) -test-api-watch: ## Run API tests in watch mode +test-watch: ## Run tests in watch mode cd server && npm run test:watch -test-api-cov: ## Run API tests with coverage enabled +test-cov: ## Run tests with coverage enabled cd server && npm run test:cov -test-client: test-client-legacy-unit test-client-kit-unit ## Run client tests - -test-client-legacy-unit: ## Run legacy client unit tests - cd client/legacy && npm run test-unit - -test-client-kit-unit: ## Run SvelteKit client unit tests - cd client/kit && npm run test:coverage - -test-client-e2e: ## Run client E2E tests (servers must be running) - make database-seed - cd client/kit && npm run test-e2e - -test-client-ci: test-client test-client-e2e-ci - -test-client-e2e-ci: ## Run client E2E tests - make database-seed - cd client/kit && npm run test-e2e:ci - -linter: linter-api linter-client ## Run linters - -linter-api: ## Run API linters +linter: ## Run linters cd server && npm run lint -linter-client: linter-client-legacy linter-client-kit ## Run client linters - -linter-client-legacy: ## Run legacy client linters - cd client/legacy && npm run lint - -linter-client-kit: ## Run SvelteKit client linters - cd client/kit && npm run lint - -format: format-api format-client ## Run code formatting - -format-api: ## Run API code formatting +format: ## Run code formatting cd server && npm run format -format-client: format-client-kit ## Run client code formatting - -format-client-kit: ## Run SvelteKit client code formatting - cd client/kit && npm run format - database-migrate: ## Database migrations cd server && npm run migration:migrate @@ -176,6 +70,7 @@ database-test-init: ## Initialize test database database-migration: ## Generate a database migration cd server && npm run migration:generate -- migrations/$(NAME) + database-seed: ## Seed database cd server && npm run build && npm run seed:run @@ -185,10 +80,8 @@ database-connect: ## Connect to the database container ci: ## Run CI checks make compose CMD="up -d" make install - make install-client-e2e make build make database-migrate make test-api-cov make database-test-init - make test-client-ci make linter diff --git a/server/nest-cli.json b/server/nest-cli.json index 56167b36..42b307e8 100644 --- a/server/nest-cli.json +++ b/server/nest-cli.json @@ -1,4 +1,10 @@ { "collection": "@nestjs/schematics", - "sourceRoot": "src" + "sourceRoot": "src", + "compilerOptions": { + "assets": [ + {"include": "templates/*", "watchAssets": true}, + {"include": "public/*", "watchAssets": true} + ] + } } diff --git a/server/package-lock.json b/server/package-lock.json index b2008eac..d1a92b58 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -26,6 +26,7 @@ "date-fns": "^2.8.1", "helmet": "^3.22.0", "lodash": ">=4.17.19", + "nunjucks": "^3.2.4", "passport-http-bearer": "^1.0.1", "pg": "^8.2.1", "reflect-metadata": "^0.1.13", @@ -3071,6 +3072,11 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -3247,7 +3253,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, + "devOptional": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3359,6 +3365,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3484,7 +3495,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } @@ -3576,7 +3587,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, + "devOptional": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -3773,7 +3784,7 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, + "devOptional": true, "funding": [ { "type": "individual", @@ -5498,7 +5509,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, + "devOptional": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5802,7 +5813,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, + "devOptional": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -6239,7 +6250,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, + "devOptional": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -6302,7 +6313,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -6331,7 +6342,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, + "devOptional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -6363,7 +6374,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.12.0" } @@ -8388,7 +8399,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -8447,6 +8458,38 @@ "node": ">=0.10.0" } }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/nunjucks/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -8950,7 +8993,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8.6" }, @@ -9276,7 +9319,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, + "devOptional": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -10305,7 +10348,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, + "devOptional": true, "dependencies": { "is-number": "^7.0.0" }, @@ -13682,6 +13725,11 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -13808,7 +13856,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, + "devOptional": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -13895,6 +13943,11 @@ "es-abstract": "^1.18.0-next.1" } }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -13985,7 +14038,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true + "devOptional": true }, "bl": { "version": "4.1.0", @@ -14055,7 +14108,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, + "devOptional": true, "requires": { "fill-range": "^7.0.1" } @@ -14179,7 +14232,7 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, + "devOptional": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -15475,7 +15528,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, + "devOptional": true, "requires": { "to-regex-range": "^5.0.1" } @@ -15705,7 +15758,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, + "devOptional": true, "requires": { "is-glob": "^4.0.1" } @@ -16027,7 +16080,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, + "devOptional": true, "requires": { "binary-extensions": "^2.0.0" } @@ -16066,7 +16119,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "devOptional": true }, "is-fullwidth-code-point": { "version": "1.0.0", @@ -16086,7 +16139,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, + "devOptional": true, "requires": { "is-extglob": "^2.1.1" } @@ -16106,7 +16159,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "devOptional": true }, "is-number-object": { "version": "1.0.4", @@ -17663,7 +17716,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "devOptional": true }, "npm-bundled": { "version": "1.1.1", @@ -17713,6 +17766,23 @@ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, + "nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "requires": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + } + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -18081,7 +18151,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", - "dev": true + "devOptional": true }, "pify": { "version": "2.3.0", @@ -18320,7 +18390,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, + "devOptional": true, "requires": { "picomatch": "^2.2.1" } @@ -19105,7 +19175,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, + "devOptional": true, "requires": { "is-number": "^7.0.0" } diff --git a/server/package.json b/server/package.json index 9d3b72e7..8e8a3dd5 100644 --- a/server/package.json +++ b/server/package.json @@ -42,6 +42,7 @@ "date-fns": "^2.8.1", "helmet": "^3.22.0", "lodash": ">=4.17.19", + "nunjucks": "^3.2.4", "passport-http-bearer": "^1.0.1", "pg": "^8.2.1", "reflect-metadata": "^0.1.13", diff --git a/server/src/Infrastructure/Controller/HomeController.ts b/server/src/Infrastructure/Controller/HomeController.ts new file mode 100644 index 00000000..915da6a0 --- /dev/null +++ b/server/src/Infrastructure/Controller/HomeController.ts @@ -0,0 +1,15 @@ +import { + Controller, + Get, + Render +} from '@nestjs/common'; + +@Controller('') +export class HomeController { + + @Get() + @Render('home') + public root() { + return { who: 'world' }; + } +} diff --git a/server/src/app.module.ts b/server/src/app.module.ts index abb312e2..1bd696e1 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -10,8 +10,12 @@ import { HumanResourceModule } from './Infrastructure/HumanResource/humanResourc import { SettingsModule } from './Infrastructure/Settings/settings.module'; import { dataSourceOptions } from './datasource'; +import { HomeController } from './Infrastructure/Controller/HomeController'; @Module({ + controllers: [ + HomeController, + ], imports: [ TypeOrmModule.forRoot(dataSourceOptions), ConfigModule.forRoot(), diff --git a/server/src/main.ts b/server/src/main.ts index 5db330b0..98886663 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -1,32 +1,25 @@ +import * as path from 'path'; import { NestFactory } from '@nestjs/core'; -import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { ValidationPipe } from '@nestjs/common'; import * as helmet from 'helmet'; +import * as nunjucks from 'nunjucks'; import { AppModule } from './app.module'; +import { NestExpressApplication } from '@nestjs/platform-express'; async function bootstrap() { - const app = await NestFactory.create(AppModule); + const app = await NestFactory.create(AppModule); + const express = app.getHttpAdapter().getInstance(); + app.use(helmet()); - app.enableCors(); - app.setGlobalPrefix('api'); app.useGlobalPipes(new ValidationPipe({ transform: true })); - const options = new DocumentBuilder() - .setTitle('Permacoop') - .setDescription( - 'PermaCoop is an eco-design and open-source ERP solution for cooperatives.' - ) - .setVersion('1.0.0') - .addBearerAuth() - .addSecurity('calendar_token', { - type: 'apiKey', - name: 'token', - in: 'query' - }) - .build(); - - const document = SwaggerModule.createDocument(app, options); - SwaggerModule.setup('api', app, document); + const assetsDir = path.join(__dirname, '..', 'public'); + app.useStaticAssets(assetsDir, { prefix: '/public' }); + + const viewsDir = path.join(__dirname, '..', 'templates'); + nunjucks.configure(viewsDir, { express }); + app.setBaseViewsDir(viewsDir); + app.setViewEngine('njk'); await app.listen(3000, '0.0.0.0'); } diff --git a/server/src/public/styles.css b/server/src/public/styles.css new file mode 100644 index 00000000..544441d9 --- /dev/null +++ b/server/src/public/styles.css @@ -0,0 +1,4 @@ +p { + color: red; +} + diff --git a/server/src/templates/_base.njk b/server/src/templates/_base.njk new file mode 100644 index 00000000..fca12a40 --- /dev/null +++ b/server/src/templates/_base.njk @@ -0,0 +1,16 @@ + + + + + + + + + + {% block body %} +
+ {% block main %}{% endblock main %} +
+ {% endblock body %} + + diff --git a/server/src/templates/home.njk b/server/src/templates/home.njk new file mode 100644 index 00000000..c4e68058 --- /dev/null +++ b/server/src/templates/home.njk @@ -0,0 +1,5 @@ +{% extends '_base.njk' %} + +{% block main %} +

Hello, {{ who }}!

+{% endblock main %} From 157d59934db76b70484e1d0c93fb9a224a0fe5c6 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 15 Sep 2023 14:04:12 +0200 Subject: [PATCH 02/49] Add login page --- Makefile | 7 +- server/nest-cli.json | 7 +- server/package-lock.json | 794 ++++++++---------- .../Controller/HomeController.ts | 15 - .../User/Controller/LoginController.ts | 17 + .../HumanResource/humanResource.module.ts | 2 + server/src/app.module.ts | 4 - server/src/main.ts | 2 +- .../images/icons/android-icon-144x144.png | Bin 0 -> 9773 bytes .../images/icons/android-icon-192x192.png | Bin 0 -> 13736 bytes .../images/icons/android-icon-36x36.png | Bin 0 -> 2108 bytes .../images/icons/android-icon-48x48.png | Bin 0 -> 2721 bytes .../images/icons/android-icon-72x72.png | Bin 0 -> 4010 bytes .../images/icons/android-icon-96x96.png | Bin 0 -> 5712 bytes server/src/public/images/icons/favicon.ico | Bin 0 -> 1150 bytes server/src/public/images/login-office.jpeg | Bin 0 -> 20627 bytes server/src/public/images/logo.png | Bin 0 -> 4743 bytes server/src/public/styles.css | 177 +++- server/src/templates/_base.njk | 3 +- server/src/templates/home.njk | 5 - server/src/templates/login.njk | 29 + 21 files changed, 594 insertions(+), 468 deletions(-) delete mode 100644 server/src/Infrastructure/Controller/HomeController.ts create mode 100644 server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts create mode 100644 server/src/public/images/icons/android-icon-144x144.png create mode 100644 server/src/public/images/icons/android-icon-192x192.png create mode 100644 server/src/public/images/icons/android-icon-36x36.png create mode 100644 server/src/public/images/icons/android-icon-48x48.png create mode 100644 server/src/public/images/icons/android-icon-72x72.png create mode 100644 server/src/public/images/icons/android-icon-96x96.png create mode 100644 server/src/public/images/icons/favicon.ico create mode 100644 server/src/public/images/login-office.jpeg create mode 100644 server/src/public/images/logo.png delete mode 100644 server/src/templates/home.njk create mode 100644 server/src/templates/login.njk diff --git a/Makefile b/Makefile index 341e37fe..eb6638a3 100644 --- a/Makefile +++ b/Makefile @@ -3,9 +3,6 @@ help: compose = docker-compose -p permacoop -# See color codes here: http://jafrog.com/2013/11/23/colors-in-terminal.html -run = ./tools/colorize_prefix.sh [server] 30 - install: ## Install cp -n server/.env.dist server/.env make install-deps @@ -20,7 +17,7 @@ install-dev: up ## Install local development dependencies and services make database-test-init start: up ## Start - ${run} "cd server && npm run start:dev" + cd server && npm run start:dev compose: ## Run Docker compose command (args: CMD) ${compose} ${CMD} @@ -44,7 +41,7 @@ build: ## Build dist cd server && npm run build start-dist: ## Serve built server - ${run} "cd server && npm run start:prod" + cd server && npm run start:prod test: ## Run tests cd server && npm run test -- $(FILE) diff --git a/server/nest-cli.json b/server/nest-cli.json index 42b307e8..c6fc0b1e 100644 --- a/server/nest-cli.json +++ b/server/nest-cli.json @@ -2,9 +2,8 @@ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { - "assets": [ - {"include": "templates/*", "watchAssets": true}, - {"include": "public/*", "watchAssets": true} - ] + "assets": ["templates/**/*", "public/**/*"], + "watchAssets": true, + "manualRestart": true } } diff --git a/server/package-lock.json b/server/package-lock.json index d1a92b58..9df4e565 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -92,19 +92,19 @@ } }, "node_modules/@angular-devkit/core": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.2.4.tgz", - "integrity": "sha512-yl+0j1bMwJLKShsyCXw77tbJG8Sd21+itisPLL2MgEpLNAO252kr9zG4TLlFRJyKVftm2l1h78KjqvM5nbOXNg==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.0.1.tgz", + "integrity": "sha512-2uz98IqkKJlgnHbWQ7VeL4pb+snGAZXIama2KXi+k9GsRntdcw+udX8rL3G9SdUGUF+m6+147Y1oRBMHsO/v4w==", "dev": true, "dependencies": { "ajv": "8.12.0", "ajv-formats": "2.1.1", "jsonc-parser": "3.2.0", - "rxjs": "6.6.7", + "rxjs": "7.8.1", "source-map": "0.7.4" }, "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "node": "^16.14.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, @@ -139,50 +139,32 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/@angular-devkit/core/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@angular-devkit/core/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/@angular-devkit/schematics": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-15.2.4.tgz", - "integrity": "sha512-/W7/vvn59PAVLzhcvD4/N/E8RDhub8ny1A7I96LTRjC5o+yvVV16YJ4YJzolrRrIEN01KmLVQJ9A58VCaweMgw==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.0.1.tgz", + "integrity": "sha512-A9D0LTYmiqiBa90GKcSuWb7hUouGIbm/AHbJbjL85WLLRbQA2PwKl7P5Mpd6nS/ZC0kfG4VQY3VOaDvb3qpI9g==", "dev": true, "dependencies": { - "@angular-devkit/core": "15.2.4", + "@angular-devkit/core": "16.0.1", "jsonc-parser": "3.2.0", - "magic-string": "0.29.0", + "magic-string": "0.30.0", "ora": "5.4.1", - "rxjs": "6.6.7" + "rxjs": "7.8.1" }, "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "node": "^16.14.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } }, "node_modules/@angular-devkit/schematics-cli": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-15.2.4.tgz", - "integrity": "sha512-QTTKEH5HOkxvQtCxb2Lna2wubehkaIzA6DKUBISijPQliLomw74tzc7lXCywmMqRTbQPVRLG3kBK97hR4x67nA==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.0.1.tgz", + "integrity": "sha512-6KLA125dpgd6oJGtiO2JpZAb92uOG3njQGIt7NFcuQGW/5GO7J41vMXH9cBAfdtbV8SIggSmR/cIEE9ijfj6YQ==", "dev": true, "dependencies": { - "@angular-devkit/core": "15.2.4", - "@angular-devkit/schematics": "15.2.4", + "@angular-devkit/core": "16.0.1", + "@angular-devkit/schematics": "16.0.1", "ansi-colors": "4.1.3", "inquirer": "8.2.4", "symbol-observable": "4.0.0", @@ -192,7 +174,7 @@ "schematics": "bin/schematics.js" }, "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "node": "^16.14.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } @@ -276,24 +258,6 @@ "node": ">=12" } }, - "node_modules/@angular-devkit/schematics/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -1695,9 +1659,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", @@ -1721,14 +1685,14 @@ } }, "node_modules/@nestjs/cli": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.3.0.tgz", - "integrity": "sha512-v/E8Y3zFk30+FljETvPgpoGIUiOfWuOe6WUFw3ExGfDeWrF/A8ceupDHPWNknBAqvNtz2kVrWu5mwsZUEKGIgg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.5.0.tgz", + "integrity": "sha512-Z7q+3vNsQSG2d2r2Hl/OOj5EpfjVx3OfnJ9+KuAsOdw1sKLm7+Zc6KbhMFTd/eIvfx82ww3Nk72xdmfPYCulWA==", "dev": true, "dependencies": { - "@angular-devkit/core": "15.2.4", - "@angular-devkit/schematics": "15.2.4", - "@angular-devkit/schematics-cli": "15.2.4", + "@angular-devkit/core": "16.0.1", + "@angular-devkit/schematics": "16.0.1", + "@angular-devkit/schematics-cli": "16.0.1", "@nestjs/schematics": "^9.0.4", "chalk": "4.1.2", "chokidar": "3.5.3", @@ -1739,14 +1703,14 @@ "node-emoji": "1.11.0", "ora": "5.4.1", "os-name": "4.0.1", - "rimraf": "4.4.0", + "rimraf": "4.4.1", "shelljs": "0.8.5", "source-map-support": "0.5.21", "tree-kill": "1.2.2", - "tsconfig-paths": "4.1.2", + "tsconfig-paths": "4.2.0", "tsconfig-paths-webpack-plugin": "4.0.1", "typescript": "4.9.5", - "webpack": "5.76.2", + "webpack": "5.82.1", "webpack-node-externals": "3.0.0" }, "bin": { @@ -1766,13 +1730,13 @@ } }, "node_modules/@nestjs/cli/node_modules/glob": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.0.tgz", - "integrity": "sha512-EAZejC7JvnQINayvB/7BJbpZpNOJ8Lrw2OZNEvQxe0vaLn1SuwMcfV7/MNaX8L/T0wmptBFI4YMtDvSBxYDc7w==", + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", - "minimatch": "^7.4.1", + "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" }, @@ -1784,33 +1748,33 @@ } }, "node_modules/@nestjs/cli/node_modules/minimatch": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", - "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@nestjs/cli/node_modules/minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/@nestjs/cli/node_modules/rimraf": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.0.tgz", - "integrity": "sha512-X36S+qpCUR0HjXlkDe4NAOhS//aHH0Z+h8Ckf2auGJk3PTnx5rLmrHkwNdbVQuCSUhOyFrlRvFEllZOYE+yZGQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", + "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", "dev": true, "dependencies": { "glob": "^9.2.0" @@ -1826,9 +1790,9 @@ } }, "node_modules/@nestjs/cli/node_modules/tsconfig-paths": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz", - "integrity": "sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "dependencies": { "json5": "^2.2.2", @@ -2427,9 +2391,9 @@ } }, "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", "dev": true }, "node_modules/@types/express": { @@ -2915,148 +2879,148 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "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==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "dev": true }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { - "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==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dev": true, "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/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dev": true, "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/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dev": true, "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/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dev": true, "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/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dev": true, "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/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, @@ -3095,9 +3059,9 @@ } }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "devOptional": true, "bin": { "acorn": "bin/acorn" @@ -4497,12 +4461,12 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.11.0.tgz", - "integrity": "sha512-0Gcraf7gAJSQoPg+bTSXNhuzAYtXqLc4C011vb8S3B8XUSEkGYNBk20c68X9291VF4vvsCD8SPkr6Mza+DwU+g==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.4", "tapable": "^2.2.0" }, "engines": { @@ -4561,9 +4525,9 @@ } }, "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", + "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", "dev": true }, "node_modules/es-to-primitive": { @@ -7976,9 +7940,9 @@ } }, "node_modules/magic-string": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.29.0.tgz", - "integrity": "sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==", + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.13" @@ -8856,37 +8820,37 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.1.tgz", - "integrity": "sha512-OW+5s+7cw6253Q4E+8qQ/u1fVvcJQCJo/VFD8pje+dbJCF1n5ZRMV2AEHbGp+5Q7jxQIYJxkHopnj6nzdGeZLA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dev": true, "dependencies": { - "lru-cache": "^7.14.1", - "minipass": "^4.0.2" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=14" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", "dev": true, "engines": { - "node": ">=12" + "node": "14 || >=16.14" } }, "node_modules/path-scurry/node_modules/minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/path-to-regexp": { @@ -9502,9 +9466,9 @@ } }, "node_modules/rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dependencies": { "tslib": "^2.1.0" } @@ -9525,9 +9489,9 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", @@ -9579,9 +9543,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dev": true, "dependencies": { "randombytes": "^2.1.0" @@ -10215,13 +10179,13 @@ } }, "node_modules/terser": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", - "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", + "version": "5.19.4", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.4.tgz", + "integrity": "sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g==", "dev": true, "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -10233,16 +10197,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" }, "engines": { "node": ">= 10.13.0" @@ -11087,22 +11051,22 @@ } }, "node_modules/webpack": { - "version": "5.76.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.2.tgz", - "integrity": "sha512-Th05ggRm23rVzEOlX8y67NkYCHa9nTNcwHPBhdg+lKG+mtiW7XgggjAeeLnADAe7mLjJ6LUNfgHAuRRh+Z6J7w==", + "version": "5.82.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", + "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", + "enhanced-resolve": "^5.14.0", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -11111,9 +11075,9 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.1.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", + "terser-webpack-plugin": "^5.3.7", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, @@ -11438,15 +11402,15 @@ } }, "@angular-devkit/core": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.2.4.tgz", - "integrity": "sha512-yl+0j1bMwJLKShsyCXw77tbJG8Sd21+itisPLL2MgEpLNAO252kr9zG4TLlFRJyKVftm2l1h78KjqvM5nbOXNg==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.0.1.tgz", + "integrity": "sha512-2uz98IqkKJlgnHbWQ7VeL4pb+snGAZXIama2KXi+k9GsRntdcw+udX8rL3G9SdUGUF+m6+147Y1oRBMHsO/v4w==", "dev": true, "requires": { "ajv": "8.12.0", "ajv-formats": "2.1.1", "jsonc-parser": "3.2.0", - "rxjs": "6.6.7", + "rxjs": "7.8.1", "source-map": "0.7.4" }, "dependencies": { @@ -11467,62 +11431,30 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true } } }, "@angular-devkit/schematics": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-15.2.4.tgz", - "integrity": "sha512-/W7/vvn59PAVLzhcvD4/N/E8RDhub8ny1A7I96LTRjC5o+yvVV16YJ4YJzolrRrIEN01KmLVQJ9A58VCaweMgw==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.0.1.tgz", + "integrity": "sha512-A9D0LTYmiqiBa90GKcSuWb7hUouGIbm/AHbJbjL85WLLRbQA2PwKl7P5Mpd6nS/ZC0kfG4VQY3VOaDvb3qpI9g==", "dev": true, "requires": { - "@angular-devkit/core": "15.2.4", + "@angular-devkit/core": "16.0.1", "jsonc-parser": "3.2.0", - "magic-string": "0.29.0", + "magic-string": "0.30.0", "ora": "5.4.1", - "rxjs": "6.6.7" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } + "rxjs": "7.8.1" } }, "@angular-devkit/schematics-cli": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-15.2.4.tgz", - "integrity": "sha512-QTTKEH5HOkxvQtCxb2Lna2wubehkaIzA6DKUBISijPQliLomw74tzc7lXCywmMqRTbQPVRLG3kBK97hR4x67nA==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.0.1.tgz", + "integrity": "sha512-6KLA125dpgd6oJGtiO2JpZAb92uOG3njQGIt7NFcuQGW/5GO7J41vMXH9cBAfdtbV8SIggSmR/cIEE9ijfj6YQ==", "dev": true, "requires": { - "@angular-devkit/core": "15.2.4", - "@angular-devkit/schematics": "15.2.4", + "@angular-devkit/core": "16.0.1", + "@angular-devkit/schematics": "16.0.1", "ansi-colors": "4.1.3", "inquirer": "8.2.4", "symbol-observable": "4.0.0", @@ -12649,9 +12581,9 @@ "dev": true }, "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.3.0", @@ -12675,14 +12607,14 @@ } }, "@nestjs/cli": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.3.0.tgz", - "integrity": "sha512-v/E8Y3zFk30+FljETvPgpoGIUiOfWuOe6WUFw3ExGfDeWrF/A8ceupDHPWNknBAqvNtz2kVrWu5mwsZUEKGIgg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.5.0.tgz", + "integrity": "sha512-Z7q+3vNsQSG2d2r2Hl/OOj5EpfjVx3OfnJ9+KuAsOdw1sKLm7+Zc6KbhMFTd/eIvfx82ww3Nk72xdmfPYCulWA==", "dev": true, "requires": { - "@angular-devkit/core": "15.2.4", - "@angular-devkit/schematics": "15.2.4", - "@angular-devkit/schematics-cli": "15.2.4", + "@angular-devkit/core": "16.0.1", + "@angular-devkit/schematics": "16.0.1", + "@angular-devkit/schematics-cli": "16.0.1", "@nestjs/schematics": "^9.0.4", "chalk": "4.1.2", "chokidar": "3.5.3", @@ -12693,14 +12625,14 @@ "node-emoji": "1.11.0", "ora": "5.4.1", "os-name": "4.0.1", - "rimraf": "4.4.0", + "rimraf": "4.4.1", "shelljs": "0.8.5", "source-map-support": "0.5.21", "tree-kill": "1.2.2", - "tsconfig-paths": "4.1.2", + "tsconfig-paths": "4.2.0", "tsconfig-paths-webpack-plugin": "4.0.1", "typescript": "4.9.5", - "webpack": "5.76.2", + "webpack": "5.82.1", "webpack-node-externals": "3.0.0" }, "dependencies": { @@ -12714,45 +12646,45 @@ } }, "glob": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.0.tgz", - "integrity": "sha512-EAZejC7JvnQINayvB/7BJbpZpNOJ8Lrw2OZNEvQxe0vaLn1SuwMcfV7/MNaX8L/T0wmptBFI4YMtDvSBxYDc7w==", + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", - "minimatch": "^7.4.1", + "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "minimatch": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", - "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } }, "minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", "dev": true }, "rimraf": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.0.tgz", - "integrity": "sha512-X36S+qpCUR0HjXlkDe4NAOhS//aHH0Z+h8Ckf2auGJk3PTnx5rLmrHkwNdbVQuCSUhOyFrlRvFEllZOYE+yZGQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", + "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", "dev": true, "requires": { "glob": "^9.2.0" } }, "tsconfig-paths": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz", - "integrity": "sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "requires": { "json5": "^2.2.2", @@ -13184,9 +13116,9 @@ } }, "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", "dev": true }, "@types/express": { @@ -13568,148 +13500,148 @@ } }, "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dev": true, "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "@webassemblyjs/floating-point-hex-parser": { - "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==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", "dev": true }, "@webassemblyjs/helper-numbers": { - "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==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dev": true, "requires": { - "@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/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dev": true, "requires": { - "@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/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dev": true, "requires": { - "@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/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dev": true, "requires": { - "@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/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, @@ -13745,9 +13677,9 @@ } }, "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "devOptional": true }, "acorn-import-assertions": { @@ -14757,12 +14689,12 @@ } }, "enhanced-resolve": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.11.0.tgz", - "integrity": "sha512-0Gcraf7gAJSQoPg+bTSXNhuzAYtXqLc4C011vb8S3B8XUSEkGYNBk20c68X9291VF4vvsCD8SPkr6Mza+DwU+g==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, "requires": { - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, @@ -14809,9 +14741,9 @@ } }, "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", + "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", "dev": true }, "es-to-primitive": { @@ -17369,9 +17301,9 @@ "dev": true }, "magic-string": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.29.0.tgz", - "integrity": "sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==", + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", "dev": true, "requires": { "@jridgewell/sourcemap-codec": "^1.4.13" @@ -18046,25 +17978,25 @@ "dev": true }, "path-scurry": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.1.tgz", - "integrity": "sha512-OW+5s+7cw6253Q4E+8qQ/u1fVvcJQCJo/VFD8pje+dbJCF1n5ZRMV2AEHbGp+5Q7jxQIYJxkHopnj6nzdGeZLA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dev": true, "requires": { - "lru-cache": "^7.14.1", - "minipass": "^4.0.2" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "dependencies": { "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", "dev": true }, "minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", "dev": true } } @@ -18509,9 +18441,9 @@ } }, "rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "requires": { "tslib": "^2.1.0" } @@ -18532,9 +18464,9 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "requires": { "@types/json-schema": "^7.0.8", @@ -18575,9 +18507,9 @@ } }, "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -19079,13 +19011,13 @@ } }, "terser": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", - "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", + "version": "5.19.4", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.4.tgz", + "integrity": "sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g==", "dev": true, "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -19099,16 +19031,16 @@ } }, "terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" } }, "test-exclude": { @@ -19639,22 +19571,22 @@ } }, "webpack": { - "version": "5.76.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.2.tgz", - "integrity": "sha512-Th05ggRm23rVzEOlX8y67NkYCHa9nTNcwHPBhdg+lKG+mtiW7XgggjAeeLnADAe7mLjJ6LUNfgHAuRRh+Z6J7w==", + "version": "5.82.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", + "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", + "enhanced-resolve": "^5.14.0", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -19663,9 +19595,9 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.1.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", + "terser-webpack-plugin": "^5.3.7", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" } diff --git a/server/src/Infrastructure/Controller/HomeController.ts b/server/src/Infrastructure/Controller/HomeController.ts deleted file mode 100644 index 915da6a0..00000000 --- a/server/src/Infrastructure/Controller/HomeController.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { - Controller, - Get, - Render -} from '@nestjs/common'; - -@Controller('') -export class HomeController { - - @Get() - @Render('home') - public root() { - return { who: 'world' }; - } -} diff --git a/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts b/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts new file mode 100644 index 00000000..ba17f7af --- /dev/null +++ b/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts @@ -0,0 +1,17 @@ +import { Controller, Get, Post, Render, Req } from '@nestjs/common'; +import { Request } from 'express'; + +@Controller('') +export class LoginController { + @Get() + @Render('login') + public get() { + return {}; + } + + @Post() + @Render('login') + public async post(@Req() req: Request) { + return {}; + } +} diff --git a/server/src/Infrastructure/HumanResource/humanResource.module.ts b/server/src/Infrastructure/HumanResource/humanResource.module.ts index 2df256f6..175829e9 100644 --- a/server/src/Infrastructure/HumanResource/humanResource.module.ts +++ b/server/src/Infrastructure/HumanResource/humanResource.module.ts @@ -5,6 +5,7 @@ import { PassportModule } from '@nestjs/passport'; import { BusModule } from '../bus.module'; import { User } from 'src/Domain/HumanResource/User/User.entity'; import { File } from 'src/Domain/File/File.entity'; +import { LoginController } from './User/Controller/LoginController'; import { LoginAction } from './User/Action/LoginAction'; import { CreateUserAction } from './User/Action/CreateUserAction'; import { GetMeAction } from './User/Action/GetMeAction'; @@ -97,6 +98,7 @@ import { GetPendingLeaveRequestsCountQueryHandler } from 'src/Application/HumanR ]) ], controllers: [ + LoginController, LoginAction, CreateUserAction, GetLeavesAction, diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 1bd696e1..abb312e2 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -10,12 +10,8 @@ import { HumanResourceModule } from './Infrastructure/HumanResource/humanResourc import { SettingsModule } from './Infrastructure/Settings/settings.module'; import { dataSourceOptions } from './datasource'; -import { HomeController } from './Infrastructure/Controller/HomeController'; @Module({ - controllers: [ - HomeController, - ], imports: [ TypeOrmModule.forRoot(dataSourceOptions), ConfigModule.forRoot(), diff --git a/server/src/main.ts b/server/src/main.ts index 98886663..723118ce 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -15,7 +15,7 @@ async function bootstrap() { const assetsDir = path.join(__dirname, '..', 'public'); app.useStaticAssets(assetsDir, { prefix: '/public' }); - + const viewsDir = path.join(__dirname, '..', 'templates'); nunjucks.configure(viewsDir, { express }); app.setBaseViewsDir(viewsDir); diff --git a/server/src/public/images/icons/android-icon-144x144.png b/server/src/public/images/icons/android-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..2cf1be22811ffd3819be1b017386869e700d7ae6 GIT binary patch literal 9773 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 literal 0 HcmV?d00001 diff --git a/server/src/public/images/icons/android-icon-36x36.png b/server/src/public/images/icons/android-icon-36x36.png new file mode 100644 index 0000000000000000000000000000000000000000..f6afdb92cfa8c7bcbd705ea2184c0ad7c9e06bb7 GIT binary patch literal 2108 zcmZ{m3pAAL8ppqKiFP)}B{IaMlrR@&%oq$akzt~7r!Wn3%`nUiBH7p`mpXLhRxUMZ z*w)lk+95(*O{U0Dzez0DuDp^kd7Ld>p}sY6RKc6Q@goR3!_Mtrrg0Hn^?S&=yPoP^Ab;W~R&UDn zuPrG#@Kr@Ec9U(JVzsrc^NEb&Y0;{5G>_c-yZVfwEz~*HD@9*m&<;a|bscv=<1GfW z4RFPU%jkQ8VQjvuyFqb@fj?AbrJ4JAzbt#wGaO$r#ouv&?74a#E{_r4_f5$xVfr3W zJ+Ve5iUP|ToY&t)S`el~I#^~wFiQ)9I?Ofu8x=(K&pGgxpV2 z0raQgweLnH5BV)(Q1p&_(Vj-?#@dsh$7Qe(}7OyrU0qDH#vPau#8-*eDL69l48@r-m3CYS;Mgg z3iQSG;M}YvJj85l4!*b@de~ETjTdXy*3m&PklOkkP*!UHcw$GWWV!C;+n0xOsx1{A z-1CyHaDlK*<>kz6WL*-ke1exgJ6Y?YlKFw##?Q@W{lW*%adr;5zPK0G-NSA@xU z#fqNsotkbLcf%vOw_$U7pIdOwogMV?^zaee!!4`Pd7WqDHa4}ovww+nkH0VfAhMcB zuWC2$Q-*u*4yiqy5`5*04!`Jr(a-178ni-u3qF5X;m2fLkHgwW*DlZU)9W2?SE-p! zU=YT`kPnPP*nDU&(IT@z*dVPp&P{+waLq$?wo@v(sn48JV~@@ zSW2b`^*g<1i(zVddGHF(xHZ`%266O-S--+ZFxTI0M+@` zqEKD=*yNLKtBp;MM?aUTiJyjCP1n-BYIm*NzQ<4J98K?KH#GnB-e^eJ-KczgZq-1z zzP3~R$df;-xUZD@hTzqe)p)O@Kz2V$(Lb{pKwi)cQ`;MTs_sw4xjYS0{ve&2{xRs> zyo}OmHZ1?BnOLk~OI>hUL@2wlK%z*>ucn(QTJdkuDx&EpbC;ggH{u*R{f0S4lDgkv&;$n~l=AZROi!!4o+9K9Lrf?e)oGj_tpW3{aPpXG> z$KMW<+H751dU!f7%P@b}I|cjOPs*`S{3)sfo`Bw+~CZmb<$3+2q?8+z+R-fkRvSD6NO@~pvkf0taX)MQg z1S3{lc0icFLOw{Z3>>w3sO{+B)P4*hET!nn3f>y3tj4cxP3`HNT--QJDHwz4e7hc6 zaxlTJF?9~sKeosDf_*oazIf(&BvsdXc*5>d2_5RaaoKqDg9UE$)29L>~sp^l1RF-4OuT2&& zPrFc^jVAdu#qZ?LY<#Gtv(VG_5ru* zyD-nugFQQt)Xc2?HSET%)FMo5(VG-hH_?jh0$Jfgaw+=H>$_?ksDkF!9P=&3+N==I z-Z4l9Nqz8iU3nFlZz~!_tZgBAP$w_;HdM0D?#? zyoCP1^9XZOb(X;em*=pM#$x{;7nQqCz2N75mP?dvk literal 0 HcmV?d00001 diff --git a/server/src/public/images/icons/android-icon-48x48.png b/server/src/public/images/icons/android-icon-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..2b402dad7f06b811a5dc0110060551cb29cfa6cd GIT binary patch literal 2721 zcmZ{mc{J4f8^^!aELkIRZQ~mIG8l$QmbrEYSrcI}!(xf{`sWZTAOllh;RS^z-4Y` zWCwcKcVlA(cW1`0w?N12Ylt=kfYv*l-!Lp-%s{j=MFGuJ(KRrT^ft3Y13lyqtwX+}fUnzO`)ze~KJMdzF&FC4bKS%EVxdrM%uR^w3HoTB2)wIy)W$?ci_x7VDF<=#%VwxvzvksQU2q zxWXx06CI>d^B69URj4LDyLX56m^v_HV!(K&9!~i+w_8JE*+^~((K&N&CuU3`o!Dr$ z%1Tge3Xamfjppl~o*XJP@oEM9+DStDl{^GBe^r<95-HS;u2nQDsed{zfD%bCe4 zYnGgNbmb^*#!=%2^|W`r+s$Rp091=6svX^9@Z?jVWtQ1+4m-Wpd`_v1D%6blx3{6iwa|#f9+NZEf?*>l;1C>TVg?fz5GKM>?Wq zG&$q6{MQJt!dyfBIuyfjRUse%Sq(iuezm1^ZiQh?U;`p8AMKf2E+{?7=w5dERD=7f z^(ECnRJ>FBso^gS0?elCad70myJb^_bW+2(K`Gi>o&vR(TX1p=xV_L7cPw$VUky*P z*gzXcDhaPlRabY1(#}xfn%?&0FTGmD#%zYSW{o?h>|OaD@U?6woTa2mi0KSJkm7Ss zOPAVqUL480B&X!F_xY&1JNC2Ww#a6y#d>`0rK#sAts7S^9xhheR9fb?bNx{}{<3Ic zuE=%eP8+cxKXa+3kXtLQpejXK{c$U7us^2H?0Mt+o%aEU0W$;TwTt8M?xIAm%9Q)} zdmg?cM|vt}SS0oL?$sK0W_ffpF`GC!7g*OJN+g+Y>_SP^o*BSjxMB)_{Q8@F3KknF zK}Fs4U1b?N`O82gQ&qU!*EeYO@8Y0p z1ZT2WeuF^&W&2FPfyPjC_%GZv^JC5SWZBMBNm+nH|B-UFlyrmK1(ti00o<=Et=J}& zIOV;Lakhf4TaKDckJRPvGdU)Yy|ZL;jOT3+&@Y%RBS%+oQ05N|Qp2upGC-h1VjS<| z`2J8=y3cPb=+e*rK!AU!m_?wKiJ|W5VB`A&Gv!OjZTY6u$i3)x<@$D!Vc)h`a>~S7 zNS?08RJF5}Uqa5>Q^XLxIf#X?IWR=VuU(qPXDI* zr@>@lm(t4F*%zQB$QIA+%!cdbZ_h}`ncaBx zmhmKI4pQX0=vQ&8I>9|wOQ<~&g4T1%q#sT5W={%IABFFd{1F(+Z1iGM%hi=!~@M1v8iB@g4gz7f|{?APSN`+IvktuvWBcl_Qp&~NN`$Qd}Ee7HNI z4Sp1$B;!jY9}EeL^bW;>4p4`w=_sqIE5o!M)YOq`+DHwUA`FIv!GxTNV*k?+Nbteq zqW*saj^lMD*kJN~0+E0tMPNd)fO#Os7mLRD;=TPPwNwx)+R8eT;7GVKOcR_cc~MPE z(vL(6MyjetL`10Iztf)BdNIxvz*N+6K>8SGnp*KNB=qH{3FwS@%lHYe^q6xwVBIkZW(D*#1N^cV^IsH^} zv@-{A_y8<;ebvAqQUJkM6^9AOdlQ0)s{ef$RUBLcs4emR z#!|+Tgph=g{Wrbmf6o8?|IYcJ=iJYA?(6psspccPVr5ep+9BLDy_CdT?U z6l?rvoTsC_?KkR;D2CQk*IX9>Y9BHkyPc!VsW3K1dO-D%z$#@T0yDNT2Y@gM0EmhO zfJ2Ha>KgzADFDFQZ2*8~0{~9|vDsRavOwobNZ};vxLN76MKM+Z(d2WD_RM6oI3&fVUsNhRJ+yrzF1&qc zV6`(HTRi*h!xHP%ZS72)pUJ76vDQgqo9W}m zVN`}5A{;-I@eN~})JQ9fk)%&)Jj32tv)YrwPO6T^d)O1*BTc&cd#F1|6&p?FB5@{(bi zu|5*a(3mk6D{GF3^bdi-&~6Pglj#SF^1s3kItvn9SodcIZqG7-3yt4f z$5$2;StVTscgt3z>_i(M%WWU@EtMR1-%Tge?M+*7x8k{!qv_DH;hw3J4K?%l4ei?#eR>MS zK8&Bl(C{(`KwR4msGI6<3--3%Et85GOX^D)ReoV^*vQ#mQ!&^lvjEJ`6%Q$U;p`Vp zHT&Bw3=WpiNvr8{@B^kFXb3kxzZr2Q_eOs@bzHzW`^*fzOl6Q{MvS4^NW~E zLiF4?PYl=dZzQ|w4`e2Wx$Hy^sZ89{&R)Ezuu(&rwl6~}@OKycrmX%!L$5)%5>99v zdQfyKB*fGhKyYq*Syago`Dke8WR-V?hn-hEaV18`_1kV;1J#{r<$?!K(NcUXuWn!> zIL*d3YcM743I0Jx4AZjBtJjJ$9qdju@|V72AM6*Qq8&I&uWCiM_n40$=CI+L49|;E z5jnk|MW<} zXT8&6ZQ0;owuDeE*+0HDApdiCQT3t;Ty1S95Fs+43Ox=TC~??taFanrua{|R6B99! zqW4TPLkp++W!$uNZ)`-`Q`y9QmL!pm2X}{2sstQv3K*t~q1|{bpGWB_%3#q(c5vMm ztaZOcePVs-MSSztL^j$!s(Vc8^y@YkC)Ep~$kZaOTO_PRY56f){cSQQeO?f6eJoKyqGn=IZ z)B2m2cP_w`WfkoB+qCE(;#}+`fmFhDpkN(ts75*V5g264^y4u7C^Ju{ zjV5WMJCNs>v<_2~tb|F;@T!-zKvdnx2Wdvjps?SIF1iDCu}=PeRiGIZUo=K35Ckff zQbjR*@`aH6Rh4pOo+7D#n6_2`QaMRf_v{}&28)>S%{p)-%&-pJco1987Qr^C{L0Wb zqeHg;x!yDG?Q(8YcH{IEh_Wb~UeTzeatr*6P)HRW?FV+Kfh-l0yjFsJ$O<8smt>3G zlVvz*H6Ew4o1}g8NmB;?OoE-k>fANN4pPrsP~#&w2<8;>Lp0>s!xj19gD~pG97|f#qOj@ zn%Jpuw^V988lBn~nWcOFn*N@SVZhA#m++HWjj@A4r^m*Q0E1wulVBQm)Cilh&_XaB z+wIidQIT3Iks{dz2!9|i%dK+At>nuRSW-dKSBLF_mMXH>!o=01)z{Z=40^zH6b}u+ z38PU{K3@<}a|i31?7{V^N;;YgxY?@ZS_U0x(#v`Gg~V#m=~nmUGexbT-T>YPlpLS$ z&yEQ*MRwLAw|=vX66$m;C+d;xPQ)!?j#bVV^Tf~Zjy3)2;Xw*(Ro~hh5h}cD7uOb= z=BfqBHs#>1UnG$zq1@zlt>0Wi4781$iK*5ZEuW9MEA0c=+0`k(8(E8niFfsHhbF1g zu|)SAw&FgxfZ?UmcPGcX&;4yhU8uR43{JmKJt_2s6}Hq)w5_LrAWyrf&y=A9F|NYH z@$a%<7lWBzSuxKf=|N4pHZb!C(2%BKZLui3OYp(lqzb|JOp^ui|Pp~$MF+b^xY`fHzMtjh%I z=rvb3xQr`zk6k=GItoIPo%6gnqJDuwc#BPoTaQl5(1~Zx#G*mum(-pfp2GYfW1|SI z{Iyj-G%dODz9W6AE8hN|E<5CkF@U&e5l{b{bmhq53bJbSv2!XjFZ{ajh3R8Xjze>> zG>sM0$n>}hznE3!7At!c0Ck)o|7s|D}uyrgD7Q8tF>P8kSzw-kV~Al6Ykjvx7809i zlvr0&;II8l@9MNqb_nlal%aDkM0jNFSJjF*zYD2f(UgF!)oJ-;Ty>IBzDK*EMLAoY zy;6#%ZL2Jbl|N1#-(KBh>G!f#PTtSTA{dvdE$>WfZri>ZKmUnF0K2~v=);`rv%Js| zN$tQxhdP3_s3aGlCyiXISo@5TdOq2gAS7BgInLh?o35Wmdc@XrcGthXJxJ}!C4ztZ z9wta{tsH0R(A|{h@;Tf8K21IqQKIK{QEqHE(krc@7unor; zu|+VshA(G-C_#dj^hsI!N$!`y-rV;|25pn0odlN{fvs~jvqk8dvJePoVO{FOt%{E< z)h}kcFZ1I@>T^5Wbg8*{&>X+YK1oD{)^>!O)wc$QKUnaHei3?16#Cc+6TH$mn45d< zMi{xYAhYo?VZ{rZK_(bzA|!9^ZY)K40$IItUJ~n>j$DykH@@`P!Xh}Y7n8hJn%ZVH zXE{oGmOrKsL4LJ4H4|Tav-Qb%77=~=8kBOhA9yR=vh#49nbPE301B_cFdunL2 zXB0=_Ec5FYe(4F7bLG%{Vhxl z2cHJi()98ZXxn z`diolp{9+A;Vf8HvXior>-?9R}oluP9~8 z^~Ajz2tX4;mb;tS^E$n2cd+{+^WWD>No!7WhyL?9r*jd_M3|a-*W+*JN8OWZiZCuu zD$PeE4UpG79YR9_qxZA?iWuKcL4&uj!y+fXKT14~o2jWsVhxM4E5BOGaAerU-KkbE zItgc(KIUDjT7RU&Cg*XWfX3tT9QsV^LO*G7b>SC|W(7Yo9}>eRc3U(!3l($mKeb1# z4bw^4EQpj)dRzxaII;pi_#@z1|2eH2ghg#0e}%M^v6Y|O9{X$wZ{Dbx9}0aUr}^KN zdM@sVSZ)%yh)`^ao&U0&efR#6i`(?Iz20NxC=3m! z7(h`0tS$#ulv7Z%11mzoYEUHw83hHXf&z~tM)3ax`1*UG5V-$80KwQ_NC`0flL6z8 zz=pV?;ed&+nHMJOqiPZ`$y3Z8RY8@h3fmmf_&kASSZwrf?@!0=~;{Xe=+~$ghG*UlqV7k zfYlW*0O&Xh!}Bkl|6v?a9$4fbgj6Ydo`PKb7h;a`g=296aNwV+>7%(y>K_!2tz5y^NkfsZPPbdcUb zdhcE7>Wlw*Gw*wE=FPpkXLk2@%AP&v+_@Y5LhCsNDHACG0HA=VDZ_Bo>Te?^!u6|J zJ`y-WXs@WL2mn+ilHJ1Z;Kq0;*mETSc8FyMH(;|-gJ}W){#*b+a5w;PjhhPI1^~Q( z0Kl#l03ekG05G_}Y0{CwEf862JXZ$%`TOLzl%(QjNZi$oQ8=phpQhU9EC&GG>wqXL z>iK>@$el%*P6zeKUsx|0hO#w8VfbfLI3+U}x=i;as+fCXS)?K3JLuDie{y$z6a;Of zmZVa%&xIUHvZ2mBS}dluoYIRa5_LAF)$|(G95IhcLIDr}!;SZmY!HB5R~+vUkhSAO zM5ti4{1)|Pt3EFP%Mng}D=$T4Q^Nd-hB*KIP8x_cmVXWSO)VEWK~z;p{M11z^As_J zP>0^w^8@cTFVBk4`IWaviZ>z@URhLW7lECJN-Oyi1W}i#e@B!5^ zvG`Q=WbO3FP1N%{KF843#7O^nWf!hEn9se@bV6db&!A7k&vl!H^Ei$58GTIrikEuo zm5|=EgEQnJbmr82`d0_mZ?_70hHPUb;)xE)nl9V&6Q8`~ewmt#q>I8n$%gHkp%`I!}Kx~bpMYe91p#Dy6mT&cNzwR%K z^F|lnrV%+b1zrv{j*~^()>kfP6IvWK$abcX7%Tti7*)R%z2wq4V$DUSP+Iy1rY^&v zd7}FGSyP$t;XlXd*2JEh=6w$nVXtHf^cw)HTAFin-nX+=mz?@dlmjvHY{rjwbxj&h z^=ofp<9o`%ZzzA=UL)?ul&D4zPju? zkdM;f^ENHxcH57_?Y95e4-4&eS|9e8Wr@FRSg^O$8FssmbB9@RXTL{8rVXiX7w_kN zyN4735=&mSs*~TjZa@LCI_Xv%yWpr`9jYtH_SqM znDWw(W8JP7iHse_l4bE3`uPa=phiKDiccNz56`79N3DWyLbckb&bz4Qv=p=^FZFm% z+g)O8P>l5DyoHo}+85LI3t1gwG$$XoL$hJ&)2obcV~a2OP1_xl{2Hb^sE7jRcTme< zw^#41=7>LROEFY)CUD<>Nu%j0X<0Dsw25J-l4l`zpK1 z^I-IhIRYRe7Js4ZXOX3OhEdKyYa&{EhQ?`x5+hpny-n&=1Y8;Mel}~yU!*Wvpj`aYClSq4FBthw=tKOsv|0`gZ~r- z&4BRmd&_xC#w0D`1dsh6t5oPA1{}Ax6{r#;23fVgTTtSr z?e-$aR*4wv;IcNXjt0UA1Kyn~C}{OQ5eU+^!?JMa-?7yl89SB=33rKG3RzCm*RxCEBd zVi*ly{*s@1M0MH7z5IU3$)X-rWrrVA*3Io0k@*hA63dyzr~d#Y>Gw{4U^E06U_QiJ zv;~eS6U5asUry{X47%b{96oKkJlBH!GHv-$zJmLpg%?lXe9KzA=cG}hHDSm@FtxD9 zdSk^ss*oUvh2+{JTM9F>OBj<|&Ea3vYpnc-iuc-Jll>+*QAtvbYP#yVGQ<_%iPijxxCRcD#c z@ZQGxl2p)Yf;scwJF;MMH!O!Omtlg#cpnq(UlaMg7aGVK582UvflJ&R>VY(;=9Z+5 zh*{7pwM`OZ=xv9u&@16>w?>$a3O=E`RPN>@?YHZxdO6&8iLUw%J|f08zv;lMHFKlb-iBOJ$07KB%}L{a!StAzx!MU){6d2k6C2`7u(PQ2 zcuc>B=Iu+iqI%W3#YK75?5YD6GvE5@8kR>Jol_+IuaVNNm^cU7rJSA zTeovvCV0t~zLFaO673SvH!mqBb5i;!&vf)rJ{FM|Tbx)e*pTw^SY4*0%gk}^yAa+J zZ&6(3yBtu(l^COnGR;KGuG?<0Zof&!cd>IN0!JBeL97%YkPeP`=Qx?rRD%64rduh?g z!6`%i5%rO9g?nE5voHw6s{^|edJX$@$X?J$k@V#g!2uZ0i*AB6HG+3^NRo;opInZyU+Km0;RDOj!;$OFsBXrZTVF}N4`D?!Wq zkO;*2_0xNQsrE1;!wDBucu5r--edWgc-abj&G9d+1k^!bog*nZKU32lIow7U`j?fV@8TwXm#<}0OkH!!_0xF zRoZ)OE3Iek@0WLIy+$)y*GFp!R3X-x9SMTyA;kUa-EWQPFb=rr1Mfh`e~Kum-~9^7 znzdTSS|#a3hWV^|yp)sd6MgoKkRM}e$m>)39-T{*5iE-Y%QHRPEZG`9b7L4r89-3I zTewe#fb_A3W2C-C0F;aJriEP6#T-#>$hF*by%QI<1!9tv0!1kt-%i~B*kj$yl56ht z{q%l^2x}vZ37H%#u-)MGsY_Ggz0;3U32%G!$>V;QsYAHvaJ>4Ni1fzG;ZnsZZ%@l`* zM)zle^cMY4$hOiGvr#XtPCH)#`Yw)s@)>YFskYglxq`7>-YxTp;B)RZLi{2Fcoj^! z)W8J$)QD_%!AQ2H#k|E>pk%U{ZTv$xkoxe0m!P#@ckSZ|FG>6|dwp^dlTZX$7C**n102(Bwrv;u1x9AG7zle=kN+?yafI+k>+8RGrryL|d(IgZ@2?2k zivJW+I|FFj#Inq2RcPMv%B4ZR38+# zy(j7-i*&ePTIt?j3MTwC(Wq4cjVw|#qE!=M!GqA2H>r8!;i@PbrxwH9}}oGlSaW6+c|m{6bm;>3n74P*@}hTauzS9ev%G5f{BfQ{1h1FCGSn$x$~R2lk6pif@@E15#b`dsg3-8DMSJ)>qLpH(5goYC05->%Q++Y= zUSx3=p2!Ub$PL^13D7^$t#sE0s`XmCE>5TacFfS+_n;D4-RCrUvvqLEBe-S9<1ALk zJe}%N{vore{JXh_0%ZJhZ598|%M+Q_?AWU5gH`Ed;+L_FJ3cu~EBRd=Ed{^ye(*Ag zj=wMWI}eDQJz`~dIfJLweQf52u!RpUR-CA7P;}K z>gd;rx;);JX16~N7g&DynZB&&!Q-0!`tX8{YqmEsmf=!Hx?}D{yD{PyKA`LFKd)AMnH3Ir`v1ofT`Ze?qYD5iq4!WO`PYE@sZDqlMDSUWZ=u_Nh}w_I1k*3nI@F z$L-0iM6;$(b<5F|>P~b;CQ5YIF%R7fyHt(4?dw*6$luM*DvJ7zDgEyJ{_%$IaKBoo zgaYCZ+$CgRS+4@unIk5k?-#<2xin_Qk!E>OYK{S&rkYm!zS+yImYd z^9M1Qg5o_WgJ&~i;_2yt*bonoi|Uh$$j2sPJMD3(~Q!4tv%iY?gc;oZ$Y_ zA9UEw%@+~fg3q&_eGx`_QZ3gvc>kD;wfsT1si7ig^k!{lUu+SRS6EC&dF}6O?H+!& zyU?p=EXlC^jk>_` z_kE5dF1u`@%$bAp6E#}~s>r*HJ^@uOW4~Scei7&u2pd8@4YJoOMEU}a+w8qPV(qh@ z{T3$LR~(R56VUgHFPDtChnn`aLB{kOM_81HMYcbap=I1mYQ2krJ73on`HVbuq_ZPE zd!vu_G-y;+tfa2Hp4nnuNpefepRB1o>98vx%~dY_Djn@;k*MjZ1+h*;98ypmJJ_bp z-Lm6nRJL@xm>#mHR?=nn4xU1GX$?`R?XUT=od+Qcxb#^SpKYZz^P+8{eqWBzDp_NR zwOCoReN&CCnr2-;3Gw){D5{V*SS4WUgPhY01Qn!WHyg6DH*I%Cs;p_lTx{njhgm}~ z4?JFbJgCITk8pa|E=t^3MM=&$|MBcbolr?<| zlpNgoLAaF$Nl9lxriPgY6|x*BjM$&qEQDUdTRu4Oj^By6pttiyAwzep>04)q%-it3 zurk^wO1rNis^-G$=6f{(8=N=pQnGCk10cy-cF(P zQ>1muaGKu$(LKwv=e|IhZgxu{i_}_I3|-w%gV#T)zw{Qlq>1j3U^ll$BCI-Rd+?SX z1k4loLgxyd?}S2Y2eN;#v|{qsZFyCVb!QJKJuMy5K8J=WyI||wdX|zgeojjE1r_c* z(jBEg2&+~f8-zvRa~xH=gBuGk?qPR$t6(XpZyY7#_nuDTThycmy@gX=cN5Ru8c{G$chH%0T6{ZQS>-qq zGP7yQUj`XBhyn*%3Us>7+v+xx4U~G^w#i?-=vR&<3(RS1zZ$rYs8mgy>}Ow+sK0(q zlC`k+&DTkZ+qmz{(f{?*u(rEcYgAlF&?50gWcTdePM34FmxJzi=21FAg$0J;(yk^G zb#r(VFp(GiniYbH)^t5wYMU5cV|40+mNr_sbr< zcP4gFpkpdkPaw^KOa zp}dLQsR@uS-ZCxNBX-CyEANbneWTAMSprQdTR%3P-#??Q85V`+4JLM3nUv{14J=lc z%+9ebPU>{5MwRLC`mSg9@H)iJs)rijb(2(K8=VQm*|($hsnde4`c84bIng_E&l;1-CgK# zNTS=r-Rp6pRgBQKa5O^7#uI@f01=?Dq=2x908m0tSVT%#LP`|K2Lwt1feeNy*8j!e z>SpU`=lB0J*pc=Z;22c@YCyT!p?%<<2mr(tZjaD}+dJAgvxy6W1tkO|*>EaB0zfgG zRyG}BaW)4u+FeRW$j8S=(D5%C*KlY-H&6Td*9SO(fCqmi>N$A1T1!bOyV-cTB9Le) zsTVjX3Lsqa=d;lN!Td+3l#~O)(cS?K5SA370(eH?Fbw~a^WPXlM_aVRU&wd`J24Kz z_%Dd2qbmaK=Z*mU$0{Lrq`iE#f!6<#qp62O0ffcCViG{Gm@trnkKYalq578`T}OWe z0H~yt_D*gew`B0IC4CqKVCU$9z-?d16^V9nvlp_1dpp{=AyGpAb1*`7AW^t2LQ)bW vCLwAE7XyR9;s`My0t~Vdwg$uDc7iw#L7aWzOsu#YUH|~1qNR*gvI_k#?P!gZ literal 0 HcmV?d00001 diff --git a/server/src/public/images/icons/favicon.ico b/server/src/public/images/icons/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5b6cfe2152ba828d00eb9dc8661ea71298053d42 GIT binary patch literal 1150 zcmbVMOK;Oa5H=DwE)@sP9QkSdA8tGam5_*30YVh1s#*aRrGf(wHI4FY{77OuYsc{; zj@S0btasP65+}x5&w6IQZyvjeVcei+XUCxTUE}^u!?G7R$Fz9m=l zO)n^^As_Ks)*R#TH@f~Qy6z`f;V;y6)kI2NE0k0Msl`o9oDN%_9Qj4n{sWn-4SlAD(sOy)-zO!ts&7A=q1ToQkueMerVEpFs~M$dka zEN9ZD@}(OW{m~1!?nz@`lYc;1A-blb%rN!7z@xsGRFC#u?R_%d1uxc!s1`H$*~W+s zC%i*5SQ0*r`pPH!s8w$Z`z?xXfGC^8Twc%5c?xrO2u5cxzU&~P8gy-1d-iK^flnP+ zG&dpIS5+LYe}*)*;8Pv_-UDoDzA{G6mN|qk0<0;IdN-Az`O2 zMg_@pQ?o0J6#{1u%z8!rF%+4D<#ZRT#Xc(f4K&ik>N+)xK7VP?lM&&bgPAW;Z03J) NDvw6#|AGJ2e*k~x)Oi2^ literal 0 HcmV?d00001 diff --git a/server/src/public/images/login-office.jpeg b/server/src/public/images/login-office.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..32a9fb12b467a3484fbd9a0bfafb4278b052f93f GIT binary patch literal 20627 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 literal 0 HcmV?d00001 diff --git a/server/src/public/images/logo.png b/server/src/public/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2e8695210bfc486c5af441ce28a6b8eb4414085b GIT binary patch literal 4743 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 Iv_tfN04Z+8)c^nh literal 0 HcmV?d00001 diff --git a/server/src/public/styles.css b/server/src/public/styles.css index 544441d9..13b8d6e6 100644 --- a/server/src/public/styles.css +++ b/server/src/public/styles.css @@ -1,4 +1,177 @@ -p { - color: red; +@layer reset, defaults, components, utilities; + +:root { + /* Spacing */ + --v: 0.25rem; + --w: 0.5rem; + /* Fonts */ + --font-default: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + /* Colors */ + --background-default: #ffffff; + --background-alt-grey: #f9fafb; + --background-action-violet: #6c2bd9; + --background-action-violet-hover: #52289b; + --text-on-background-default: #282828; + --text-on-background-action-violet: #ffffff; + --text-danger: #ff0000; + /* Shadows */ + --shadow-default: rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 20px 25px -5px, rgba(0, 0, 0, 0.1) 0px 8px 10px -6px; +} + +/* Dark mode */ +@media (prefers-color-scheme: dark) { + :root { + /* Colors */ + --background-alt-grey: #121317; + } +} + +@layer reset { + /* https://www.joshwcomeau.com/css/custom-css-reset/ */ + /* + 1. Use a more-intuitive box-sizing model. + */ + *, + *::before, + *::after { + box-sizing: border-box; + } + /* + 2. Remove default margin + */ + * { + margin: 0; + } + /* + Typographic tweaks! + 3. Add accessible line-height + 4. Improve text rendering + */ + body { + line-height: 1.5; + -webkit-font-smoothing: antialiased; + } + /* + 5. Improve media defaults + */ + img, + picture, + video, + canvas, + svg { + display: block; + max-width: 100%; + } + /* + 6. Remove built-in form typography styles + */ + input, + button, + textarea, + select { + font: inherit; + } + /* + 7. Avoid text overflows + */ + p, + h1, + h2, + h3, + h4, + h5, + h6 { + overflow-wrap: break-word; + } + /* + 8. Create a root stacking context + */ + #root, + #__next { + isolation: isolate; + } +} + +@layer defaults { + body { + background-color: var(--background-default); + color: var(--text-on-background-default); + font-family: var(--font-default); + } + + h1 { + margin-bottom: calc(3 * var(--w)); + } + + label.required::after { + content: ' *'; + color: var(--text-danger); + } + + button { + cursor: pointer; + } + + button:not(:disabled):hover { + background-color: var(--hover-tint); + } } +@layer components { + .c-card { + background-color: var(--background-default); + box-shadow: var(--shadow-default); + } + + .c-input-group { + margin-bottom: calc(2 * var(--w)); + } + + .c-input-group > input { + display: block; + width: 100%; + } + + .c-input-group > label { + margin-bottom: var(--v); + } + + .c-btn { + --hover-tint: var(--background-action-violet-hover); + border: none; + padding: var(--w) calc(2 * var(--w)); + background-color: var(--background-action-violet); + color: var(--text-on-background-action-violet); + } + .c-btn:hover { + background-color: var(--hover-tint); + } +} + +@layer utilities { + .u-center { + display: grid; + place-items: center; + } + + .u-background-alt-grey { + background-color: var(--background-alt-grey); + } + + .u-cols--even { + display: grid; + grid-template-columns: repeat(var(--cols), 1fr); + } + + .u-mt { + margin-top: var(--mt); + } + + .u-p { + padding: var(--p); + } + + .u-text--center { + text-align: center; + } +} diff --git a/server/src/templates/_base.njk b/server/src/templates/_base.njk index fca12a40..4cc08769 100644 --- a/server/src/templates/_base.njk +++ b/server/src/templates/_base.njk @@ -5,8 +5,9 @@ + {% block title %}Permacoop{% endblock title %} - + {% block body %}
{% block main %}{% endblock main %} diff --git a/server/src/templates/home.njk b/server/src/templates/home.njk deleted file mode 100644 index c4e68058..00000000 --- a/server/src/templates/home.njk +++ /dev/null @@ -1,5 +0,0 @@ -{% extends '_base.njk' %} - -{% block main %} -

Hello, {{ who }}!

-{% endblock main %} diff --git a/server/src/templates/login.njk b/server/src/templates/login.njk new file mode 100644 index 00000000..adbbaaef --- /dev/null +++ b/server/src/templates/login.njk @@ -0,0 +1,29 @@ +{% extends '_base.njk' %} + +{% block title %}Se connecter - {{ super() }}{% endblock title %} +{% block body_class %}u-center u-background-alt-grey{% endblock body_class %} + +{% block main %} +
+
+ +
+

+ Connexion +

+ +
+ + +
+ +
+ + +
+ + +
+
+
+{% endblock main %} From 76bf8e94c03a6224af49a7c1aa9cc2b87c16d729 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 15 Sep 2023 17:35:06 +0200 Subject: [PATCH 03/49] Implement session-based auth --- server/package-lock.json | 510 ++++++++++++++++-- server/package.json | 7 + .../Home/Controller/HomeController.ts | 12 + server/src/Infrastructure/Home/home.module.ts | 7 + .../User/Controller/LoginController.ts | 13 +- .../User/Controller/LogoutController.ts | 24 + .../User/Security/IsAuthenticatedGuard.ts | 17 + .../User/Security/LocalAuthGuard.ts | 17 + .../User/Security/LocalStrategy.ts | 29 + .../User/Security/UserSerializer.ts | 34 ++ .../HumanResource/humanResource.module.ts | 11 +- server/src/app.module.ts | 2 + server/src/main.ts | 27 +- server/src/templates/home.njk | 9 + server/src/templates/login.njk | 6 +- 15 files changed, 669 insertions(+), 56 deletions(-) create mode 100644 server/src/Infrastructure/Home/Controller/HomeController.ts create mode 100644 server/src/Infrastructure/Home/home.module.ts create mode 100644 server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts create mode 100644 server/src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard.ts create mode 100644 server/src/Infrastructure/HumanResource/User/Security/LocalAuthGuard.ts create mode 100644 server/src/Infrastructure/HumanResource/User/Security/LocalStrategy.ts create mode 100644 server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts create mode 100644 server/src/templates/home.njk diff --git a/server/package-lock.json b/server/package-lock.json index 9df4e565..e87bc242 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -22,12 +22,15 @@ "argon2": "^0.26.2", "class-transformer": "^0.3.1", "class-validator": "^0.12.2", + "connect-pg-simple": "^9.0.0", "crypto": "^1.0.1", "date-fns": "^2.8.1", + "express-session": "^1.17.3", "helmet": "^3.22.0", "lodash": ">=4.17.19", "nunjucks": "^3.2.4", "passport-http-bearer": "^1.0.1", + "passport-local": "^1.0.0", "pg": "^8.2.1", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", @@ -40,10 +43,14 @@ "@nestjs/cli": "^9.3.0", "@nestjs/schematics": "^9.0.3", "@nestjs/testing": "^9.2.0", + "@types/connect-pg-simple": "^7.0.1", "@types/express": "^4.17.3", + "@types/express-session": "^1.17.7", "@types/jest": "25.1.4", "@types/node": "^13.9.1", + "@types/nunjucks": "^3.2.3", "@types/passport-http-bearer": "^1.0.35", + "@types/passport-local": "^1.0.35", "@types/supertest": "^2.0.8", "@typescript-eslint/eslint-plugin": "4.22.0", "@typescript-eslint/parser": "4.22.0", @@ -1947,9 +1954,9 @@ } }, "node_modules/@nestjs/passport": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-9.0.0.tgz", - "integrity": "sha512-Gnh8n1wzFPOLSS/94X1sUP4IRAoXTgG4odl7/AO5h+uwscEGXxJFercrZfqdAwkWhqkKWbsntM3j5mRy/6ZQDA==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-9.0.3.tgz", + "integrity": "sha512-HplSJaimEAz1IOZEu+pdJHHJhQyBOPAYWXYHfAPQvRqWtw4FJF1VXl1Qtk9dcXQX1eKytDtH+qBzNQc19GWNEg==", "peerDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0", "passport": "^0.4.0 || ^0.5.0 || ^0.6.0" @@ -2346,6 +2353,17 @@ "@types/node": "*" } }, + "node_modules/@types/connect-pg-simple": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@types/connect-pg-simple/-/connect-pg-simple-7.0.1.tgz", + "integrity": "sha512-cpSccwirAbSoup2hx0Jg/oPpUGXu2+QwX67awRJrkNp1E3gxOrGL4phU17oLzx/mGyLQKGLYEHlvoI/soB+Lhg==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/express-session": "*", + "@types/pg": "*" + } + }, "node_modules/@types/content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.3.tgz", @@ -2419,6 +2437,15 @@ "@types/range-parser": "*" } }, + "node_modules/@types/express-session": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.7.tgz", + "integrity": "sha512-L25080PBYoRLu472HY/HNCxaXY8AaGgqGC8/p/8+BYMhG0RDOLQ1wpXOpAzr4Gi5TGozTKyJv5BVODM5UNyVMw==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -2520,8 +2547,13 @@ "node_modules/@types/node": { "version": "13.13.49", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.49.tgz", - "integrity": "sha512-v5fPzKjPAZ33/G4X8EXvGlbHFKQClfKAz1bKF/+cKaWss9lAIqrOETfcFNL3xG+DG2VCEev+dK4/lCa+YZaxBA==", - "devOptional": true + "integrity": "sha512-v5fPzKjPAZ33/G4X8EXvGlbHFKQClfKAz1bKF/+cKaWss9lAIqrOETfcFNL3xG+DG2VCEev+dK4/lCa+YZaxBA==" + }, + "node_modules/@types/nunjucks": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.3.tgz", + "integrity": "sha512-+lFIql0nbWSftazQ27cOYvSLC92SsfjxrU0I/Iys7hoxrBkN8OF+wmxxzx3bLFyFrLgDZ9lUckGcwldE4SfDQA==", + "dev": true }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -2530,9 +2562,9 @@ "dev": true }, "node_modules/@types/passport": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.6.tgz", - "integrity": "sha512-9oKfrJXuAxvyxdrtMCxKkHgmd6DMO8NDOLvMJ1LvIWd6/xP+i81PAkpTaEca7VhJX9S009RciwZL/j6dsLsHrA==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", + "integrity": "sha512-QFdJ2TiAEoXfEQSNDISJR1Tm51I78CymqcBa8imbjo6dNNu+l2huDxxbDEIoFIwOSKMkOfHEikyDuZ38WwWsmw==", "dev": true, "dependencies": { "@types/express": "*" @@ -2549,6 +2581,89 @@ "@types/passport": "*" } }, + "node_modules/@types/passport-local": { + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.35.tgz", + "integrity": "sha512-K4eLTJ8R0yYW8TvCqkjB0pTKoqfUSdl5PfZdidTjV2ETV3604fQxtY6BHKjQWAx50WUS0lqzBvKv3LoI1ZBPeA==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz", + "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/pg": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", + "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + } + }, + "node_modules/@types/pg/node_modules/pg-types": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", + "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", + "dependencies": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.0.1", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/pg/node_modules/postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/pg/node_modules/postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dependencies": { + "obuf": "~1.1.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/pg/node_modules/postgres-date": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", + "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/pg/node_modules/postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "engines": { + "node": ">=12" + } + }, "node_modules/@types/prettier": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", @@ -4070,6 +4185,18 @@ "typedarray": "^0.0.6" } }, + "node_modules/connect-pg-simple": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/connect-pg-simple/-/connect-pg-simple-9.0.0.tgz", + "integrity": "sha512-tPHR01VQU/qnOl8bMsORD1WyrNkbVkyNmnXfXqaH4NZfxWb3zQkCTPbVHjkhjFpKCQpHA+Ry9Y7medndwyvq6A==", + "dependencies": { + "@types/pg": "^8.10.2", + "pg": "^8.8.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", @@ -5332,6 +5459,51 @@ "node": ">= 0.10.0" } }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/express/node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -8523,6 +8695,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -8534,6 +8711,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8779,6 +8964,17 @@ "node": ">= 0.4.0" } }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", @@ -8874,23 +9070,26 @@ "peer": true }, "node_modules/pg": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz", - "integrity": "sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.5.0", - "pg-pool": "^3.3.0", - "pg-protocol": "^1.5.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, "engines": { "node": ">= 8.0.0" }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, "peerDependencies": { - "pg-native": ">=2.0.0" + "pg-native": ">=3.0.1" }, "peerDependenciesMeta": { "pg-native": { @@ -8898,10 +9097,16 @@ } } }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, "node_modules/pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" }, "node_modules/pg-int8": { "version": "1.0.1", @@ -8911,18 +9116,26 @@ "node": ">=4.0.0" } }, + "node_modules/pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", + "engines": { + "node": ">=4" + } + }, "node_modules/pg-pool": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz", - "integrity": "sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", "peerDependencies": { "pg": ">=8.0" } }, "node_modules/pg-protocol": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", - "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" }, "node_modules/pg-types": { "version": "2.2.0", @@ -9039,6 +9252,11 @@ "node": ">=0.10.0" } }, + "node_modules/postgres-range": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", + "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==" + }, "node_modules/prettier": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", @@ -9214,6 +9432,14 @@ } ] }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -10873,6 +11099,17 @@ "node": ">=4.2.0" } }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -12765,9 +13002,9 @@ "requires": {} }, "@nestjs/passport": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-9.0.0.tgz", - "integrity": "sha512-Gnh8n1wzFPOLSS/94X1sUP4IRAoXTgG4odl7/AO5h+uwscEGXxJFercrZfqdAwkWhqkKWbsntM3j5mRy/6ZQDA==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-9.0.3.tgz", + "integrity": "sha512-HplSJaimEAz1IOZEu+pdJHHJhQyBOPAYWXYHfAPQvRqWtw4FJF1VXl1Qtk9dcXQX1eKytDtH+qBzNQc19GWNEg==", "requires": {} }, "@nestjs/platform-express": { @@ -13071,6 +13308,17 @@ "@types/node": "*" } }, + "@types/connect-pg-simple": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@types/connect-pg-simple/-/connect-pg-simple-7.0.1.tgz", + "integrity": "sha512-cpSccwirAbSoup2hx0Jg/oPpUGXu2+QwX67awRJrkNp1E3gxOrGL4phU17oLzx/mGyLQKGLYEHlvoI/soB+Lhg==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/express-session": "*", + "@types/pg": "*" + } + }, "@types/content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.3.tgz", @@ -13144,6 +13392,15 @@ "@types/range-parser": "*" } }, + "@types/express-session": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.7.tgz", + "integrity": "sha512-L25080PBYoRLu472HY/HNCxaXY8AaGgqGC8/p/8+BYMhG0RDOLQ1wpXOpAzr4Gi5TGozTKyJv5BVODM5UNyVMw==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -13245,8 +13502,13 @@ "@types/node": { "version": "13.13.49", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.49.tgz", - "integrity": "sha512-v5fPzKjPAZ33/G4X8EXvGlbHFKQClfKAz1bKF/+cKaWss9lAIqrOETfcFNL3xG+DG2VCEev+dK4/lCa+YZaxBA==", - "devOptional": true + "integrity": "sha512-v5fPzKjPAZ33/G4X8EXvGlbHFKQClfKAz1bKF/+cKaWss9lAIqrOETfcFNL3xG+DG2VCEev+dK4/lCa+YZaxBA==" + }, + "@types/nunjucks": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.3.tgz", + "integrity": "sha512-+lFIql0nbWSftazQ27cOYvSLC92SsfjxrU0I/Iys7hoxrBkN8OF+wmxxzx3bLFyFrLgDZ9lUckGcwldE4SfDQA==", + "dev": true }, "@types/parse-json": { "version": "4.0.0", @@ -13255,9 +13517,9 @@ "dev": true }, "@types/passport": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.6.tgz", - "integrity": "sha512-9oKfrJXuAxvyxdrtMCxKkHgmd6DMO8NDOLvMJ1LvIWd6/xP+i81PAkpTaEca7VhJX9S009RciwZL/j6dsLsHrA==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", + "integrity": "sha512-QFdJ2TiAEoXfEQSNDISJR1Tm51I78CymqcBa8imbjo6dNNu+l2huDxxbDEIoFIwOSKMkOfHEikyDuZ38WwWsmw==", "dev": true, "requires": { "@types/express": "*" @@ -13274,6 +13536,76 @@ "@types/passport": "*" } }, + "@types/passport-local": { + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.35.tgz", + "integrity": "sha512-K4eLTJ8R0yYW8TvCqkjB0pTKoqfUSdl5PfZdidTjV2ETV3604fQxtY6BHKjQWAx50WUS0lqzBvKv3LoI1ZBPeA==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "@types/passport-strategy": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz", + "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "@types/pg": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", + "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", + "requires": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + }, + "dependencies": { + "pg-types": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", + "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", + "requires": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.0.1", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + } + }, + "postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==" + }, + "postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "requires": { + "obuf": "~1.1.2" + } + }, + "postgres-date": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", + "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==" + }, + "postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==" + } + } + }, "@types/prettier": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", @@ -14403,6 +14735,15 @@ "typedarray": "^0.0.6" } }, + "connect-pg-simple": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/connect-pg-simple/-/connect-pg-simple-9.0.0.tgz", + "integrity": "sha512-tPHR01VQU/qnOl8bMsORD1WyrNkbVkyNmnXfXqaH4NZfxWb3zQkCTPbVHjkhjFpKCQpHA+Ry9Y7medndwyvq6A==", + "requires": { + "@types/pg": "^8.10.2", + "pg": "^8.8.0" + } + }, "consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", @@ -15361,6 +15702,33 @@ } } }, + "express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "requires": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -17760,6 +18128,11 @@ "has": "^1.0.3" } }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -17768,6 +18141,11 @@ "ee-first": "1.1.1" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -17949,6 +18327,14 @@ "passport-strategy": "1.x.x" } }, + "passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "requires": { + "passport-strategy": "1.x.x" + } + }, "passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", @@ -18019,39 +18405,51 @@ "peer": true }, "pg": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz", - "integrity": "sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", "requires": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.5.0", - "pg-pool": "^3.3.0", - "pg-protocol": "^1.5.0", + "pg-cloudflare": "^1.1.1", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", "pg-types": "^2.1.0", "pgpass": "1.x" } }, + "pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, "pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" }, "pg-int8": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" }, + "pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==" + }, "pg-pool": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz", - "integrity": "sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", "requires": {} }, "pg-protocol": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", - "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" }, "pg-types": { "version": "2.2.0", @@ -18135,6 +18533,11 @@ "xtend": "^4.0.0" } }, + "postgres-range": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", + "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==" + }, "prettier": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", @@ -18262,6 +18665,11 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -19434,6 +19842,14 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", diff --git a/server/package.json b/server/package.json index 8e8a3dd5..7e11451c 100644 --- a/server/package.json +++ b/server/package.json @@ -38,12 +38,15 @@ "argon2": "^0.26.2", "class-transformer": "^0.3.1", "class-validator": "^0.12.2", + "connect-pg-simple": "^9.0.0", "crypto": "^1.0.1", "date-fns": "^2.8.1", + "express-session": "^1.17.3", "helmet": "^3.22.0", "lodash": ">=4.17.19", "nunjucks": "^3.2.4", "passport-http-bearer": "^1.0.1", + "passport-local": "^1.0.0", "pg": "^8.2.1", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", @@ -56,10 +59,14 @@ "@nestjs/cli": "^9.3.0", "@nestjs/schematics": "^9.0.3", "@nestjs/testing": "^9.2.0", + "@types/connect-pg-simple": "^7.0.1", "@types/express": "^4.17.3", + "@types/express-session": "^1.17.7", "@types/jest": "25.1.4", "@types/node": "^13.9.1", + "@types/nunjucks": "^3.2.3", "@types/passport-http-bearer": "^1.0.35", + "@types/passport-local": "^1.0.35", "@types/supertest": "^2.0.8", "@typescript-eslint/eslint-plugin": "4.22.0", "@typescript-eslint/parser": "4.22.0", diff --git a/server/src/Infrastructure/Home/Controller/HomeController.ts b/server/src/Infrastructure/Home/Controller/HomeController.ts new file mode 100644 index 00000000..bb88a667 --- /dev/null +++ b/server/src/Infrastructure/Home/Controller/HomeController.ts @@ -0,0 +1,12 @@ +import { Controller, Get, Render, UseGuards } from '@nestjs/common'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; + +@Controller('') +@UseGuards(IsAuthenticatedGuard) +export class HomeController { + @Get() + @Render('home') + public get() { + return {}; + } +} diff --git a/server/src/Infrastructure/Home/home.module.ts b/server/src/Infrastructure/Home/home.module.ts new file mode 100644 index 00000000..a5a73ffb --- /dev/null +++ b/server/src/Infrastructure/Home/home.module.ts @@ -0,0 +1,7 @@ +import { Module } from '@nestjs/common'; +import { HomeController } from './Controller/HomeController'; + +@Module({ + controllers: [HomeController] +}) +export class HomeModule {} diff --git a/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts b/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts index ba17f7af..4d012726 100644 --- a/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts +++ b/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts @@ -1,7 +1,8 @@ -import { Controller, Get, Post, Render, Req } from '@nestjs/common'; -import { Request } from 'express'; +import { Controller, Get, Post, Render, Res, UseGuards } from '@nestjs/common'; +import { Response } from 'express'; +import { LocalAuthGuard } from '../Security/LocalAuthGuard'; -@Controller('') +@Controller('login') export class LoginController { @Get() @Render('login') @@ -10,8 +11,8 @@ export class LoginController { } @Post() - @Render('login') - public async post(@Req() req: Request) { - return {}; + @UseGuards(LocalAuthGuard) + public async post(@Res() res: Response) { + res.redirect(303, '/'); } } diff --git a/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts new file mode 100644 index 00000000..94c83579 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts @@ -0,0 +1,24 @@ +import { + Controller, + InternalServerErrorException, + Post, + Req, + Res +} from '@nestjs/common'; +import { Request, Response } from 'express'; + +@Controller('logout') +export class LogoutController { + @Post() + public async post(@Req() req: Request, @Res() res: Response) { + const err = await new Promise(resolve => { + req.logout(err => resolve(err)); + }); + + if (err) { + throw new InternalServerErrorException('Failed to log out'); + } + + res.redirect('/login', 303); + } +} diff --git a/server/src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard.ts b/server/src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard.ts new file mode 100644 index 00000000..bcc83198 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard.ts @@ -0,0 +1,17 @@ +import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; +import { Request, Response } from 'express'; + +@Injectable() +export class IsAuthenticatedGuard implements CanActivate { + canActivate(context: ExecutionContext): boolean { + const req = context.switchToHttp().getRequest() as Request; + + if (!req.user) { + const res = context.switchToHttp().getResponse() as Response; + res.redirect(303, '/login'); + return false; + } + + return true; + } +} diff --git a/server/src/Infrastructure/HumanResource/User/Security/LocalAuthGuard.ts b/server/src/Infrastructure/HumanResource/User/Security/LocalAuthGuard.ts new file mode 100644 index 00000000..99facea5 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/User/Security/LocalAuthGuard.ts @@ -0,0 +1,17 @@ +import { ExecutionContext, Injectable } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { Request } from 'express'; + +@Injectable() +export class LocalAuthGuard extends AuthGuard('local') { + constructor() { + super(); + } + + async canActivate(context: ExecutionContext): Promise { + await super.canActivate(context); + const request = context.switchToHttp().getRequest() as Request; + await super.logIn(request); + return true; + } +} diff --git a/server/src/Infrastructure/HumanResource/User/Security/LocalStrategy.ts b/server/src/Infrastructure/HumanResource/User/Security/LocalStrategy.ts new file mode 100644 index 00000000..269ba782 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/User/Security/LocalStrategy.ts @@ -0,0 +1,29 @@ +import { Strategy } from 'passport-local'; +import { PassportStrategy } from '@nestjs/passport'; +import { Injectable, UnauthorizedException, Inject } from '@nestjs/common'; +import { AuthenticatedView } from 'src/Application/HumanResource/User/View/AuthenticatedView'; +import { IQueryBus } from '@nestjs/cqrs'; +import { LoginQuery } from 'src/Application/HumanResource/User/Query/LoginQuery'; + +@Injectable() +export class LocalStrategy extends PassportStrategy(Strategy, 'local') { + constructor( + @Inject('IQueryBus') + private readonly queryBus: IQueryBus + ) { + super({ + usernameField: 'email' + }); + } + + public async validate( + email: string, + password: string + ): Promise { + try { + return await this.queryBus.execute(new LoginQuery(email, password)); + } catch (exc) { + throw new UnauthorizedException(); + } + } +} diff --git a/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts b/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts new file mode 100644 index 00000000..c77051c1 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts @@ -0,0 +1,34 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { PassportSerializer } from '@nestjs/passport'; +import { AuthenticatedView } from 'src/Application/HumanResource/User/View/AuthenticatedView'; +import { IUserRepository } from 'src/Domain/HumanResource/User/Repository/IUserRepository'; + +@Injectable() +export class UserSerializer extends PassportSerializer { + constructor( + @Inject('IUserRepository') + private readonly userRepository: IUserRepository + ) { + super(); + } + + serializeUser(user: AuthenticatedView, done: Function) { + done(null, user); + } + + public async deserializeUser( + { email }: AuthenticatedView, + done: Function + ): Promise { + const user = await this.userRepository.findOneByEmail(email); + + if (!user) { + done( + `Could not deserialize user: user with ${email} could not be found`, + null + ); + } + + done(null, user); + } +} diff --git a/server/src/Infrastructure/HumanResource/humanResource.module.ts b/server/src/Infrastructure/HumanResource/humanResource.module.ts index 175829e9..1245f580 100644 --- a/server/src/Infrastructure/HumanResource/humanResource.module.ts +++ b/server/src/Infrastructure/HumanResource/humanResource.module.ts @@ -21,6 +21,8 @@ import { GetUsersQueryHandler } from 'src/Application/HumanResource/User/Query/G import { IsEmailAlreadyExist } from 'src/Domain/HumanResource/User/Specification/IsEmailAlreadyExist'; import { UpdateProfileCommandHandler } from 'src/Application/HumanResource/User/Command/UpdateProfileCommandHandler'; import { BearerStrategy } from './User/Security/BearerStrategy'; +import { LocalStrategy } from './User/Security/LocalStrategy'; +import { UserSerializer } from './User/Security/UserSerializer'; import { GetUserByIdQueryHandler } from 'src/Application/HumanResource/User/Query/GetUserByIdQueryHandler'; import { UserAdministrative } from 'src/Domain/HumanResource/User/UserAdministrative.entity'; import { UserAdministrativeRepository } from './User/Repository/UserAdministrativeRepository'; @@ -78,12 +80,16 @@ import { GetLeavesCalendarAction } from './Leave/Action/GetLeavesCalendarAction' import { GetLeavesCalendarQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetLeavesCalendarQueryHandler'; import { GetPendingLeaveRequestsCountAction } from './Leave/Action/GetPendingLeaveRequestsCountAction'; import { GetPendingLeaveRequestsCountQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetPendingLeaveRequestsCountQueryHandler'; +import session = require('express-session'); +import { LogoutController } from './User/Controller/LogoutController'; @Module({ imports: [ BusModule, ConfigModule, - PassportModule, + PassportModule.register({ + session: true + }), TypeOrmModule.forFeature([ User, UserAdministrative, @@ -99,6 +105,7 @@ import { GetPendingLeaveRequestsCountQueryHandler } from 'src/Application/HumanR ], controllers: [ LoginController, + LogoutController, LoginAction, CreateUserAction, GetLeavesAction, @@ -158,6 +165,8 @@ import { GetPendingLeaveRequestsCountQueryHandler } from 'src/Application/HumanR UpdateProfileCommandHandler, UpdateUserCommandHandler, BearerStrategy, + LocalStrategy, + UserSerializer, GetUserByIdQueryHandler, GetUserAdministrativeByIdQueryHandler, GetUsersElementsQueryHandler, diff --git a/server/src/app.module.ts b/server/src/app.module.ts index abb312e2..d6fa7cc8 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -1,6 +1,7 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ConfigModule } from '@nestjs/config'; +import { HomeModule } from './Infrastructure/Home/home.module'; import { ProjectModule } from './Infrastructure/Project/project.module'; import { CustomerModule } from './Infrastructure/Customer/customer.module'; import { TaskModule } from './Infrastructure/Task/task.module'; @@ -15,6 +16,7 @@ import { dataSourceOptions } from './datasource'; imports: [ TypeOrmModule.forRoot(dataSourceOptions), ConfigModule.forRoot(), + HomeModule, CustomerModule, FairCalendarModule, FileModule, diff --git a/server/src/main.ts b/server/src/main.ts index 723118ce..00570c65 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -1,18 +1,43 @@ import * as path from 'path'; +import * as passport from 'passport'; +import * as pg from 'pg'; import { NestFactory } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; import * as helmet from 'helmet'; import * as nunjucks from 'nunjucks'; -import { AppModule } from './app.module'; +import * as session from 'express-session'; +import * as connectPgSimple from 'connect-pg-simple'; import { NestExpressApplication } from '@nestjs/platform-express'; +import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); const express = app.getHttpAdapter().getInstance(); + const pgPool = new pg.Pool({ + host: process.env.DATABASE_HOST, + port: +process.env.DATABASE_PORT, + user: process.env.DATABASE_USERNAME, + password: process.env.DATABASE_PASSWORD, + database: process.env.DATABASE_NAME + }); + app.use(helmet()); app.useGlobalPipes(new ValidationPipe({ transform: true })); + app.use( + session({ + secret: 'my-secret', + resave: false, + saveUninitialized: false, + store: new (connectPgSimple(session))({ + pool: pgPool, + createTableIfMissing: true + }) + }), + passport.session() + ); + const assetsDir = path.join(__dirname, '..', 'public'); app.useStaticAssets(assetsDir, { prefix: '/public' }); diff --git a/server/src/templates/home.njk b/server/src/templates/home.njk new file mode 100644 index 00000000..54bf74cf --- /dev/null +++ b/server/src/templates/home.njk @@ -0,0 +1,9 @@ +{% extends '_base.njk' %} + +{% block body %} +

Hello, world!

+ +
+ +
+{% endblock body %} diff --git a/server/src/templates/login.njk b/server/src/templates/login.njk index adbbaaef..ca6c913c 100644 --- a/server/src/templates/login.njk +++ b/server/src/templates/login.njk @@ -7,11 +7,15 @@
-
+

Connexion

+ {% if user %} +

User: {{ user|dump }}

+ {% endif %} +
From bfef892c8a9f2395e47406af76141c73603d62ee Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Sat, 16 Sep 2023 15:51:58 +0200 Subject: [PATCH 04/49] Add e2e tests using Playwright --- Makefile | 7 +- server/e2e/login.spec.js | 22 + server/package-lock.json | 3200 +++++++---------- server/package.json | 3 +- server/playwright.config.ts | 16 + .../User/Controller/LogoutController.ts | 4 +- .../User/Security/UserSerializer.ts | 24 +- server/src/templates/login.njk | 8 +- 8 files changed, 1420 insertions(+), 1864 deletions(-) create mode 100644 server/e2e/login.spec.js create mode 100644 server/playwright.config.ts diff --git a/Makefile b/Makefile index eb6638a3..0a8d8cbc 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ install-deps: ## Install dependencies cd server && npm ci install-dev: up ## Install local development dependencies and services + cd server && npx playwright install firefox make database-test-init start: up ## Start @@ -49,6 +50,9 @@ test: ## Run tests test-watch: ## Run tests in watch mode cd server && npm run test:watch +test-e2e: + cd server && npx playwright test + test-cov: ## Run tests with coverage enabled cd server && npm run test:cov @@ -79,6 +83,7 @@ ci: ## Run CI checks make install make build make database-migrate - make test-api-cov + make test-cov make database-test-init + make test-e2e make linter diff --git a/server/e2e/login.spec.js b/server/e2e/login.spec.js new file mode 100644 index 00000000..e39ff89c --- /dev/null +++ b/server/e2e/login.spec.js @@ -0,0 +1,22 @@ +import { test, expect } from '@playwright/test'; + +test('redirects to login', async ({ page }) => { + await page.goto('/'); + await page.waitForURL('/login'); +}); + +test('logs in', async ({ page }) => { + await page.goto('/login'); + + const emailField = page.getByRole('textbox', { name: 'Adresse email' }); + await expect(emailField).toHaveAttribute('type', 'email'); + await emailField.fill('john@doe.com'); + + const passwordField = page.getByRole('textbox', { name: 'Mot de passe' }); + await expect(passwordField).toHaveAttribute('type', 'password'); + await passwordField.fill('john'); + + await page.getByRole('button', { name: 'Se connecter' }).click(); + + await page.waitForURL('/'); +}) diff --git a/server/package-lock.json b/server/package-lock.json index e87bc242..7d3f6f32 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -43,10 +43,11 @@ "@nestjs/cli": "^9.3.0", "@nestjs/schematics": "^9.0.3", "@nestjs/testing": "^9.2.0", + "@playwright/test": "^1.38.0", "@types/connect-pg-simple": "^7.0.1", "@types/express": "^4.17.3", "@types/express-session": "^1.17.7", - "@types/jest": "25.1.4", + "@types/jest": "^29.5.5", "@types/node": "^13.9.1", "@types/nunjucks": "^3.2.3", "@types/passport-http-bearer": "^1.0.35", @@ -461,9 +462,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -494,18 +495,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.19", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.19.tgz", + "integrity": "sha512-Tinq7ybnEPFFXhlYOYFiSjespWQk0dq2dRNAiMdRTOYQzEGqnnNyrTxPYHP5r6wGjlF1rFgABdDV0g8EwD6Qbg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -611,9 +612,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.3.tgz", - "integrity": "sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==", + "version": "7.22.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", + "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -683,12 +684,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -785,12 +786,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -858,13 +859,13 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.2.tgz", - "integrity": "sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==", + "version": "7.22.19", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz", + "integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.19", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1177,16 +1178,16 @@ } }, "node_modules/@jest/console": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz", - "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -1194,37 +1195,37 @@ } }, "node_modules/@jest/core": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz", - "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "dependencies": { - "@jest/console": "^29.3.1", - "@jest/reporters": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.2.0", - "jest-config": "^29.3.1", - "jest-haste-map": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.3.1", - "jest-resolve-dependencies": "^29.3.1", - "jest-runner": "^29.3.1", - "jest-runtime": "^29.3.1", - "jest-snapshot": "^29.3.1", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", - "jest-watcher": "^29.3.1", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "pretty-format": "^29.3.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -1249,92 +1250,6 @@ "node": ">=8" } }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/core/node_modules/jest-config": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", - "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.3.1", - "@jest/types": "^29.3.1", - "babel-jest": "^29.3.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.3.1", - "jest-environment-node": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.3.1", - "jest-runner": "^29.3.1", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.3.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/@jest/core/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/@jest/core/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1347,111 +1262,99 @@ "node": ">=8" } }, - "node_modules/@jest/core/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@jest/environment": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", - "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.3.1" + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz", - "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "dependencies": { - "expect": "^29.3.1", - "jest-snapshot": "^29.3.1" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", - "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "dependencies": { - "jest-get-type": "^29.2.0" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", - "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "dependencies": { - "@jest/types": "^29.3.1", - "@sinonjs/fake-timers": "^9.1.2", + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.3.1", - "jest-mock": "^29.3.1", - "jest-util": "^29.3.1" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", - "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.3.1", - "@jest/expect": "^29.3.1", - "@jest/types": "^29.3.1", - "jest-mock": "^29.3.1" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz", - "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -1459,13 +1362,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1", - "jest-worker": "^29.3.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -1492,14 +1395,30 @@ "node": ">=8" } }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@jest/reporters/node_modules/jest-worker": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", - "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.3.1", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -1507,6 +1426,21 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@jest/reporters/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1535,24 +1469,24 @@ } }, "node_modules/@jest/schemas": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", - "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.24.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", - "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, @@ -1561,13 +1495,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz", - "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "dependencies": { - "@jest/console": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1576,14 +1510,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz", - "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "dependencies": { - "@jest/test-result": "^29.3.1", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -1591,38 +1525,38 @@ } }, "node_modules/@jest/transform": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", - "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.3.1", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", - "write-file-atomic": "^4.0.1" + "write-file-atomic": "^4.0.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/types": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", - "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1682,13 +1616,13 @@ "devOptional": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@nestjs/cli": { @@ -2227,28 +2161,43 @@ "node": ">=4" } }, + "node_modules/@playwright/test": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.0.tgz", + "integrity": "sha512-xis/RXXsLxwThKnlIXouxmIvvT3zvQj1JE39GsNieMUrMpb3/GySHDh2j8itCG22qKVD4MYLBp7xB73cUW/UUw==", + "dev": true, + "dependencies": { + "playwright": "1.38.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "node_modules/@sinonjs/commons": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz", - "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "dependencies": { - "@sinonjs/commons": "^1.7.0" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@sqltools/formatter": { @@ -2294,13 +2243,13 @@ } }, "node_modules/@types/babel__core": { - "version": "7.1.20", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", - "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", "dev": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" @@ -2326,12 +2275,12 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", "dev": true, "dependencies": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "node_modules/@types/body-parser": { @@ -2447,9 +2396,9 @@ } }, "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, "dependencies": { "@types/node": "*" @@ -2492,13 +2441,13 @@ } }, "node_modules/@types/jest": { - "version": "25.1.4", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-25.1.4.tgz", - "integrity": "sha512-QDDY2uNAhCV7TMCITrxz+MRk1EizcsevzfeS6LykIlq2V1E5oO4wXG8V2ZEd9w7Snxeeagk46YbMgZ8ESHx3sw==", + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", "dev": true, "dependencies": { - "jest-diff": "^25.1.0", - "pretty-format": "^25.1.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, "node_modules/@types/json-schema": { @@ -2664,12 +2613,6 @@ "node": ">=12" } }, - "node_modules/@types/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", - "dev": true - }, "node_modules/@types/qs": { "version": "6.9.6", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz", @@ -3456,15 +3399,15 @@ "dev": true }, "node_modules/babel-jest": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", - "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "dependencies": { - "@jest/transform": "^29.3.1", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.2.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -3493,9 +3436,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz", - "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -3531,12 +3474,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz", - "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.2.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -3910,9 +3853,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, "node_modules/class-transformer": { @@ -4118,9 +4061,9 @@ } }, "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, "node_modules/color-convert": { @@ -4320,6 +4263,27 @@ "node": ">=10" } }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -4373,10 +4337,18 @@ } }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deep-extend": { "version": "0.6.0", @@ -4412,16 +4384,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", + "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { - "object-keys": "^1.0.12" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/delayed-stream": { @@ -4485,15 +4476,6 @@ "node": ">=0.3.1" } }, - "node_modules/diff-sequences": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", - "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", - "dev": true, - "engines": { - "node": ">= 8.3" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -5394,25 +5376,25 @@ } }, "node_modules/expect": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", - "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/expect/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -5890,13 +5872,14 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6009,6 +5992,18 @@ "node": ">=0.10" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -6043,10 +6038,48 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, "engines": { "node": ">= 0.4" }, @@ -6434,10 +6467,13 @@ } }, "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -6528,13 +6564,13 @@ } }, "node_modules/is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -6553,10 +6589,13 @@ } }, "node_modules/is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -6636,17 +6675,17 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps": { @@ -6696,9 +6735,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -6717,15 +6756,15 @@ } }, "node_modules/jest": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", - "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "dependencies": { - "@jest/core": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.3.1" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" @@ -6743,12 +6782,13 @@ } }, "node_modules/jest-changed-files": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz", - "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "dependencies": { "execa": "^5.0.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" }, "engines": { @@ -6800,28 +6840,29 @@ } }, "node_modules/jest-circus": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz", - "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "dependencies": { - "@jest/environment": "^29.3.1", - "@jest/expect": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.3.1", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-runtime": "^29.3.1", - "jest-snapshot": "^29.3.1", - "jest-util": "^29.3.1", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0", - "pretty-format": "^29.3.1", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -6829,55 +6870,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-circus/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-cli": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz", - "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "dependencies": { - "@jest/core": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.3.1", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", - "prompts": "^2.0.1", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "yargs": "^17.3.1" }, "bin": { @@ -6904,18 +6912,6 @@ "node": ">=8" } }, - "node_modules/jest-cli/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-cli/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -6939,80 +6935,6 @@ "node": ">=8" } }, - "node_modules/jest-cli/node_modules/jest-config": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", - "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.3.1", - "@jest/types": "^29.3.1", - "babel-jest": "^29.3.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.3.1", - "jest-environment-node": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.3.1", - "jest-runner": "^29.3.1", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.3.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-cli/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-cli/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -7039,22 +6961,10 @@ "node": ">=8" } }, - "node_modules/jest-cli/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/jest-cli/node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { "cliui": "^8.0.1", @@ -7078,38 +6988,76 @@ "node": ">=12" } }, - "node_modules/jest-diff": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.5.0.tgz", - "integrity": "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==", + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "dependencies": { - "chalk": "^3.0.0", - "diff-sequences": "^25.2.6", - "jest-get-type": "^25.2.6", - "pretty-format": "^25.5.0" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">= 8.3" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/jest-config/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-config/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/jest-docblock": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", - "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" @@ -7119,103 +7067,62 @@ } }, "node_modules/jest-each": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz", - "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.2.0", - "jest-util": "^29.3.1", - "pretty-format": "^29.3.1" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-each/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-each/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-each/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-environment-node": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz", - "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "dependencies": { - "@jest/environment": "^29.3.1", - "@jest/fake-timers": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.3.1", - "jest-util": "^29.3.1" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", - "dev": true, - "engines": { - "node": ">= 8.3" - } - }, "node_modules/jest-haste-map": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", - "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", - "jest-worker": "^29.3.1", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -7227,13 +7134,13 @@ } }, "node_modules/jest-haste-map/node_modules/jest-worker": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", - "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.3.1", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -7257,152 +7164,88 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz", - "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "dependencies": { - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-leak-detector/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-leak-detector/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-leak-detector/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-matcher-utils": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", - "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-matcher-utils/node_modules/diff-sequences": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", - "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils/node_modules/jest-diff": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", - "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-message-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", - "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.3.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -7410,47 +7253,15 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-mock": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", - "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.3.1" + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -7474,28 +7285,28 @@ } }, "node_modules/jest-regex-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", - "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz", - "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", + "resolve.exports": "^2.0.0", "slash": "^3.0.0" }, "engines": { @@ -7503,43 +7314,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz", - "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "dependencies": { - "jest-regex-util": "^29.2.0", - "jest-snapshot": "^29.3.1" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz", - "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "dependencies": { - "@jest/console": "^29.3.1", - "@jest/environment": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.2.0", - "jest-environment-node": "^29.3.1", - "jest-haste-map": "^29.3.1", - "jest-leak-detector": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-resolve": "^29.3.1", - "jest-runtime": "^29.3.1", - "jest-util": "^29.3.1", - "jest-watcher": "^29.3.1", - "jest-worker": "^29.3.1", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -7548,13 +7359,13 @@ } }, "node_modules/jest-runner/node_modules/jest-worker": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", - "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.3.1", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -7597,31 +7408,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz", - "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.3.1", - "@jest/fake-timers": "^29.3.1", - "@jest/globals": "^29.3.1", - "@jest/source-map": "^29.2.0", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-mock": "^29.3.1", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.3.1", - "jest-snapshot": "^29.3.1", - "jest-util": "^29.3.1", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -7639,105 +7450,69 @@ } }, "node_modules/jest-snapshot": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz", - "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.3.1", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-haste-map": "^29.3.1", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.3.1", - "semver": "^7.3.5" + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-snapshot/node_modules/diff-sequences": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", - "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-diff": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", - "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-snapshot/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -7754,12 +7529,12 @@ } }, "node_modules/jest-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", - "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -7771,34 +7546,22 @@ } }, "node_modules/jest-validate": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz", - "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.2.0", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.3.1" + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-validate/node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -7812,47 +7575,27 @@ } }, "node_modules/jest-validate/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-watcher": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz", - "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "dependencies": { - "@jest/test-result": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.3.1", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { @@ -8124,27 +7867,33 @@ } }, "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "dependencies": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/make-error": { @@ -8660,14 +8409,14 @@ } }, "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -9208,6 +8957,36 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.0.tgz", + "integrity": "sha512-fJGw+HO0YY+fU/F1N57DMO+TmXHTrmr905J05zwAQE9xkuwP/QLDk63rVhmyxh03dYnEhnRbsdbH9B0UVVRB3A==", + "dev": true, + "dependencies": { + "playwright-core": "1.38.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz", + "integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -9270,74 +9049,29 @@ } }, "node_modules/pretty-format": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz", - "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==", - "dev": true, - "dependencies": { - "@jest/types": "^25.5.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - }, - "engines": { - "node": ">= 8.3" - } - }, - "node_modules/pretty-format/node_modules/@jest/types": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", - "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 8.3" - } - }, - "node_modules/pretty-format/node_modules/@types/istanbul-reports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", - "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/pretty-format/node_modules/@types/yargs": { - "version": "15.0.14", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", - "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/pretty-format/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-format/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "node": ">=10" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/process-nextick-args": { @@ -9390,14 +9124,30 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, "engines": { "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -9486,9 +9236,9 @@ } }, "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/readable-stream": { @@ -9615,9 +9365,9 @@ } }, "node_modules/resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, "engines": { "node": ">=10" @@ -11212,9 +10962,9 @@ "peer": true }, "node_modules/v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", @@ -11910,9 +11660,9 @@ } }, "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true }, "@babel/helper-simple-access": { @@ -11934,15 +11684,15 @@ } }, "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.19", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.19.tgz", + "integrity": "sha512-Tinq7ybnEPFFXhlYOYFiSjespWQk0dq2dRNAiMdRTOYQzEGqnnNyrTxPYHP5r6wGjlF1rFgABdDV0g8EwD6Qbg==", "dev": true }, "@babel/helper-validator-option": { @@ -12026,9 +11776,9 @@ } }, "@babel/parser": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.3.tgz", - "integrity": "sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==", + "version": "7.22.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", + "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -12077,12 +11827,12 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -12149,12 +11899,12 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.22.5" } }, "@babel/template": { @@ -12204,13 +11954,13 @@ } }, "@babel/types": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.2.tgz", - "integrity": "sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==", + "version": "7.22.19", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz", + "integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.19", "to-fast-properties": "^2.0.0" } }, @@ -12447,51 +12197,51 @@ "dev": true }, "@jest/console": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz", - "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "requires": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz", - "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "requires": { - "@jest/console": "^29.3.1", - "@jest/reporters": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.2.0", - "jest-config": "^29.3.1", - "jest-haste-map": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.3.1", - "jest-resolve-dependencies": "^29.3.1", - "jest-runner": "^29.3.1", - "jest-runtime": "^29.3.1", - "jest-snapshot": "^29.3.1", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", - "jest-watcher": "^29.3.1", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "pretty-format": "^29.3.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -12502,65 +12252,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "jest-config": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", - "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.3.1", - "@jest/types": "^29.3.1", - "babel-jest": "^29.3.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.3.1", - "jest-environment-node": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.3.1", - "jest-runner": "^29.3.1", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.3.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true - }, - "pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -12569,92 +12260,86 @@ "requires": { "ansi-regex": "^5.0.1" } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true } } }, "@jest/environment": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", - "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "requires": { - "@jest/fake-timers": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.3.1" + "jest-mock": "^29.7.0" } }, "@jest/expect": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz", - "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "requires": { - "expect": "^29.3.1", - "jest-snapshot": "^29.3.1" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" } }, "@jest/expect-utils": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", - "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "requires": { - "jest-get-type": "^29.2.0" + "jest-get-type": "^29.6.3" }, "dependencies": { "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true } } }, "@jest/fake-timers": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", - "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "requires": { - "@jest/types": "^29.3.1", - "@sinonjs/fake-timers": "^9.1.2", + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.3.1", - "jest-mock": "^29.3.1", - "jest-util": "^29.3.1" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" } }, "@jest/globals": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", - "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "requires": { - "@jest/environment": "^29.3.1", - "@jest/expect": "^29.3.1", - "@jest/types": "^29.3.1", - "jest-mock": "^29.3.1" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" } }, "@jest/reporters": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz", - "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -12662,13 +12347,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1", - "jest-worker": "^29.3.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -12681,18 +12366,40 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, + "istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + } + }, "jest-worker": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", - "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.3.1", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -12714,79 +12421,79 @@ } }, "@jest/schemas": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", - "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "requires": { - "@sinclair/typebox": "^0.24.1" + "@sinclair/typebox": "^0.27.8" } }, "@jest/source-map": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", - "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } }, "@jest/test-result": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz", - "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "requires": { - "@jest/console": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz", - "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "requires": { - "@jest/test-result": "^29.3.1", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", - "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.3.1", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", - "write-file-atomic": "^4.0.1" + "write-file-atomic": "^4.0.2" } }, "@jest/types": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", - "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "requires": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -12834,13 +12541,13 @@ "devOptional": true }, "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@nestjs/cli": { @@ -13182,28 +12889,37 @@ "safe-buffer": "^5.1.2" } }, + "@playwright/test": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.0.tgz", + "integrity": "sha512-xis/RXXsLxwThKnlIXouxmIvvT3zvQj1JE39GsNieMUrMpb3/GySHDh2j8itCG22qKVD4MYLBp7xB73cUW/UUw==", + "dev": true, + "requires": { + "playwright": "1.38.0" + } + }, "@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "@sinonjs/commons": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz", - "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "requires": { - "@sinonjs/commons": "^1.7.0" + "@sinonjs/commons": "^3.0.0" } }, "@sqltools/formatter": { @@ -13249,13 +12965,13 @@ } }, "@types/babel__core": { - "version": "7.1.20", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", - "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", "dev": true, "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" @@ -13281,12 +12997,12 @@ } }, "@types/babel__traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", "dev": true, "requires": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "@types/body-parser": { @@ -13402,9 +13118,9 @@ } }, "@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, "requires": { "@types/node": "*" @@ -13447,13 +13163,13 @@ } }, "@types/jest": { - "version": "25.1.4", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-25.1.4.tgz", - "integrity": "sha512-QDDY2uNAhCV7TMCITrxz+MRk1EizcsevzfeS6LykIlq2V1E5oO4wXG8V2ZEd9w7Snxeeagk46YbMgZ8ESHx3sw==", + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", "dev": true, "requires": { - "jest-diff": "^25.1.0", - "pretty-format": "^25.1.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, "@types/json-schema": { @@ -13606,12 +13322,6 @@ } } }, - "@types/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", - "dev": true - }, "@types/qs": { "version": "6.9.6", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz", @@ -14219,15 +13929,15 @@ "dev": true }, "babel-jest": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", - "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "requires": { - "@jest/transform": "^29.3.1", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.2.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -14247,9 +13957,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz", - "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -14279,12 +13989,12 @@ } }, "babel-preset-jest": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz", - "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^29.2.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -14526,9 +14236,9 @@ "dev": true }, "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, "class-transformer": { @@ -14680,9 +14390,9 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, "color-convert": { @@ -14834,6 +14544,21 @@ "yaml": "^1.10.0" } }, + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + } + }, "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -14876,10 +14601,11 @@ } }, "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "requires": {} }, "deep-extend": { "version": "0.6.0", @@ -14906,13 +14632,26 @@ "clone": "^1.0.2" } }, + "define-data-property": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", + "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" } }, "delayed-stream": { @@ -14954,12 +14693,6 @@ "optional": true, "peer": true }, - "diff-sequences": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", - "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", - "dev": true - }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -15632,22 +15365,22 @@ "dev": true }, "expect": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", - "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "requires": { - "@jest/expect-utils": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "dependencies": { "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true } } @@ -16017,13 +15750,14 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" } }, "get-package-type": { @@ -16102,6 +15836,15 @@ "resolved": "https://registry.npmjs.org/google-libphonenumber/-/google-libphonenumber-3.2.19.tgz", "integrity": "sha512-zevRvpUuc88wIXa+ijlMprAc8SrldUtYY2vQpfymmxyZ2ksct6gFrGxccpo28+zjvjK51VoSUaDUHS24XYp6dA==" }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -16127,10 +15870,33 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } }, "has-unicode": { "version": "2.0.1", @@ -16410,10 +16176,13 @@ } }, "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-extglob": { "version": "2.1.1", @@ -16468,13 +16237,13 @@ "dev": true }, "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" + "has-tostringtag": "^1.0.0" } }, "is-stream": { @@ -16484,10 +16253,13 @@ "dev": true }, "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-symbol": { "version": "1.0.3", @@ -16542,13 +16314,13 @@ } }, "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "requires": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, @@ -16587,9 +16359,9 @@ } }, "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -16602,24 +16374,25 @@ "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==" }, "jest": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", - "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "requires": { - "@jest/core": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.3.1" + "jest-cli": "^29.7.0" } }, "jest-changed-files": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz", - "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "requires": { "execa": "^5.0.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" }, "dependencies": { @@ -16655,74 +16428,49 @@ } }, "jest-circus": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz", - "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "requires": { - "@jest/environment": "^29.3.1", - "@jest/expect": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.3.1", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-runtime": "^29.3.1", - "jest-snapshot": "^29.3.1", - "jest-util": "^29.3.1", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0", - "pretty-format": "^29.3.1", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } } }, "jest-cli": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz", - "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "requires": { - "@jest/core": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.3.1", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", - "prompts": "^2.0.1", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "yargs": "^17.3.1" }, "dependencies": { @@ -16732,12 +16480,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, "cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -16755,59 +16497,6 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "jest-config": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", - "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.3.1", - "@jest/types": "^29.3.1", - "babel-jest": "^29.3.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.3.1", - "jest-environment-node": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.3.1", - "jest-runner": "^29.3.1", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.3.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true - }, - "pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -16828,16 +16517,10 @@ "ansi-regex": "^5.0.1" } }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, "yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { "cliui": "^8.0.1", @@ -16857,131 +16540,122 @@ } } }, - "jest-diff": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.5.0.tgz", - "integrity": "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==", + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "requires": { - "chalk": "^3.0.0", - "diff-sequences": "^25.2.6", - "jest-get-type": "^25.2.6", - "pretty-format": "^25.5.0" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true } } }, "jest-docblock": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", - "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz", - "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "requires": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.2.0", - "jest-util": "^29.3.1", - "pretty-format": "^29.3.1" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true - }, - "pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true } } }, "jest-environment-node": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz", - "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "requires": { - "@jest/environment": "^29.3.1", - "@jest/fake-timers": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.3.1", - "jest-util": "^29.3.1" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" } }, - "jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", - "dev": true - }, "jest-haste-map": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", - "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "requires": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", - "jest-worker": "^29.3.1", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, "dependencies": { "jest-worker": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", - "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.3.1", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } @@ -16998,158 +16672,87 @@ } }, "jest-leak-detector": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz", - "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "requires": { - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true - }, - "pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true } } }, "jest-matcher-utils": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", - "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, "diff-sequences": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", - "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, "jest-diff": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", - "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" } }, "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true - }, - "pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true } } }, "jest-message-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", - "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.3.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } } }, "jest-mock": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", - "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "requires": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.3.1" + "jest-util": "^29.7.0" } }, "jest-pnp-resolver": { @@ -17160,75 +16763,75 @@ "requires": {} }, "jest-regex-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", - "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true }, "jest-resolve": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz", - "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", + "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz", - "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "requires": { - "jest-regex-util": "^29.2.0", - "jest-snapshot": "^29.3.1" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" } }, "jest-runner": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz", - "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "requires": { - "@jest/console": "^29.3.1", - "@jest/environment": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.2.0", - "jest-environment-node": "^29.3.1", - "jest-haste-map": "^29.3.1", - "jest-leak-detector": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-resolve": "^29.3.1", - "jest-runtime": "^29.3.1", - "jest-util": "^29.3.1", - "jest-watcher": "^29.3.1", - "jest-worker": "^29.3.1", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, "dependencies": { "jest-worker": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", - "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.3.1", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } @@ -17261,31 +16864,31 @@ } }, "jest-runtime": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz", - "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==", - "dev": true, - "requires": { - "@jest/environment": "^29.3.1", - "@jest/fake-timers": "^29.3.1", - "@jest/globals": "^29.3.1", - "@jest/source-map": "^29.2.0", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-mock": "^29.3.1", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.3.1", - "jest-snapshot": "^29.3.1", - "jest-util": "^29.3.1", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -17299,82 +16902,55 @@ } }, "jest-snapshot": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz", - "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.3.1", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-haste-map": "^29.3.1", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.3.1", - "semver": "^7.3.5" + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, "diff-sequences": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", - "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, "jest-diff": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", - "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" } }, "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true - }, - "pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true }, "semver": { @@ -17389,12 +16965,12 @@ } }, "jest-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", - "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "requires": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -17403,25 +16979,19 @@ } }, "jest-validate": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz", - "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "requires": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.2.0", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.3.1" + "pretty-format": "^29.7.0" }, "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -17429,43 +16999,26 @@ "dev": true }, "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true - }, - "pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true } } }, "jest-watcher": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz", - "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "requires": { - "@jest/test-result": "^29.3.1", - "@jest/types": "^29.3.1", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.3.1", + "jest-util": "^29.7.0", "string-length": "^4.0.1" } }, @@ -17678,19 +17231,22 @@ } }, "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "requires": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "dependencies": { "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -18105,14 +17661,14 @@ "dev": true }, "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, @@ -18504,6 +18060,22 @@ "find-up": "^4.0.0" } }, + "playwright": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.0.tgz", + "integrity": "sha512-fJGw+HO0YY+fU/F1N57DMO+TmXHTrmr905J05zwAQE9xkuwP/QLDk63rVhmyxh03dYnEhnRbsdbH9B0UVVRB3A==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.38.0" + } + }, + "playwright-core": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz", + "integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g==", + "dev": true + }, "pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -18545,63 +18117,21 @@ "dev": true }, "pretty-format": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz", - "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "requires": { - "@jest/types": "^25.5.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "dependencies": { - "@jest/types": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", - "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, - "@types/istanbul-reports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", - "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" - } - }, - "@types/yargs": { - "version": "15.0.14", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", - "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } } } }, @@ -18646,9 +18176,15 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true + }, + "pure-rand": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", "dev": true }, "qs": { @@ -18707,9 +18243,9 @@ } }, "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "readable-stream": { @@ -18805,9 +18341,9 @@ "dev": true }, "resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true }, "restore-cursor": { @@ -19921,9 +19457,9 @@ "peer": true }, "v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.12", diff --git a/server/package.json b/server/package.json index 7e11451c..c9620bf5 100644 --- a/server/package.json +++ b/server/package.json @@ -59,10 +59,11 @@ "@nestjs/cli": "^9.3.0", "@nestjs/schematics": "^9.0.3", "@nestjs/testing": "^9.2.0", + "@playwright/test": "^1.38.0", "@types/connect-pg-simple": "^7.0.1", "@types/express": "^4.17.3", "@types/express-session": "^1.17.7", - "@types/jest": "25.1.4", + "@types/jest": "^29.5.5", "@types/node": "^13.9.1", "@types/nunjucks": "^3.2.3", "@types/passport-http-bearer": "^1.0.35", diff --git a/server/playwright.config.ts b/server/playwright.config.ts new file mode 100644 index 00000000..5ec41ba4 --- /dev/null +++ b/server/playwright.config.ts @@ -0,0 +1,16 @@ +import type { PlaywrightTestConfig } from "@playwright/test"; + +const config: PlaywrightTestConfig = { + testDir: "./e2e", + retries: 0, + timeout: 5 * 1000, + use: { + baseURL: "http://localhost:3000", + browserName: "firefox", + headless: true, + screenshot: "only-on-failure", + video: "on-first-retry", + }, +}; + +export default config; diff --git a/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts index 94c83579..d3c9133f 100644 --- a/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts +++ b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts @@ -10,7 +10,7 @@ import { Request, Response } from 'express'; @Controller('logout') export class LogoutController { @Post() - public async post(@Req() req: Request, @Res() res: Response) { + public async post(@Req() req: Request, @Res() res: Response): Promise { const err = await new Promise(resolve => { req.logout(err => resolve(err)); }); @@ -19,6 +19,6 @@ export class LogoutController { throw new InternalServerErrorException('Failed to log out'); } - res.redirect('/login', 303); + res.redirect(303, '/login'); } } diff --git a/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts b/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts index c77051c1..145973b5 100644 --- a/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts +++ b/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts @@ -1,34 +1,14 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { PassportSerializer } from '@nestjs/passport'; import { AuthenticatedView } from 'src/Application/HumanResource/User/View/AuthenticatedView'; -import { IUserRepository } from 'src/Domain/HumanResource/User/Repository/IUserRepository'; @Injectable() export class UserSerializer extends PassportSerializer { - constructor( - @Inject('IUserRepository') - private readonly userRepository: IUserRepository - ) { - super(); - } - serializeUser(user: AuthenticatedView, done: Function) { done(null, user); } - public async deserializeUser( - { email }: AuthenticatedView, - done: Function - ): Promise { - const user = await this.userRepository.findOneByEmail(email); - - if (!user) { - done( - `Could not deserialize user: user with ${email} could not be found`, - null - ); - } - + public deserializeUser(user: AuthenticatedView, done: Function): void { done(null, user); } } diff --git a/server/src/templates/login.njk b/server/src/templates/login.njk index ca6c913c..6dfe2b54 100644 --- a/server/src/templates/login.njk +++ b/server/src/templates/login.njk @@ -12,18 +12,14 @@ Connexion - {% if user %} -

User: {{ user|dump }}

- {% endif %} -
- +
- +
From 261324dedd0a89ff0fe381a8c15eb94c58cf2fb0 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Sat, 16 Sep 2023 19:11:46 +0200 Subject: [PATCH 05/49] Add app shell, add named routes --- .../Home/Controller/HomeController.ts | 4 +- .../User/Controller/LoginController.ts | 2 +- .../User/Controller/LogoutController.ts | 2 + .../User/Security/IsAuthenticatedGuard.ts | 10 +- .../ExceptionFilter/AuthRequiredFilter.ts | 18 ++ .../ExceptionFilter/UnexpectedErrorFilter.ts | 12 + .../Infrastructure/NestJS/Routing/WithName.ts | 50 +++++ server/src/Infrastructure/Nunjucks/index.ts | 55 +++++ server/src/app.module.ts | 22 +- server/src/main.ts | 17 +- server/src/public/styles.css | 207 ++++++++++++++++-- server/src/templates/components/header.njk | 25 +++ server/src/templates/components/nav.njk | 76 +++++++ server/src/templates/errors/error.njk | 22 ++ server/src/templates/home.njk | 9 - server/src/templates/icons/calendar.njk | 4 + server/src/templates/icons/crm.njk | 4 + server/src/templates/icons/dashboard.njk | 5 + server/src/templates/icons/group.njk | 8 + server/src/templates/icons/logout.njk | 5 + server/src/templates/icons/user.njk | 4 + server/src/templates/{ => layouts}/_base.njk | 1 + server/src/templates/layouts/app.njk | 16 ++ server/src/templates/layouts/blank.njk | 1 + server/src/templates/pages/home.njk | 5 + server/src/templates/{ => pages}/login.njk | 18 +- 26 files changed, 552 insertions(+), 50 deletions(-) create mode 100644 server/src/Infrastructure/NestJS/ExceptionFilter/AuthRequiredFilter.ts create mode 100644 server/src/Infrastructure/NestJS/ExceptionFilter/UnexpectedErrorFilter.ts create mode 100644 server/src/Infrastructure/NestJS/Routing/WithName.ts create mode 100644 server/src/Infrastructure/Nunjucks/index.ts create mode 100644 server/src/templates/components/header.njk create mode 100644 server/src/templates/components/nav.njk create mode 100644 server/src/templates/errors/error.njk delete mode 100644 server/src/templates/home.njk create mode 100644 server/src/templates/icons/calendar.njk create mode 100644 server/src/templates/icons/crm.njk create mode 100644 server/src/templates/icons/dashboard.njk create mode 100644 server/src/templates/icons/group.njk create mode 100644 server/src/templates/icons/logout.njk create mode 100644 server/src/templates/icons/user.njk rename server/src/templates/{ => layouts}/_base.njk (92%) create mode 100644 server/src/templates/layouts/app.njk create mode 100644 server/src/templates/layouts/blank.njk create mode 100644 server/src/templates/pages/home.njk rename server/src/templates/{ => pages}/login.njk (54%) diff --git a/server/src/Infrastructure/Home/Controller/HomeController.ts b/server/src/Infrastructure/Home/Controller/HomeController.ts index bb88a667..278e568d 100644 --- a/server/src/Infrastructure/Home/Controller/HomeController.ts +++ b/server/src/Infrastructure/Home/Controller/HomeController.ts @@ -1,11 +1,13 @@ import { Controller, Get, Render, UseGuards } from '@nestjs/common'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/NestJS/Routing/WithName'; @Controller('') @UseGuards(IsAuthenticatedGuard) export class HomeController { @Get() - @Render('home') + @WithName('home') + @Render('pages/home') public get() { return {}; } diff --git a/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts b/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts index 4d012726..53b1c8eb 100644 --- a/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts +++ b/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts @@ -5,7 +5,7 @@ import { LocalAuthGuard } from '../Security/LocalAuthGuard'; @Controller('login') export class LoginController { @Get() - @Render('login') + @Render('pages/login') public get() { return {}; } diff --git a/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts index d3c9133f..f45ad0ad 100644 --- a/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts +++ b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts @@ -6,10 +6,12 @@ import { Res } from '@nestjs/common'; import { Request, Response } from 'express'; +import { WithName } from 'src/Infrastructure/NestJS/Routing/WithName'; @Controller('logout') export class LogoutController { @Post() + @WithName('logout') public async post(@Req() req: Request, @Res() res: Response): Promise { const err = await new Promise(resolve => { req.logout(err => resolve(err)); diff --git a/server/src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard.ts b/server/src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard.ts index bcc83198..b80cc9e7 100644 --- a/server/src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard.ts +++ b/server/src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard.ts @@ -1,17 +1,11 @@ import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; -import { Request, Response } from 'express'; +import { Request } from 'express'; @Injectable() export class IsAuthenticatedGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const req = context.switchToHttp().getRequest() as Request; - if (!req.user) { - const res = context.switchToHttp().getResponse() as Response; - res.redirect(303, '/login'); - return false; - } - - return true; + return !!req.user; } } diff --git a/server/src/Infrastructure/NestJS/ExceptionFilter/AuthRequiredFilter.ts b/server/src/Infrastructure/NestJS/ExceptionFilter/AuthRequiredFilter.ts new file mode 100644 index 00000000..3d60e280 --- /dev/null +++ b/server/src/Infrastructure/NestJS/ExceptionFilter/AuthRequiredFilter.ts @@ -0,0 +1,18 @@ +import { + ExceptionFilter, + Catch, + ArgumentsHost, + UnauthorizedException, + HttpException, + ForbiddenException +} from '@nestjs/common'; +import { Response } from 'express'; + +@Catch(UnauthorizedException, ForbiddenException) +export class AuthRequiredFilter implements ExceptionFilter { + catch(exception: HttpException, host: ArgumentsHost): void { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + response.status(exception.getStatus()).redirect('/login', 303); + } +} diff --git a/server/src/Infrastructure/NestJS/ExceptionFilter/UnexpectedErrorFilter.ts b/server/src/Infrastructure/NestJS/ExceptionFilter/UnexpectedErrorFilter.ts new file mode 100644 index 00000000..b27a1187 --- /dev/null +++ b/server/src/Infrastructure/NestJS/ExceptionFilter/UnexpectedErrorFilter.ts @@ -0,0 +1,12 @@ +import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common'; +import { Response } from 'express'; + +@Catch(Error) +export class UnexpectedErrorFilter implements ExceptionFilter { + catch(error: unknown, host: ArgumentsHost): void { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + response.render('errors/error', { error }); + response.statusCode = 500; + } +} diff --git a/server/src/Infrastructure/NestJS/Routing/WithName.ts b/server/src/Infrastructure/NestJS/Routing/WithName.ts new file mode 100644 index 00000000..bc22193f --- /dev/null +++ b/server/src/Infrastructure/NestJS/Routing/WithName.ts @@ -0,0 +1,50 @@ +import { INestApplication } from '@nestjs/common'; +import { DiscoveryService } from '@nestjs/core'; +import { PATH_METADATA } from '@nestjs/common/constants'; + +const ROUTE_NAME_METADATA = '__route_name__'; + +export function WithName(routeName: string | Symbol): MethodDecorator { + return ( + _target: object, + _key: string | symbol, + descriptor: TypedPropertyDescriptor + ) => { + Reflect.defineMetadata(ROUTE_NAME_METADATA, routeName, descriptor.value); + return descriptor; + }; +} + +export type NamedRoute = { + name: string; + path: string; +}; + +export function getNamedRoutes(app: INestApplication): NamedRoute[] { + const namedRoutes: NamedRoute[] = []; + + app + .get(DiscoveryService) + .getControllers() + .forEach(controller => { + const rootPath = Reflect.getMetadata(PATH_METADATA, controller.metatype); + Object.getOwnPropertyNames(controller.instance.__proto__).forEach( + methodName => { + const method = controller.instance.__proto__[methodName]; + const name = Reflect.getMetadata(ROUTE_NAME_METADATA, method); + if (name) { + const path = Reflect.getMetadata( + PATH_METADATA, + controller.instance.__proto__[methodName] + ); + namedRoutes.push({ + name, + path: `/${rootPath}${path === '/' ? '' : path}` + }); + } + } + ); + }); + + return namedRoutes; +} diff --git a/server/src/Infrastructure/Nunjucks/index.ts b/server/src/Infrastructure/Nunjucks/index.ts new file mode 100644 index 00000000..c0198931 --- /dev/null +++ b/server/src/Infrastructure/Nunjucks/index.ts @@ -0,0 +1,55 @@ +import { NestExpressApplication } from '@nestjs/platform-express'; +import { NextFunction, Request, Response } from 'express'; +import { FileSystemLoader, Environment, TemplateCallback } from 'nunjucks'; +import { getNamedRoutes } from '../NestJS/Routing/WithName'; + +type ContextProcessorFn = ( + ctx: Record, + req: Request, + res: Response +) => void; + +export const nunjucks = ( + app: NestExpressApplication, + { watch } = { watch: false } +) => { + const express = app.getHttpAdapter().getInstance(); + + const loader = new FileSystemLoader(express.get('views'), { watch }); + const env = new Environment(loader); + + const engine = ( + name: string, + ctx: Record, + cb: TemplateCallback + ) => { + env.render(name, { ...ctx, ...ctx._locals.njkCtx }, cb); + }; + + const ctxProcessors: ContextProcessorFn[] = [ + (ctx, req, _res) => { + ctx.req = req; + ctx.path = (name: string) => urls[name] ?? '#'; + } + ]; + + const urls = {}; + + getNamedRoutes(app).forEach(({ name, path }) => { + urls[name] = path; + }); + + app.use((req: Request, res: Response, next: NextFunction): void => { + const ctx = (res.locals.njkCtx = res.locals.njkCtx ?? {}); + ctxProcessors.forEach(fn => fn(ctx, req, res)); + next(); + }); + + return { + env, + engine, + contextProcessor: (fn: ContextProcessorFn) => { + ctxProcessors.push(fn); + } + }; +}; diff --git a/server/src/app.module.ts b/server/src/app.module.ts index d6fa7cc8..3101c87b 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -1,4 +1,5 @@ import { Module } from '@nestjs/common'; +import { APP_FILTER, DiscoveryModule } from '@nestjs/core'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ConfigModule } from '@nestjs/config'; import { HomeModule } from './Infrastructure/Home/home.module'; @@ -9,11 +10,27 @@ import { FairCalendarModule } from './Infrastructure/FairCalendar/faircalendar.m import { FileModule } from './Infrastructure/File/file.module'; import { HumanResourceModule } from './Infrastructure/HumanResource/humanResource.module'; import { SettingsModule } from './Infrastructure/Settings/settings.module'; - +import { UnexpectedErrorFilter } from './Infrastructure/NestJS/ExceptionFilter/UnexpectedErrorFilter'; +import { AuthRequiredFilter } from './Infrastructure/NestJS/ExceptionFilter/AuthRequiredFilter'; import { dataSourceOptions } from './datasource'; +const providers = []; + +if (process.env.NODE_ENV !== 'production') { + providers.push({ + provide: APP_FILTER, + useClass: UnexpectedErrorFilter + }); +} + +providers.push({ + provide: APP_FILTER, + useClass: AuthRequiredFilter +}); + @Module({ imports: [ + DiscoveryModule, TypeOrmModule.forRoot(dataSourceOptions), ConfigModule.forRoot(), HomeModule, @@ -24,6 +41,7 @@ import { dataSourceOptions } from './datasource'; ProjectModule, TaskModule, SettingsModule - ] + ], + providers }) export class AppModule {} diff --git a/server/src/main.ts b/server/src/main.ts index 00570c65..7933bc44 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -4,17 +4,18 @@ import * as pg from 'pg'; import { NestFactory } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; import * as helmet from 'helmet'; -import * as nunjucks from 'nunjucks'; import * as session from 'express-session'; import * as connectPgSimple from 'connect-pg-simple'; import { NestExpressApplication } from '@nestjs/platform-express'; import { AppModule } from './app.module'; +import { nunjucks } from './Infrastructure/Nunjucks'; async function bootstrap() { + const isProd = process.env.NODE_ENV === 'production'; + const app = await NestFactory.create(AppModule); - const express = app.getHttpAdapter().getInstance(); - const pgPool = new pg.Pool({ + const sessionPgPool = new pg.Pool({ host: process.env.DATABASE_HOST, port: +process.env.DATABASE_PORT, user: process.env.DATABASE_USERNAME, @@ -31,7 +32,7 @@ async function bootstrap() { resave: false, saveUninitialized: false, store: new (connectPgSimple(session))({ - pool: pgPool, + pool: sessionPgPool, createTableIfMissing: true }) }), @@ -42,8 +43,14 @@ async function bootstrap() { app.useStaticAssets(assetsDir, { prefix: '/public' }); const viewsDir = path.join(__dirname, '..', 'templates'); - nunjucks.configure(viewsDir, { express }); app.setBaseViewsDir(viewsDir); + + const njk = nunjucks(app, { watch: !isProd }); + njk.env.addFilter('translate', key => key); + njk.contextProcessor((ctx, _req, _res) => { + ctx.asset = (path: string) => `/public/${path}`; + }); + app.engine('njk', njk.engine); app.setViewEngine('njk'); await app.listen(3000, '0.0.0.0'); diff --git a/server/src/public/styles.css b/server/src/public/styles.css index 13b8d6e6..f6b9431d 100644 --- a/server/src/public/styles.css +++ b/server/src/public/styles.css @@ -1,11 +1,17 @@ -@layer reset, defaults, components, utilities; +@layer reset, defaults, layouts, components, utilities; :root { /* Spacing */ --v: 0.25rem; --w: 0.5rem; /* Fonts */ - --font-default: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + --font-default: Inter, system-ui, -apple-system, BlinkMacSystemFont, + 'Segoe UI', Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + --font-size-md: 1.1rem; + --font-size-sm: calc(0.8 * var(--font-size-md)); + --font-size-lg: calc(1.2 * var(--font-size-md)); + --font-size-default: var(--font-size-md); /* Colors */ --background-default: #ffffff; --background-alt-grey: #f9fafb; @@ -15,7 +21,9 @@ --text-on-background-action-violet: #ffffff; --text-danger: #ff0000; /* Shadows */ - --shadow-default: rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 20px 25px -5px, rgba(0, 0, 0, 0.1) 0px 8px 10px -6px; + --shadow-default: rgba(0, 0, 0, 0) 0px 0px 0px 0px, + rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 20px 25px -5px, + rgba(0, 0, 0, 0.1) 0px 8px 10px -6px; } /* Dark mode */ @@ -97,6 +105,7 @@ background-color: var(--background-default); color: var(--text-on-background-default); font-family: var(--font-default); + font-size: var(--font-size-default); } h1 { @@ -115,63 +124,231 @@ button:not(:disabled):hover { background-color: var(--hover-tint); } + + a { + color: inherit; + } + + a:visited { + color: inherit; + } +} + +@layer layouts { + .pc-app { + display: grid; + grid-template-areas: + 'nav header' + 'nav main'; + grid-template-columns: auto 1fr; + grid-template-rows: auto 1fr; + height: 100vh; + background-color: var(--background-alt-grey); + } + + .pc-app__sidebar { + grid-area: nav; + background-color: var(--background-default); + } + + .pc-app__content { + padding: calc(3 * var(--w)); + } } @layer components { - .c-card { + .pc-card { background-color: var(--background-default); box-shadow: var(--shadow-default); } - .c-input-group { + .pc-input-group { margin-bottom: calc(2 * var(--w)); } - .c-input-group > input { + .pc-input-group > input { display: block; width: 100%; } - .c-input-group > label { + .pc-input-group > label { margin-bottom: var(--v); } - .c-btn { + .pc-btn { --hover-tint: var(--background-action-violet-hover); border: none; padding: var(--w) calc(2 * var(--w)); background-color: var(--background-action-violet); color: var(--text-on-background-action-violet); } - .c-btn:hover { + .pc-btn:hover { background-color: var(--hover-tint); } + + .pc-nav { + overflow-y: auto; + padding: calc(4 * var(--v)) 0; + } + + .pc-nav ul { + list-style-type: none; + padding: 0; + width: 100%; + } + + .pc-nav ul li { + position: relative; + padding: calc(3 * var(--v)) calc(3 * var(--v)); + } + + .pc-nav ul li ul { + padding: calc(2 * var(--v)); + margin-top: calc(2 * var(--v)); + overflow: hidden; + font-size: var(--font-size-sm); + box-shadow: var(--shadow-inner); + background-color: var(--background-alt-grey); + } + + .pc-nav ul li ul li { + padding: calc(2 * var(--v)) calc(1 * var(--v)); + } + + .pc-nav__decoration { + position: absolute; + inset: 0; + left: 0; + width: var(--v); + background-color: var(--background-action-violet); + border-top-right-radius: var(--radius-lg); + border-bottom-right-radius: var(--radius-lg); + } + + .pc-nav a, + .pc-nav details > summary { + display: inline-flex; + column-gap: calc(2 * var(--v)); + align-items: center; + width: 100%; + font-size: var(--font-size-sm); + } + + .pc-nav details > summary { + cursor: pointer; + } + + .pc-nav a[aria-current='page'] { + font-weight: bold; + } + + .pc-nav details summary > svg, + svg.pc-icon--sm { + display: inline; + } + + .pc-brand { + display: inline-flex; + align-items: center; + column-gap: calc(3 * var(--v)); + padding: calc(6 * var(--v)); + font-size: var(--font-size-lg); + font-weight: bold; + } + + .pc-brand__logo { + width: calc(8 * var(--v)); + height: calc(8 * var(--v)); + } + + .pc-icon--danger { + color: var(--text-danger); + } + + .pc-icon--sm { + width: calc(6 * var(--v)); + height: calc(6 * var(--v)); + } + + .pc-icon--left { + display: flex; + align-items: center; + } + + .pc-icon--left > .pc-icon { + margin-inline-end: calc(2 * var(--v)); + } + + .pc-header { + grid-area: header; + background-color: var(--background-default); + display: flex; + justify-content: end; + padding: calc(3 * var(--v)); + } + + details.pc-dropdown { + position: relative; + } + + details.pc-dropdown > summary { + cursor: pointer; + } + + details.pc-dropdown .pc-dropdown__content { + z-index: 1; + position: absolute; + background-color: var(--background-default); + box-shadow: var(--shadow-default); + right: 0; + width: max-content; + padding: calc(3 * var(--v)); + } + + ul.pc-dropdown__content > li { + padding-block: calc(2 * var(--v)); + } + + .pc-raw-list { + list-style-type: none; + margin: 0; + padding: 0; + } + + button.pc-link { + background: none; + border: none; + padding: 0; + color: var(--text-link); + cursor: pointer; + text-decoration: underline; + } } @layer utilities { - .u-center { + .pc-center { display: grid; place-items: center; } - .u-background-alt-grey { + .pc-background-alt-grey { background-color: var(--background-alt-grey); } - .u-cols--even { + .pc-cols--even { display: grid; grid-template-columns: repeat(var(--cols), 1fr); } - .u-mt { + .pc-mt { margin-top: var(--mt); } - .u-p { + .pc-p { padding: var(--p); } - .u-text--center { + .pc-text--center { text-align: center; } } diff --git a/server/src/templates/components/header.njk b/server/src/templates/components/header.njk new file mode 100644 index 00000000..2ee94b7c --- /dev/null +++ b/server/src/templates/components/header.njk @@ -0,0 +1,25 @@ +
+
+ + {{ req.user.firstName|first|upper }} + + +
+
diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk new file mode 100644 index 00000000..18119fea --- /dev/null +++ b/server/src/templates/components/nav.njk @@ -0,0 +1,76 @@ +{% set view_name = 'home' %} + + diff --git a/server/src/templates/errors/error.njk b/server/src/templates/errors/error.njk new file mode 100644 index 00000000..ca43adb4 --- /dev/null +++ b/server/src/templates/errors/error.njk @@ -0,0 +1,22 @@ + + + + + + Error + + + +

Error

+
+            {{ error }}
+        
+ + diff --git a/server/src/templates/home.njk b/server/src/templates/home.njk deleted file mode 100644 index 54bf74cf..00000000 --- a/server/src/templates/home.njk +++ /dev/null @@ -1,9 +0,0 @@ -{% extends '_base.njk' %} - -{% block body %} -

Hello, world!

- -
- -
-{% endblock body %} diff --git a/server/src/templates/icons/calendar.njk b/server/src/templates/icons/calendar.njk new file mode 100644 index 00000000..e9b7198e --- /dev/null +++ b/server/src/templates/icons/calendar.njk @@ -0,0 +1,4 @@ + diff --git a/server/src/templates/icons/crm.njk b/server/src/templates/icons/crm.njk new file mode 100644 index 00000000..827d3b9e --- /dev/null +++ b/server/src/templates/icons/crm.njk @@ -0,0 +1,4 @@ + diff --git a/server/src/templates/icons/dashboard.njk b/server/src/templates/icons/dashboard.njk new file mode 100644 index 00000000..1087d84d --- /dev/null +++ b/server/src/templates/icons/dashboard.njk @@ -0,0 +1,5 @@ + diff --git a/server/src/templates/icons/group.njk b/server/src/templates/icons/group.njk new file mode 100644 index 00000000..904971cf --- /dev/null +++ b/server/src/templates/icons/group.njk @@ -0,0 +1,8 @@ + diff --git a/server/src/templates/icons/logout.njk b/server/src/templates/icons/logout.njk new file mode 100644 index 00000000..b75ed127 --- /dev/null +++ b/server/src/templates/icons/logout.njk @@ -0,0 +1,5 @@ + diff --git a/server/src/templates/icons/user.njk b/server/src/templates/icons/user.njk new file mode 100644 index 00000000..2f743e05 --- /dev/null +++ b/server/src/templates/icons/user.njk @@ -0,0 +1,4 @@ + diff --git a/server/src/templates/_base.njk b/server/src/templates/layouts/_base.njk similarity index 92% rename from server/src/templates/_base.njk rename to server/src/templates/layouts/_base.njk index 4cc08769..dcafd73d 100644 --- a/server/src/templates/_base.njk +++ b/server/src/templates/layouts/_base.njk @@ -7,6 +7,7 @@ {% block title %}Permacoop{% endblock title %} + {% block header %}{% endblock header %} {% block body %}
diff --git a/server/src/templates/layouts/app.njk b/server/src/templates/layouts/app.njk new file mode 100644 index 00000000..9dc7dd39 --- /dev/null +++ b/server/src/templates/layouts/app.njk @@ -0,0 +1,16 @@ +{% extends 'layouts/_base.njk' %} +{% block body %} +
+ + {% include "components/header.njk" %} +
+ {% block main %}{% endblock main %} +
+
+{% endblock body %} diff --git a/server/src/templates/layouts/blank.njk b/server/src/templates/layouts/blank.njk new file mode 100644 index 00000000..62331864 --- /dev/null +++ b/server/src/templates/layouts/blank.njk @@ -0,0 +1 @@ +{% extends 'layouts/_base.njk' %} diff --git a/server/src/templates/pages/home.njk b/server/src/templates/pages/home.njk new file mode 100644 index 00000000..f12f5503 --- /dev/null +++ b/server/src/templates/pages/home.njk @@ -0,0 +1,5 @@ +{% extends 'layouts/app.njk' %} + +{% block main %} +

Bonjour, {{ req.user.firstName|capitalize }} {{ req.user.lastName|capitalize }} !

+{% endblock main %} diff --git a/server/src/templates/login.njk b/server/src/templates/pages/login.njk similarity index 54% rename from server/src/templates/login.njk rename to server/src/templates/pages/login.njk index 6dfe2b54..ac506559 100644 --- a/server/src/templates/login.njk +++ b/server/src/templates/pages/login.njk @@ -1,28 +1,28 @@ -{% extends '_base.njk' %} +{% extends 'layouts/blank.njk' %} {% block title %}Se connecter - {{ super() }}{% endblock title %} -{% block body_class %}u-center u-background-alt-grey{% endblock body_class %} +{% block body_class %}pc-center pc-background-alt-grey{% endblock body_class %} {% block main %} -
-
+
+
-
-

+ +

Connexion

-
+
-
+
- +
From 54f9504c075e5c18c1fb294697ba065b8f0a793c Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Sat, 16 Sep 2023 23:40:42 +0200 Subject: [PATCH 06/49] Add translations w/ Fluent, implement basic FairCalendar, fixes --- Makefile | 7 +- server/.env.dist | 3 + server/nest-cli.json | 2 +- server/package-lock.json | 628 ++++++++++++++++++ server/package.json | 8 + server/src/Application/ITranslations.ts | 3 + .../Adapter/FluentTranslatorAdapter.ts | 56 ++ .../ExceptionFilter/AuthRequiredFilter.ts | 2 +- .../ExceptionFilter/UnexpectedErrorFilter.ts | 3 + .../Infrastructure/Common/Routing/WithName.ts | 57 ++ .../Common/Templating/filters.ts | 13 + .../{Nunjucks => Common/Templating}/index.ts | 22 +- .../Infrastructure/Common/Utils/dateUtils.ts | 14 + .../FairCalendar/Action/AddEventsAction.ts | 61 -- .../FairCalendar/Action/DeleteEventAction.ts | 41 -- .../FairCalendar/Action/GetEventAction.ts | 39 -- .../Action/GetMonthlyFairCalendarAction.ts | 48 -- .../FairCalendar/Action/UpdateEventAction.ts | 59 -- .../Controller/AddEventController.ts | 104 +++ .../Controller/DeleteEventController.ts | 41 ++ .../Controller/FairCalendarController.ts | 71 ++ .../Controller/UpdateEventController.ts | 107 +++ .../FairCalendar/DTO/AbstractEventDTO.ts | 7 +- .../FairCalendar/DTO/AddEventControllerDTO.ts | 6 + .../DTO/FairCalendarControllerDTO.ts | 12 + .../FairCalendar/faircalendar.module.ts | 22 +- .../Home/Controller/HomeController.ts | 2 +- .../User/Controller/LogoutController.ts | 2 +- .../User/Security/UserSerializer.ts | 17 +- .../Infrastructure/NestJS/Routing/WithName.ts | 50 -- server/src/app.module.ts | 4 +- .../controllers/fullcalendar_controller.js | 34 + server/src/assets/main.js | 8 + server/src/main.ts | 9 +- server/src/public/styles.css | 65 +- .../components/faircalendar_event_form.njk | 46 ++ server/src/templates/components/header.njk | 4 +- server/src/templates/components/nav.njk | 22 +- server/src/templates/layouts/_base.njk | 1 + server/src/templates/layouts/app.njk | 2 +- .../pages/faircalendar_events_add.njk | 8 + .../pages/faircalendar_events_edit.njk | 14 + .../templates/pages/faircalendar_index.njk | 11 + server/src/translations/fr-FR.ftl | 31 + 44 files changed, 1416 insertions(+), 350 deletions(-) create mode 100644 server/src/Application/ITranslations.ts create mode 100644 server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts rename server/src/Infrastructure/{NestJS => Common}/ExceptionFilter/AuthRequiredFilter.ts (86%) rename server/src/Infrastructure/{NestJS => Common}/ExceptionFilter/UnexpectedErrorFilter.ts (85%) create mode 100644 server/src/Infrastructure/Common/Routing/WithName.ts create mode 100644 server/src/Infrastructure/Common/Templating/filters.ts rename server/src/Infrastructure/{Nunjucks => Common/Templating}/index.ts (67%) create mode 100644 server/src/Infrastructure/Common/Utils/dateUtils.ts delete mode 100644 server/src/Infrastructure/FairCalendar/Action/AddEventsAction.ts delete mode 100644 server/src/Infrastructure/FairCalendar/Action/DeleteEventAction.ts delete mode 100644 server/src/Infrastructure/FairCalendar/Action/GetEventAction.ts delete mode 100644 server/src/Infrastructure/FairCalendar/Action/GetMonthlyFairCalendarAction.ts delete mode 100644 server/src/Infrastructure/FairCalendar/Action/UpdateEventAction.ts create mode 100644 server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts create mode 100644 server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts create mode 100644 server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts create mode 100644 server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts create mode 100644 server/src/Infrastructure/FairCalendar/DTO/AddEventControllerDTO.ts create mode 100644 server/src/Infrastructure/FairCalendar/DTO/FairCalendarControllerDTO.ts delete mode 100644 server/src/Infrastructure/NestJS/Routing/WithName.ts create mode 100644 server/src/assets/controllers/fullcalendar_controller.js create mode 100644 server/src/assets/main.js create mode 100644 server/src/templates/components/faircalendar_event_form.njk create mode 100644 server/src/templates/pages/faircalendar_events_add.njk create mode 100644 server/src/templates/pages/faircalendar_events_edit.njk create mode 100644 server/src/templates/pages/faircalendar_index.njk create mode 100644 server/src/translations/fr-FR.ftl diff --git a/Makefile b/Makefile index 0a8d8cbc..9e8cf8c6 100644 --- a/Makefile +++ b/Makefile @@ -38,9 +38,14 @@ rm: stop ## Stop and remove containers ps: ## Show running containers make compose CMD=ps -build: ## Build dist +build: build-app build-assets ## Build dist + +build-app: cd server && npm run build +build-assets: + cd server && npm run build:assets + start-dist: ## Serve built server cd server && npm run start:prod diff --git a/server/.env.dist b/server/.env.dist index 9fdb1c06..355bc52e 100644 --- a/server/.env.dist +++ b/server/.env.dist @@ -9,3 +9,6 @@ ACCOUNTING_INVOICE_PREFIX='FS' UPLOAD_LOCATION='uploads' FILE_ENCRYPTION_KEY='my_secret_key' CALENDAR_TOKEN='abcd1234' + +FLUENT_PATH=src/translations/fr-FR.ftl +FLUENT_LOCALE=fr-FR diff --git a/server/nest-cli.json b/server/nest-cli.json index c6fc0b1e..e18e8bc8 100644 --- a/server/nest-cli.json +++ b/server/nest-cli.json @@ -2,7 +2,7 @@ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { - "assets": ["templates/**/*", "public/**/*"], + "assets": ["templates/**/*", "public/**/*", "translations/**/*"], "watchAssets": true, "manualRestart": true } diff --git a/server/package-lock.json b/server/package-lock.json index 7d3f6f32..2a55a3b4 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -11,6 +11,11 @@ "dependencies": { "@concepta/typeorm-seeding": "^4.0.0-beta.0", "@faker-js/faker": "^7.6.0", + "@fluent/bundle": "^0.18.0", + "@fullcalendar/core": "^6.1.8", + "@fullcalendar/daygrid": "^6.1.8", + "@fullcalendar/interaction": "^6.1.8", + "@hotwired/stimulus": "^3.2.2", "@nestjs/common": "^9.2.0", "@nestjs/config": "^2.2.0", "@nestjs/core": "^9.2.0", @@ -25,6 +30,7 @@ "connect-pg-simple": "^9.0.0", "crypto": "^1.0.1", "date-fns": "^2.8.1", + "esbuild": "0.19.3", "express-session": "^1.17.3", "helmet": "^3.22.0", "lodash": ">=4.17.19", @@ -53,6 +59,7 @@ "@types/passport-http-bearer": "^1.0.35", "@types/passport-local": "^1.0.35", "@types/supertest": "^2.0.8", + "@types/webpack-env": "^1.18.1", "@typescript-eslint/eslint-plugin": "4.22.0", "@typescript-eslint/parser": "4.22.0", "eslint": "7.24.0", @@ -1011,6 +1018,336 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.3.tgz", + "integrity": "sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.3.tgz", + "integrity": "sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.3.tgz", + "integrity": "sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.3.tgz", + "integrity": "sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.3.tgz", + "integrity": "sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.3.tgz", + "integrity": "sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.3.tgz", + "integrity": "sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.3.tgz", + "integrity": "sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.3.tgz", + "integrity": "sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.3.tgz", + "integrity": "sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.3.tgz", + "integrity": "sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.3.tgz", + "integrity": "sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.3.tgz", + "integrity": "sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.3.tgz", + "integrity": "sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.3.tgz", + "integrity": "sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.3.tgz", + "integrity": "sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.3.tgz", + "integrity": "sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.3.tgz", + "integrity": "sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.3.tgz", + "integrity": "sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.3.tgz", + "integrity": "sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.3.tgz", + "integrity": "sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.3.tgz", + "integrity": "sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", @@ -1121,6 +1458,44 @@ "npm": ">=6.0.0" } }, + "node_modules/@fluent/bundle": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@fluent/bundle/-/bundle-0.18.0.tgz", + "integrity": "sha512-8Wfwu9q8F9g2FNnv82g6Ch/E1AW1wwljsUOolH5NEtdJdv0sZTuWvfCM7c3teB9dzNaJA8rn4khpidpozHWYEA==", + "engines": { + "node": ">=14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@fullcalendar/core": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.8.tgz", + "integrity": "sha512-i8JBIvZCWGO9dsMEDcx9bnsQZ9PtGSJdOXGgWbhLaGq2iq41OBdp9g9gM4b/Otv2oK8bL5Gl6CsMmb/HkDtA6Q==", + "dependencies": { + "preact": "~10.12.1" + } + }, + "node_modules/@fullcalendar/daygrid": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.8.tgz", + "integrity": "sha512-kCZxQFKb9Vqa3CZRX0v7rMSJ2mlTt4gDpyLfiNJKxUAq7W51uKurPaFZWicaXy1ESHVBxKNlbx5uNjBpyu50JQ==", + "peerDependencies": { + "@fullcalendar/core": "~6.1.8" + } + }, + "node_modules/@fullcalendar/interaction": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.8.tgz", + "integrity": "sha512-r6W4E9ohaA87M2uPSlmpE2WT7Fzu7LN0u2pE6D/tThruCEaAPbN8Pw5+sqclsuyTIL09mg0eSJm/ggJekTabSA==", + "peerDependencies": { + "@fullcalendar/core": "~6.1.8" + } + }, + "node_modules/@hotwired/stimulus": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@hotwired/stimulus/-/stimulus-3.2.2.tgz", + "integrity": "sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==" + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -2665,6 +3040,12 @@ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.0.0.tgz", "integrity": "sha512-WAy5txG7aFX8Vw3sloEKp5p/t/Xt8jD3GRD9DacnFv6Vo8ubudAsRTXgxpQwU0mpzY/H8U4db3roDuCMjShBmw==" }, + "node_modules/@types/webpack-env": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.1.tgz", + "integrity": "sha512-D0HJET2/UY6k9L6y3f5BL+IDxZmPkYmPT4+qBrRdmRLYRuV0qNKizMgTvYxXZYn+36zjPeoDZAEYBCM6XB+gww==", + "dev": true + }, "node_modules/@types/yargs": { "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", @@ -4656,6 +5037,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.3.tgz", + "integrity": "sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.3", + "@esbuild/android-arm64": "0.19.3", + "@esbuild/android-x64": "0.19.3", + "@esbuild/darwin-arm64": "0.19.3", + "@esbuild/darwin-x64": "0.19.3", + "@esbuild/freebsd-arm64": "0.19.3", + "@esbuild/freebsd-x64": "0.19.3", + "@esbuild/linux-arm": "0.19.3", + "@esbuild/linux-arm64": "0.19.3", + "@esbuild/linux-ia32": "0.19.3", + "@esbuild/linux-loong64": "0.19.3", + "@esbuild/linux-mips64el": "0.19.3", + "@esbuild/linux-ppc64": "0.19.3", + "@esbuild/linux-riscv64": "0.19.3", + "@esbuild/linux-s390x": "0.19.3", + "@esbuild/linux-x64": "0.19.3", + "@esbuild/netbsd-x64": "0.19.3", + "@esbuild/openbsd-x64": "0.19.3", + "@esbuild/sunos-x64": "0.19.3", + "@esbuild/win32-arm64": "0.19.3", + "@esbuild/win32-ia32": "0.19.3", + "@esbuild/win32-x64": "0.19.3" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -9036,6 +9453,15 @@ "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==" }, + "node_modules/preact": { + "version": "10.12.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz", + "integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prettier": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", @@ -12071,6 +12497,138 @@ } } }, + "@esbuild/android-arm": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.3.tgz", + "integrity": "sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==", + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.3.tgz", + "integrity": "sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==", + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.3.tgz", + "integrity": "sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==", + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.3.tgz", + "integrity": "sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==", + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.3.tgz", + "integrity": "sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==", + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.3.tgz", + "integrity": "sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==", + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.3.tgz", + "integrity": "sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==", + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.3.tgz", + "integrity": "sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==", + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.3.tgz", + "integrity": "sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==", + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.3.tgz", + "integrity": "sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==", + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.3.tgz", + "integrity": "sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==", + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.3.tgz", + "integrity": "sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==", + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.3.tgz", + "integrity": "sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==", + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.3.tgz", + "integrity": "sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==", + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.3.tgz", + "integrity": "sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==", + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.3.tgz", + "integrity": "sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==", + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.3.tgz", + "integrity": "sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==", + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.3.tgz", + "integrity": "sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==", + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.3.tgz", + "integrity": "sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==", + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.3.tgz", + "integrity": "sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==", + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.3.tgz", + "integrity": "sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==", + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.3.tgz", + "integrity": "sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==", + "optional": true + }, "@eslint/eslintrc": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", @@ -12150,6 +12708,36 @@ "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==" }, + "@fluent/bundle": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@fluent/bundle/-/bundle-0.18.0.tgz", + "integrity": "sha512-8Wfwu9q8F9g2FNnv82g6Ch/E1AW1wwljsUOolH5NEtdJdv0sZTuWvfCM7c3teB9dzNaJA8rn4khpidpozHWYEA==" + }, + "@fullcalendar/core": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.8.tgz", + "integrity": "sha512-i8JBIvZCWGO9dsMEDcx9bnsQZ9PtGSJdOXGgWbhLaGq2iq41OBdp9g9gM4b/Otv2oK8bL5Gl6CsMmb/HkDtA6Q==", + "requires": { + "preact": "~10.12.1" + } + }, + "@fullcalendar/daygrid": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.8.tgz", + "integrity": "sha512-kCZxQFKb9Vqa3CZRX0v7rMSJ2mlTt4gDpyLfiNJKxUAq7W51uKurPaFZWicaXy1ESHVBxKNlbx5uNjBpyu50JQ==", + "requires": {} + }, + "@fullcalendar/interaction": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.8.tgz", + "integrity": "sha512-r6W4E9ohaA87M2uPSlmpE2WT7Fzu7LN0u2pE6D/tThruCEaAPbN8Pw5+sqclsuyTIL09mg0eSJm/ggJekTabSA==", + "requires": {} + }, + "@hotwired/stimulus": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@hotwired/stimulus/-/stimulus-3.2.2.tgz", + "integrity": "sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==" + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -13374,6 +13962,12 @@ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.0.0.tgz", "integrity": "sha512-WAy5txG7aFX8Vw3sloEKp5p/t/Xt8jD3GRD9DacnFv6Vo8ubudAsRTXgxpQwU0mpzY/H8U4db3roDuCMjShBmw==" }, + "@types/webpack-env": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.1.tgz", + "integrity": "sha512-D0HJET2/UY6k9L6y3f5BL+IDxZmPkYmPT4+qBrRdmRLYRuV0qNKizMgTvYxXZYn+36zjPeoDZAEYBCM6XB+gww==", + "dev": true + }, "@types/yargs": { "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", @@ -14831,6 +15425,35 @@ "is-symbol": "^1.0.2" } }, + "esbuild": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.3.tgz", + "integrity": "sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==", + "requires": { + "@esbuild/android-arm": "0.19.3", + "@esbuild/android-arm64": "0.19.3", + "@esbuild/android-x64": "0.19.3", + "@esbuild/darwin-arm64": "0.19.3", + "@esbuild/darwin-x64": "0.19.3", + "@esbuild/freebsd-arm64": "0.19.3", + "@esbuild/freebsd-x64": "0.19.3", + "@esbuild/linux-arm": "0.19.3", + "@esbuild/linux-arm64": "0.19.3", + "@esbuild/linux-ia32": "0.19.3", + "@esbuild/linux-loong64": "0.19.3", + "@esbuild/linux-mips64el": "0.19.3", + "@esbuild/linux-ppc64": "0.19.3", + "@esbuild/linux-riscv64": "0.19.3", + "@esbuild/linux-s390x": "0.19.3", + "@esbuild/linux-x64": "0.19.3", + "@esbuild/netbsd-x64": "0.19.3", + "@esbuild/openbsd-x64": "0.19.3", + "@esbuild/sunos-x64": "0.19.3", + "@esbuild/win32-arm64": "0.19.3", + "@esbuild/win32-ia32": "0.19.3", + "@esbuild/win32-x64": "0.19.3" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -18110,6 +18733,11 @@ "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==" }, + "preact": { + "version": "10.12.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz", + "integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==" + }, "prettier": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", diff --git a/server/package.json b/server/package.json index c9620bf5..82103ce4 100644 --- a/server/package.json +++ b/server/package.json @@ -7,6 +7,7 @@ "scripts": { "prebuild": "rimraf dist", "build": "nest build", + "build:assets": "esbuild src/assets/main.js --bundle --outfile=dist/public/client.js", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", "start:dev": "nest start --preserveWatchOutput --watch --debug", @@ -27,6 +28,11 @@ "dependencies": { "@concepta/typeorm-seeding": "^4.0.0-beta.0", "@faker-js/faker": "^7.6.0", + "@fluent/bundle": "^0.18.0", + "@fullcalendar/core": "^6.1.8", + "@fullcalendar/daygrid": "^6.1.8", + "@fullcalendar/interaction": "^6.1.8", + "@hotwired/stimulus": "^3.2.2", "@nestjs/common": "^9.2.0", "@nestjs/config": "^2.2.0", "@nestjs/core": "^9.2.0", @@ -41,6 +47,7 @@ "connect-pg-simple": "^9.0.0", "crypto": "^1.0.1", "date-fns": "^2.8.1", + "esbuild": "0.19.3", "express-session": "^1.17.3", "helmet": "^3.22.0", "lodash": ">=4.17.19", @@ -69,6 +76,7 @@ "@types/passport-http-bearer": "^1.0.35", "@types/passport-local": "^1.0.35", "@types/supertest": "^2.0.8", + "@types/webpack-env": "^1.18.1", "@typescript-eslint/eslint-plugin": "4.22.0", "@typescript-eslint/parser": "4.22.0", "eslint": "7.24.0", diff --git a/server/src/Application/ITranslations.ts b/server/src/Application/ITranslations.ts new file mode 100644 index 00000000..fbceca37 --- /dev/null +++ b/server/src/Application/ITranslations.ts @@ -0,0 +1,3 @@ +export interface ITranslator { + translate(name: string, params?: Record): string; +} diff --git a/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts b/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts new file mode 100644 index 00000000..18d7c1f4 --- /dev/null +++ b/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts @@ -0,0 +1,56 @@ +import * as fs from 'fs'; +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import * as fluent from '@fluent/bundle'; +import { ITranslator } from 'src/Application/ITranslations'; + +@Injectable() +export class FluentTranslatorAdapter implements ITranslator { + private path: string; + private locale: string; + private bundle: fluent.FluentBundle = null; + + constructor(private readonly configService: ConfigService) { + this.path = this.configService.get('FLUENT_PATH'); + this.locale = this.configService.get('FLUENT_LOCALE'); + this.bundle = _readBundle(this.path, this.locale); + } + + public translate(key: string, params: Record = {}): string { + if (process.env.NODE_ENV !== 'production') { + // Refresh during development + this.bundle = _readBundle(this.path, this.locale); + } + + return _translate(this.bundle, key, params); + } +} + +const _readBundle = (path: string, locale: string) => { + const content = fs.readFileSync(path).toString(); + + const resource = new fluent.FluentResource(content); + + const bundle = new fluent.FluentBundle(locale); + const errors = bundle.addResource(resource); + + if (errors.length > 0) { + throw errors[0]; + } + + return bundle; +}; + +const _translate = ( + bundle: fluent.FluentBundle, + key: string, + params: Record = {} +): string | null => { + const message = bundle.getMessage(key); + + if (message && message.value) { + return bundle.formatPattern(message.value, params); + } else { + return key; + } +}; diff --git a/server/src/Infrastructure/NestJS/ExceptionFilter/AuthRequiredFilter.ts b/server/src/Infrastructure/Common/ExceptionFilter/AuthRequiredFilter.ts similarity index 86% rename from server/src/Infrastructure/NestJS/ExceptionFilter/AuthRequiredFilter.ts rename to server/src/Infrastructure/Common/ExceptionFilter/AuthRequiredFilter.ts index 3d60e280..41053737 100644 --- a/server/src/Infrastructure/NestJS/ExceptionFilter/AuthRequiredFilter.ts +++ b/server/src/Infrastructure/Common/ExceptionFilter/AuthRequiredFilter.ts @@ -13,6 +13,6 @@ export class AuthRequiredFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost): void { const ctx = host.switchToHttp(); const response = ctx.getResponse(); - response.status(exception.getStatus()).redirect('/login', 303); + response.status(exception.getStatus()).redirect(303, '/login'); } } diff --git a/server/src/Infrastructure/NestJS/ExceptionFilter/UnexpectedErrorFilter.ts b/server/src/Infrastructure/Common/ExceptionFilter/UnexpectedErrorFilter.ts similarity index 85% rename from server/src/Infrastructure/NestJS/ExceptionFilter/UnexpectedErrorFilter.ts rename to server/src/Infrastructure/Common/ExceptionFilter/UnexpectedErrorFilter.ts index b27a1187..0eff3c79 100644 --- a/server/src/Infrastructure/NestJS/ExceptionFilter/UnexpectedErrorFilter.ts +++ b/server/src/Infrastructure/Common/ExceptionFilter/UnexpectedErrorFilter.ts @@ -8,5 +8,8 @@ export class UnexpectedErrorFilter implements ExceptionFilter { const response = ctx.getResponse(); response.render('errors/error', { error }); response.statusCode = 500; + if (error['status'] === 400) { + console.error(error); + } } } diff --git a/server/src/Infrastructure/Common/Routing/WithName.ts b/server/src/Infrastructure/Common/Routing/WithName.ts new file mode 100644 index 00000000..e2202fe9 --- /dev/null +++ b/server/src/Infrastructure/Common/Routing/WithName.ts @@ -0,0 +1,57 @@ +import { INestApplication } from '@nestjs/common'; +import { DiscoveryService } from '@nestjs/core'; +import { PATH_METADATA } from '@nestjs/common/constants'; + +const ROUTE_NAME_METADATA = '__route_name__'; + +export function WithName(routeName: string | Symbol): MethodDecorator { + return ( + _target: object, + _key: string | symbol, + descriptor: TypedPropertyDescriptor + ) => { + Reflect.defineMetadata(ROUTE_NAME_METADATA, routeName, descriptor.value); + return descriptor; + }; +} + +export type NamedRoute = { + name: string; + path: string; +}; + +export function getNamedRoutes(app: INestApplication): NamedRoute[] { + const namedRoutes: NamedRoute[] = []; + + const controllers = app.get(DiscoveryService).getControllers(); + + controllers.forEach(controller => { + const rootPath: string = Reflect.getMetadata( + PATH_METADATA, + controller.metatype + ); + + const methodNames = Object.getOwnPropertyNames( + controller.instance.__proto__ + ); + + methodNames.forEach(methodName => { + const method = controller.instance.__proto__[methodName]; + const name: string | undefined = Reflect.getMetadata( + ROUTE_NAME_METADATA, + method + ); + + if (name) { + const path: string = Reflect.getMetadata(PATH_METADATA, method); + console.log(rootPath, path); + namedRoutes.push({ + name, + path: `/${rootPath}${path && path !== '/' ? '/' + path : ''}` + }); + } + }); + }); + + return namedRoutes; +} diff --git a/server/src/Infrastructure/Common/Templating/filters.ts b/server/src/Infrastructure/Common/Templating/filters.ts new file mode 100644 index 00000000..13328d58 --- /dev/null +++ b/server/src/Infrastructure/Common/Templating/filters.ts @@ -0,0 +1,13 @@ +import { Environment } from 'nunjucks'; +import { ITranslator } from 'src/Application/ITranslations'; +import { minutesToHours } from '../Utils/dateUtils'; + +export const registerFilters = (env: Environment, translator: ITranslator) => { + env.addFilter('trans', (key, params = {}) => + translator.translate(key, params) + ); + env.addFilter('startswith', (value: string | null, other: string) => + value ? value.startsWith(other) : false + ); + env.addFilter('minutesToHours', minutes => minutesToHours(minutes)); +}; diff --git a/server/src/Infrastructure/Nunjucks/index.ts b/server/src/Infrastructure/Common/Templating/index.ts similarity index 67% rename from server/src/Infrastructure/Nunjucks/index.ts rename to server/src/Infrastructure/Common/Templating/index.ts index c0198931..fac9625a 100644 --- a/server/src/Infrastructure/Nunjucks/index.ts +++ b/server/src/Infrastructure/Common/Templating/index.ts @@ -1,7 +1,7 @@ import { NestExpressApplication } from '@nestjs/platform-express'; import { NextFunction, Request, Response } from 'express'; import { FileSystemLoader, Environment, TemplateCallback } from 'nunjucks'; -import { getNamedRoutes } from '../NestJS/Routing/WithName'; +import { getNamedRoutes } from '../Routing/WithName'; type ContextProcessorFn = ( ctx: Record, @@ -9,7 +9,7 @@ type ContextProcessorFn = ( res: Response ) => void; -export const nunjucks = ( +export const nunjucks = async ( app: NestExpressApplication, { watch } = { watch: false } ) => { @@ -29,14 +29,26 @@ export const nunjucks = ( const ctxProcessors: ContextProcessorFn[] = [ (ctx, req, _res) => { ctx.req = req; - ctx.path = (name: string) => urls[name] ?? '#'; + (ctx.path = (name: string, params: Record = {}) => { + let path = nameToPath[name]; + if (!path) { + return '#'; + } + Object.entries(params).forEach(([name, value]) => { + path = path.replace(`:${name}`, value.toString()); + }); + return path; + }), + (ctx.view_name = pathToName[req.url] ?? null); } ]; - const urls = {}; + const nameToPath = {}; + const pathToName = {}; getNamedRoutes(app).forEach(({ name, path }) => { - urls[name] = path; + nameToPath[name] = path; + pathToName[path] = name; }); app.use((req: Request, res: Response, next: NextFunction): void => { diff --git a/server/src/Infrastructure/Common/Utils/dateUtils.ts b/server/src/Infrastructure/Common/Utils/dateUtils.ts new file mode 100644 index 00000000..54487977 --- /dev/null +++ b/server/src/Infrastructure/Common/Utils/dateUtils.ts @@ -0,0 +1,14 @@ +export const minutesToHours = (value: number): string => { + const hours = Math.floor(value / 60); + const minutes = value % 60; + + if (hours === 0) { + return `${value}m`; + } + + if (minutes === 0) { + return `${hours}h`; + } + + return `${hours}h${minutes}`; +}; diff --git a/server/src/Infrastructure/FairCalendar/Action/AddEventsAction.ts b/server/src/Infrastructure/FairCalendar/Action/AddEventsAction.ts deleted file mode 100644 index eaab045e..00000000 --- a/server/src/Infrastructure/FairCalendar/Action/AddEventsAction.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { - Body, - Post, - Controller, - Inject, - BadRequestException, - UseGuards -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; -import { User, UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { AddEventCommand } from 'src/Application/FairCalendar/Command/AddEventCommand'; -import { AddEventDTO } from '../DTO/AddEventDTO'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; - -@Controller('events') -@ApiTags('FairCalendar') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class AddEventsAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Post() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Add new event(s)' }) - public async index(@Body() dto: AddEventDTO, @LoggedUser() user: User) { - try { - const { - type, - startDate, - endDate, - projectId, - taskId, - summary, - time - } = dto; - const result = await this.commandBus.execute( - new AddEventCommand( - type, - user, - time, - new Date(startDate), - new Date(endDate), - projectId, - taskId, - summary - ) - ); - - return { ...result }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/FairCalendar/Action/DeleteEventAction.ts b/server/src/Infrastructure/FairCalendar/Action/DeleteEventAction.ts deleted file mode 100644 index 78442720..00000000 --- a/server/src/Infrastructure/FairCalendar/Action/DeleteEventAction.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { - Delete, - Controller, - Inject, - BadRequestException, - UseGuards, - Param, - HttpCode -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; -import { User, UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { DeleteEventCommand } from 'src/Application/FairCalendar/Command/DeleteEventCommand'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; - -@Controller('events') -@ApiTags('FairCalendar') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class DeleteEventAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Delete(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Delete an event' }) - @HttpCode(204) - public async index(@Param() dto: IdDTO, @LoggedUser() user: User) { - try { - await this.commandBus.execute(new DeleteEventCommand(dto.id, user)); - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/FairCalendar/Action/GetEventAction.ts b/server/src/Infrastructure/FairCalendar/Action/GetEventAction.ts deleted file mode 100644 index aca977be..00000000 --- a/server/src/Infrastructure/FairCalendar/Action/GetEventAction.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - Controller, - Inject, - BadRequestException, - UseGuards, - Param, - Get -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { GetEventByIdQuery } from 'src/Application/FairCalendar/Query/GetEventByIdQuery'; -import { EventView } from 'src/Application/FairCalendar/View/EventView'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; - -@Controller('events') -@ApiTags('FairCalendar') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetEventAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get event' }) - public async index(@Param() dto: IdDTO): Promise { - try { - return await this.queryBus.execute(new GetEventByIdQuery(dto.id)); - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/FairCalendar/Action/GetMonthlyFairCalendarAction.ts b/server/src/Infrastructure/FairCalendar/Action/GetMonthlyFairCalendarAction.ts deleted file mode 100644 index 9eb16d1c..00000000 --- a/server/src/Infrastructure/FairCalendar/Action/GetMonthlyFairCalendarAction.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { - Controller, - Inject, - UseGuards, - Query, - Get, - BadRequestException -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { GetMonthlyFairCalendarQuery } from 'src/Application/FairCalendar/Query/GetMonthlyFairCalendarQuery'; -import { MonthlyEventsDTO } from '../DTO/MonthlyEventsDTO'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { GetFairCalendarOverview } from 'src/Domain/FairCalendar/GetFairCalendarOverview'; -import { MonthlyEventsView } from 'src/Application/FairCalendar/View/MonthlyEventsView'; - -@Controller('faircalendar') -@ApiTags('FairCalendar') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetMonthlyFairCalendarAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus, - private readonly getFairCalendarOverview: GetFairCalendarOverview - ) {} - - @Get() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get monthly faircalendar by user' }) - public async index(@Query() dto: MonthlyEventsDTO) { - try { - const views = await this.queryBus.execute( - new GetMonthlyFairCalendarQuery(new Date(dto.date), dto.userId) - ); - - return new MonthlyEventsView( - views, - await this.getFairCalendarOverview.index(views) - ); - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/FairCalendar/Action/UpdateEventAction.ts b/server/src/Infrastructure/FairCalendar/Action/UpdateEventAction.ts deleted file mode 100644 index 2fb505b0..00000000 --- a/server/src/Infrastructure/FairCalendar/Action/UpdateEventAction.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { - Controller, - Inject, - BadRequestException, - UseGuards, - Param, - Put, - Body -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; -import { User, UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { UpdateEventCommand } from 'src/Application/FairCalendar/Command/UpdateEventCommand'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { EditEventDTO } from '../DTO/EditEventDTO'; - -@Controller('events') -@ApiTags('FairCalendar') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class UpdateEventAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Put(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Update event' }) - public async index( - @Param() idDto: IdDTO, - @Body() dto: EditEventDTO, - @LoggedUser() user: User - ) { - const { type, time, summary, projectId, taskId } = dto; - - try { - const id = await this.commandBus.execute( - new UpdateEventCommand( - idDto.id, - user, - type, - Number(time), - projectId, - taskId, - summary - ) - ); - - return { id }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts b/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts new file mode 100644 index 00000000..5554e91b --- /dev/null +++ b/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts @@ -0,0 +1,104 @@ +import { + BadRequestException, + Body, + Controller, + Get, + Inject, + Param, + Post, + Render, + Res, + UseGuards +} from '@nestjs/common'; +import { Response } from 'express'; +import { ICommandBus } from 'src/Application/ICommandBus'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { AddEventControllerDTO } from '../DTO/AddEventControllerDTO'; +import { AddEventDTO } from '../DTO/AddEventDTO'; +import { AddEventCommand } from 'src/Application/FairCalendar/Command/AddEventCommand'; +import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; +import { User } from 'src/Domain/HumanResource/User/User.entity'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { GetTasksQuery } from 'src/Application/Task/Query/GetTasksQuery'; +import { GetProjectsQuery } from 'src/Application/Project/Query/GetProjectsQuery'; +import { GetCooperativeQuery } from 'src/Application/Settings/Query/GetCooperativeQuery'; +import { ArrayUtils } from 'src/Infrastructure/Common/Utils/ArrayUtils'; + +@Controller('app/faircalendar/events/add/:date') +@UseGuards(IsAuthenticatedGuard) +export class AddEventController { + constructor( + @Inject('ICommandBus') + private readonly commandBus: ICommandBus, + @Inject('IQueryBus') + private readonly queryBus: IQueryBus + ) {} + + @Get() + @WithName('faircalendar_events_add') + @Render('pages/faircalendar_events_add') + public async get(@Param() dto: AddEventControllerDTO) { + const types = [ + 'mission', + 'dojo', + 'support', + 'formationConference', + 'other' + ]; + + const tasksPagination = await this.queryBus.execute(new GetTasksQuery(1)); + + const projectsPagination = await this.queryBus.execute( + new GetProjectsQuery(1) + ); + + const { dayDuration } = await this.queryBus.execute( + new GetCooperativeQuery() + ); + const times = [...ArrayUtils.range(30, dayDuration, 30)].reverse(); + + return { + date: dto.date, + types, + tasks: tasksPagination.items, + projects: projectsPagination.items, + times + }; + } + + @Post() + public async post( + @Body() dto: AddEventDTO, + @LoggedUser() user: User, + @Res() res: Response + ) { + try { + const { + type, + startDate, + endDate, + projectId, + taskId, + summary, + time + } = dto; + await this.commandBus.execute( + new AddEventCommand( + type, + user, + time, + new Date(startDate), + new Date(endDate), + projectId, + taskId, + summary + ) + ); + + res.redirect(303, '/app/faircalendar'); + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts b/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts new file mode 100644 index 00000000..30470b24 --- /dev/null +++ b/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts @@ -0,0 +1,41 @@ +import { + BadRequestException, + Controller, + Inject, + Param, + Post, + Res, + UseGuards +} from '@nestjs/common'; +import { Response } from 'express'; +import { ICommandBus } from 'src/Application/ICommandBus'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; +import { User } from 'src/Domain/HumanResource/User/User.entity'; +import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; +import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { DeleteEventCommand } from 'src/Application/FairCalendar/Command/DeleteEventCommand'; + +@Controller('app/faircalendar/events/delete') +@UseGuards(IsAuthenticatedGuard) +export class DeleteEventController { + constructor( + @Inject('ICommandBus') + private readonly commandBus: ICommandBus + ) {} + + @Post(':id') + @WithName('faircalendar_event_delete') + public async index( + @Param() dto: IdDTO, + @LoggedUser() user: User, + @Res() res: Response + ) { + try { + await this.commandBus.execute(new DeleteEventCommand(dto.id, user)); + res.redirect(303, '/app/faircalendar'); + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts new file mode 100644 index 00000000..f80c12f4 --- /dev/null +++ b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts @@ -0,0 +1,71 @@ +import { + Controller, + Get, + Inject, + Query, + Render, + UseGuards +} from '@nestjs/common'; +import { User } from 'src/Domain/HumanResource/User/User.entity'; +import { GetMonthlyFairCalendarQuery } from 'src/Application/FairCalendar/Query/GetMonthlyFairCalendarQuery'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { FairCalendarControllerDTO } from '../DTO/FairCalendarControllerDTO'; +import { EventView } from 'src/Application/FairCalendar/View/EventView'; +import { ITranslator } from 'src/Application/ITranslations'; +import { minutesToHours } from 'src/Infrastructure/Common/Utils/dateUtils'; +import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; + +@Controller('app/faircalendar') +@UseGuards(IsAuthenticatedGuard) +export class FairCalendarController { + constructor( + @Inject('IQueryBus') + private readonly queryBus: IQueryBus, + @Inject('ITranslator') + private readonly translator: ITranslator + ) {} + + @Get() + @WithName('faircalendar_index') + @Render('pages/faircalendar_index') + public async get( + @Query() dto: FairCalendarControllerDTO, + @LoggedUser() user: User + ) { + const date = dto.date ? new Date(dto.date) : new Date(); + const userId = dto.userId ? dto.userId : user['id']; + + const events: EventView[] = await this.queryBus.execute( + new GetMonthlyFairCalendarQuery(date, userId) + ); + + const fullCalendarEvents = events.map(event => { + let title = `${minutesToHours(event.time)} - `; + if (event.type === 'mission' && event.task && event.project) { + title += `${event.project.name} (${event.task.name})`; + } else { + title += `${this.translator.translate('faircalendar-type-option', { + type: event.type + })}`; + } + return { + // See: https://fullcalendar.io/docs/event-object + type: event.type, + start: event.date, + end: event.date, + title, + url: `/app/faircalendar/events/edit/${event.id}`, + textColor: `var(--event-${event.type}-text)`, + backgroundColor: `var(--event-${event.type}-background)`, + borderColor: `var(--event-${event.type}-border)` + }; + }); + + return { + fullCalendarEvents, + date + }; + } +} diff --git a/server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts b/server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts new file mode 100644 index 00000000..2e8ee41a --- /dev/null +++ b/server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts @@ -0,0 +1,107 @@ +import { + BadRequestException, + Body, + Controller, + Get, + Inject, + Param, + Post, + Render, + Res, + UseGuards +} from '@nestjs/common'; +import { ICommandBus } from 'src/Application/ICommandBus'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { AddEventControllerDTO } from '../DTO/AddEventControllerDTO'; +import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; +import { User } from 'src/Domain/HumanResource/User/User.entity'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { GetTasksQuery } from 'src/Application/Task/Query/GetTasksQuery'; +import { GetProjectsQuery } from 'src/Application/Project/Query/GetProjectsQuery'; +import { Pagination } from 'src/Application/Common/Pagination'; +import { ProjectView } from 'src/Application/Project/View/ProjectView'; +import { TaskView } from 'src/Application/Task/View/TaskView'; +import { Response } from 'express'; +import { GetCooperativeQuery } from 'src/Application/Settings/Query/GetCooperativeQuery'; +import { CooperativeView } from 'src/Application/Settings/View/CooperativeView'; +import { ArrayUtils } from 'src/Infrastructure/Common/Utils/ArrayUtils'; +import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; +import { EditEventDTO } from '../DTO/EditEventDTO'; +import { UpdateEventCommand } from 'src/Application/FairCalendar/Command/UpdateEventCommand'; +import { GetEventByIdQuery } from 'src/Application/FairCalendar/Query/GetEventByIdQuery'; + +@Controller('app/faircalendar/events/edit') +@UseGuards(IsAuthenticatedGuard) +export class UpdateEventController { + constructor( + @Inject('ICommandBus') + private readonly commandBus: ICommandBus, + @Inject('IQueryBus') + private readonly queryBus: IQueryBus + ) {} + + @Get(':id') + @WithName('faircalendar_events_edit') + @Render('pages/faircalendar_events_edit') + public async get(@Param() idDto: IdDTO) { + const event = await this.queryBus.execute(new GetEventByIdQuery(idDto.id)); + + const types = [ + 'mission', + 'dojo', + 'support', + 'formationConference', + 'other' + ]; + + const tasksPagination: Pagination = await this.queryBus.execute( + new GetTasksQuery(1) + ); + + const projectsPagination: Pagination = await this.queryBus.execute( + new GetProjectsQuery(1) + ); + + const { dayDuration }: CooperativeView = await this.queryBus.execute( + new GetCooperativeQuery() + ); + const times = [...ArrayUtils.range(30, dayDuration, 30)].reverse(); + + return { + event, + types, + tasks: tasksPagination.items, + projects: projectsPagination.items, + times + }; + } + + @Post(':id') + public async post( + @Param() idDto: IdDTO, + @Body() dto: EditEventDTO, + @LoggedUser() user: User, + @Res() res: Response + ) { + const { type, time, summary, projectId, taskId } = dto; + + try { + await this.commandBus.execute( + new UpdateEventCommand( + idDto.id, + user, + type, + Number(time), + projectId, + taskId, + summary + ) + ); + + res.redirect(303, '/app/faircalendar'); + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/FairCalendar/DTO/AbstractEventDTO.ts b/server/src/Infrastructure/FairCalendar/DTO/AbstractEventDTO.ts index 03fbb813..e6353992 100644 --- a/server/src/Infrastructure/FairCalendar/DTO/AbstractEventDTO.ts +++ b/server/src/Infrastructure/FairCalendar/DTO/AbstractEventDTO.ts @@ -6,8 +6,7 @@ import { IsIn, IsEnum, IsOptional, - IsNumber, - IsBooleanString + IsNumberString } from 'class-validator'; import { EventType } from 'src/Domain/FairCalendar/Event.entity'; import { ArrayUtils } from 'src/Infrastructure/Common/Utils/ArrayUtils'; @@ -20,8 +19,8 @@ export abstract class AbstractEventDTO { @ApiProperty() @IsNotEmpty() - @IsNumber() - @IsIn([...ArrayUtils.range(30, 480, 30)]) + @IsNumberString() + @IsIn([...ArrayUtils.range(30, 480, 30)].map(n => n.toString())) public time: number; @ApiPropertyOptional() diff --git a/server/src/Infrastructure/FairCalendar/DTO/AddEventControllerDTO.ts b/server/src/Infrastructure/FairCalendar/DTO/AddEventControllerDTO.ts new file mode 100644 index 00000000..36ccfe41 --- /dev/null +++ b/server/src/Infrastructure/FairCalendar/DTO/AddEventControllerDTO.ts @@ -0,0 +1,6 @@ +import { IsISO8601 } from 'class-validator'; + +export class AddEventControllerDTO { + @IsISO8601() + public date: string; +} diff --git a/server/src/Infrastructure/FairCalendar/DTO/FairCalendarControllerDTO.ts b/server/src/Infrastructure/FairCalendar/DTO/FairCalendarControllerDTO.ts new file mode 100644 index 00000000..4f64b08b --- /dev/null +++ b/server/src/Infrastructure/FairCalendar/DTO/FairCalendarControllerDTO.ts @@ -0,0 +1,12 @@ +import { IsOptional, IsUUID, IsDateString } from 'class-validator'; + +// TODO test +export class FairCalendarControllerDTO { + @IsUUID() + @IsOptional() + public userId?: string; + + @IsDateString() + @IsOptional() + public date?: string; +} diff --git a/server/src/Infrastructure/FairCalendar/faircalendar.module.ts b/server/src/Infrastructure/FairCalendar/faircalendar.module.ts index 00a0c195..2275db88 100644 --- a/server/src/Infrastructure/FairCalendar/faircalendar.module.ts +++ b/server/src/Infrastructure/FairCalendar/faircalendar.module.ts @@ -1,42 +1,43 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { ConfigModule } from '@nestjs/config'; import { BusModule } from '../bus.module'; import { EventRepository } from './Repository/EventRepository'; import { Event } from 'src/Domain/FairCalendar/Event.entity'; import { IsMaximumTimeSpentReached } from 'src/Domain/FairCalendar/Specification/IsMaximumTimeSpentReached'; -import { AddEventsAction } from './Action/AddEventsAction'; import { AddEventCommandHandler } from 'src/Application/FairCalendar/Command/AddEventCommandHandler'; -import { DeleteEventAction } from './Action/DeleteEventAction'; import { DeleteEventCommandHandler } from 'src/Application/FairCalendar/Command/DeleteEventCommandHandler'; import { TaskRepository } from '../Task/Repository/TaskRepository'; import { Task } from 'src/Domain/Task/Task.entity'; import { Project } from 'src/Domain/Project/Project.entity'; import { ProjectRepository } from '../Project/Repository/ProjectRepository'; -import { GetMonthlyFairCalendarAction } from './Action/GetMonthlyFairCalendarAction'; import { DateUtilsAdapter } from '../Adapter/DateUtilsAdapter'; import { GetFairCalendarOverview } from 'src/Domain/FairCalendar/GetFairCalendarOverview'; import { GetMonthlyFairCalendarQueryHandler } from 'src/Application/FairCalendar/Query/GetMonthlyFairCalendarQueryHandler'; import { GetEventByIdQueryHandler } from 'src/Application/FairCalendar/Query/GetEventByIdQueryHandler'; -import { GetEventAction } from './Action/GetEventAction'; -import { UpdateEventAction } from './Action/UpdateEventAction'; import { DoesEventBelongToUser } from 'src/Domain/FairCalendar/Specification/DoesEventBelongToUser'; import { UpdateEventCommandHandler } from 'src/Application/FairCalendar/Command/UpdateEventCommandHandler'; import { LeaveRepository } from '../HumanResource/Leave/Repository/LeaveRepository'; import { Leave } from 'src/Domain/HumanResource/Leave/Leave.entity'; import { CooperativeRepository } from '../Settings/Repository/CooperativeRepository'; import { Cooperative } from 'src/Domain/Settings/Cooperative.entity'; +import { FluentTranslatorAdapter } from '../Adapter/FluentTranslatorAdapter'; +import { FairCalendarController } from './Controller/FairCalendarController'; +import { AddEventController } from './Controller/AddEventController'; +import { UpdateEventController } from './Controller/UpdateEventController'; +import { DeleteEventController } from './Controller/DeleteEventController'; @Module({ imports: [ BusModule, + ConfigModule, TypeOrmModule.forFeature([Project, Event, Task, Leave, Cooperative]) ], controllers: [ - AddEventsAction, - DeleteEventAction, - GetEventAction, - UpdateEventAction, - GetMonthlyFairCalendarAction + FairCalendarController, + AddEventController, + UpdateEventController, + DeleteEventController ], providers: [ { provide: 'ILeaveRepository', useClass: LeaveRepository }, @@ -45,6 +46,7 @@ import { Cooperative } from 'src/Domain/Settings/Cooperative.entity'; { provide: 'ITaskRepository', useClass: TaskRepository }, { provide: 'ICooperativeRepository', useClass: CooperativeRepository }, { provide: 'IDateUtils', useClass: DateUtilsAdapter }, + { provide: 'ITranslator', useClass: FluentTranslatorAdapter }, Date, IsMaximumTimeSpentReached, AddEventCommandHandler, diff --git a/server/src/Infrastructure/Home/Controller/HomeController.ts b/server/src/Infrastructure/Home/Controller/HomeController.ts index 278e568d..2cfd5db9 100644 --- a/server/src/Infrastructure/Home/Controller/HomeController.ts +++ b/server/src/Infrastructure/Home/Controller/HomeController.ts @@ -1,6 +1,6 @@ import { Controller, Get, Render, UseGuards } from '@nestjs/common'; +import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; -import { WithName } from 'src/Infrastructure/NestJS/Routing/WithName'; @Controller('') @UseGuards(IsAuthenticatedGuard) diff --git a/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts index f45ad0ad..bcb201d3 100644 --- a/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts +++ b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts @@ -6,7 +6,7 @@ import { Res } from '@nestjs/common'; import { Request, Response } from 'express'; -import { WithName } from 'src/Infrastructure/NestJS/Routing/WithName'; +import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; @Controller('logout') export class LogoutController { diff --git a/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts b/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts index 145973b5..ef13fb8f 100644 --- a/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts +++ b/server/src/Infrastructure/HumanResource/User/Security/UserSerializer.ts @@ -1,14 +1,27 @@ -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { PassportSerializer } from '@nestjs/passport'; import { AuthenticatedView } from 'src/Application/HumanResource/User/View/AuthenticatedView'; +import { IUserRepository } from 'src/Domain/HumanResource/User/Repository/IUserRepository'; @Injectable() export class UserSerializer extends PassportSerializer { + constructor( + @Inject('IUserRepository') + private readonly userRepository: IUserRepository + ) { + super(); + } + serializeUser(user: AuthenticatedView, done: Function) { done(null, user); } - public deserializeUser(user: AuthenticatedView, done: Function): void { + public async deserializeUser( + view: AuthenticatedView, + done: Function + ): Promise { + const user = await this.userRepository.findOneById(view.id); + done(null, user); } } diff --git a/server/src/Infrastructure/NestJS/Routing/WithName.ts b/server/src/Infrastructure/NestJS/Routing/WithName.ts deleted file mode 100644 index bc22193f..00000000 --- a/server/src/Infrastructure/NestJS/Routing/WithName.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { INestApplication } from '@nestjs/common'; -import { DiscoveryService } from '@nestjs/core'; -import { PATH_METADATA } from '@nestjs/common/constants'; - -const ROUTE_NAME_METADATA = '__route_name__'; - -export function WithName(routeName: string | Symbol): MethodDecorator { - return ( - _target: object, - _key: string | symbol, - descriptor: TypedPropertyDescriptor - ) => { - Reflect.defineMetadata(ROUTE_NAME_METADATA, routeName, descriptor.value); - return descriptor; - }; -} - -export type NamedRoute = { - name: string; - path: string; -}; - -export function getNamedRoutes(app: INestApplication): NamedRoute[] { - const namedRoutes: NamedRoute[] = []; - - app - .get(DiscoveryService) - .getControllers() - .forEach(controller => { - const rootPath = Reflect.getMetadata(PATH_METADATA, controller.metatype); - Object.getOwnPropertyNames(controller.instance.__proto__).forEach( - methodName => { - const method = controller.instance.__proto__[methodName]; - const name = Reflect.getMetadata(ROUTE_NAME_METADATA, method); - if (name) { - const path = Reflect.getMetadata( - PATH_METADATA, - controller.instance.__proto__[methodName] - ); - namedRoutes.push({ - name, - path: `/${rootPath}${path === '/' ? '' : path}` - }); - } - } - ); - }); - - return namedRoutes; -} diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 3101c87b..d79c2999 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -10,8 +10,8 @@ import { FairCalendarModule } from './Infrastructure/FairCalendar/faircalendar.m import { FileModule } from './Infrastructure/File/file.module'; import { HumanResourceModule } from './Infrastructure/HumanResource/humanResource.module'; import { SettingsModule } from './Infrastructure/Settings/settings.module'; -import { UnexpectedErrorFilter } from './Infrastructure/NestJS/ExceptionFilter/UnexpectedErrorFilter'; -import { AuthRequiredFilter } from './Infrastructure/NestJS/ExceptionFilter/AuthRequiredFilter'; +import { UnexpectedErrorFilter } from './Infrastructure/Common/ExceptionFilter/UnexpectedErrorFilter'; +import { AuthRequiredFilter } from './Infrastructure/Common/ExceptionFilter/AuthRequiredFilter'; import { dataSourceOptions } from './datasource'; const providers = []; diff --git a/server/src/assets/controllers/fullcalendar_controller.js b/server/src/assets/controllers/fullcalendar_controller.js new file mode 100644 index 00000000..e4adfee5 --- /dev/null +++ b/server/src/assets/controllers/fullcalendar_controller.js @@ -0,0 +1,34 @@ +import { Controller } from '@hotwired/stimulus'; +import { Calendar } from '@fullcalendar/core'; +import interactionPlugin from '@fullcalendar/interaction'; +import dayGridPlugin from '@fullcalendar/daygrid'; + +export default class extends Controller { + static values = { + eventsJson: String, + addUrlTemplate: String, + }; + + connect() { + const calendar = new Calendar(this.element, { + plugins: [ interactionPlugin, dayGridPlugin ], + initialView: 'dayGridMonth', + locale: 'fr', + nowIndicator: true, + selectable: true, + weekends: false, + height: 700, + dayHeaderFormat: { weekday: 'long' }, + events: JSON.parse(this.eventsJsonValue), + select: (info) => { + const year = info.start.getFullYear(); + const month = (info.start.getMonth() + 1).toString().padStart(2, '0'); + const day = (info.start.getDate()).toString().padStart(2, '0'); + const url = this.addUrlTemplateValue.replace('__date__', `${year}-${month}-${day}`); + window.location = url; + } + }); + + calendar.render(); + } +} diff --git a/server/src/assets/main.js b/server/src/assets/main.js new file mode 100644 index 00000000..0f3e7647 --- /dev/null +++ b/server/src/assets/main.js @@ -0,0 +1,8 @@ +import { Application } from '@hotwired/stimulus'; + +import FullCalendarController from './controllers/fullcalendar_controller'; + +const Stimulus = Application.start(); +Stimulus.debug = true; + +Stimulus.register('fullcalendar', FullCalendarController); diff --git a/server/src/main.ts b/server/src/main.ts index 7933bc44..d6133e6a 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -8,7 +8,8 @@ import * as session from 'express-session'; import * as connectPgSimple from 'connect-pg-simple'; import { NestExpressApplication } from '@nestjs/platform-express'; import { AppModule } from './app.module'; -import { nunjucks } from './Infrastructure/Nunjucks'; +import { nunjucks } from './Infrastructure/Common/Templating'; +import { registerFilters } from './Infrastructure/Common/Templating/filters'; async function bootstrap() { const isProd = process.env.NODE_ENV === 'production'; @@ -45,8 +46,10 @@ async function bootstrap() { const viewsDir = path.join(__dirname, '..', 'templates'); app.setBaseViewsDir(viewsDir); - const njk = nunjucks(app, { watch: !isProd }); - njk.env.addFilter('translate', key => key); + const translator = app.get('ITranslator'); + + const njk = await nunjucks(app, { watch: !isProd }); + registerFilters(njk.env, translator); njk.contextProcessor((ctx, _req, _res) => { ctx.asset = (path: string) => `/public/${path}`; }); diff --git a/server/src/public/styles.css b/server/src/public/styles.css index f6b9431d..74fe038e 100644 --- a/server/src/public/styles.css +++ b/server/src/public/styles.css @@ -15,22 +15,49 @@ /* Colors */ --background-default: #ffffff; --background-alt-grey: #f9fafb; + --background-muted: #f0f0f0; --background-action-violet: #6c2bd9; --background-action-violet-hover: #52289b; - --text-on-background-default: #282828; + --background-danger: #f05252; + --text-default: #282828; + --text-muted: #555555; --text-on-background-action-violet: #ffffff; --text-danger: #ff0000; + --text-on-danger: #ffffff; /* Shadows */ --shadow-default: rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 20px 25px -5px, rgba(0, 0, 0, 0.1) 0px 8px 10px -6px; + --shadow-inner: rgba(0, 0, 0, 0.06) 0px 2px 4px 0px inset; + /* FairCalendar */ + --event-mission-background: rgb(222, 247, 236); + --event-mission-border: rgb(222, 247, 236); + --event-mission-text: rgb(4, 108, 78); + --event-dojo-background: rgb(225, 239, 254); + --event-dojo-border: rgb(225, 239, 254); + --event-dojo-text: rgb(26, 86, 219); + --event-support-background: rgb(229, 237, 255); + --event-support-border: rgb(229, 237, 255); + --event-support-text: rgb(81, 69, 205); + --event-formation_conference-background: rgb(254, 236, 220); + --event-formation_conference-border: rgb(254, 236, 220); + --event-formation_conference-text: rgb(180, 52, 3); + --event-other-background: rgb(244, 245, 247); + --event-other-border: rgb(244, 245, 247); + --event-other-text: rgb(36, 38, 45); + --event-holiday-background: rgb(237, 235, 254); + --event-holiday-border: rgb(237, 235, 254); + --event-holiday-text: rgb(108, 43, 217); } /* Dark mode */ @media (prefers-color-scheme: dark) { :root { /* Colors */ + --background-default: #1a1b23; --background-alt-grey: #121317; + --text-default: #ffffff; + --text-muted: #bbbbbb; } } @@ -103,7 +130,7 @@ @layer defaults { body { background-color: var(--background-default); - color: var(--text-on-background-default); + color: var(--text-default); font-family: var(--font-default); font-size: var(--font-size-default); } @@ -182,13 +209,19 @@ background-color: var(--background-action-violet); color: var(--text-on-background-action-violet); } + .pc-btn:hover { background-color: var(--hover-tint); } + .pc-btn--danger { + background-color: var(--background-danger); + color: var(--text-on-danger); + } + .pc-nav { overflow-y: auto; - padding: calc(4 * var(--v)) 0; + padding: calc(2 * var(--w)) 0; } .pc-nav ul { @@ -203,8 +236,8 @@ } .pc-nav ul li ul { - padding: calc(2 * var(--v)); - margin-top: calc(2 * var(--v)); + padding: var(--w); + margin-top: var(--w); overflow: hidden; font-size: var(--font-size-sm); box-shadow: var(--shadow-inner); @@ -212,7 +245,7 @@ } .pc-nav ul li ul li { - padding: calc(2 * var(--v)) calc(1 * var(--v)); + padding: var(--w) var(--v); } .pc-nav__decoration { @@ -236,11 +269,15 @@ .pc-nav details > summary { cursor: pointer; + color: var(--text-muted); } .pc-nav a[aria-current='page'] { font-weight: bold; } + .pc-nav a:not([aria-current='page']) { + color: var(--text-muted); + } .pc-nav details summary > svg, svg.pc-icon--sm { @@ -352,3 +389,19 @@ text-align: center; } } + +/* fullcalendar customizations */ + +.fc-event { + padding: var(--v); + font-weight: bold; +} + +.fc-view-harness { + background-color: var(--background-default); +} + +.fc-day-other { + position: static !important; + background-color: var(--background-muted); +} diff --git a/server/src/templates/components/faircalendar_event_form.njk b/server/src/templates/components/faircalendar_event_form.njk new file mode 100644 index 00000000..a2b0414a --- /dev/null +++ b/server/src/templates/components/faircalendar_event_form.njk @@ -0,0 +1,46 @@ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + {% if date %} + + + {% endif %} + + +
diff --git a/server/src/templates/components/header.njk b/server/src/templates/components/header.njk index 2ee94b7c..fcdb5fab 100644 --- a/server/src/templates/components/header.njk +++ b/server/src/templates/components/header.njk @@ -8,7 +8,7 @@ {% set class_name = "pc-icon pc-icon--sm" %} {% include 'icons/user.njk' %} - {{ 'header-account'|translate|capitalize }} + {{ 'header-account'|trans|capitalize }}
  • @@ -16,7 +16,7 @@
  • diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk index 18119fea..f2879bc5 100644 --- a/server/src/templates/components/nav.njk +++ b/server/src/templates/components/nav.njk @@ -1,5 +1,3 @@ -{% set view_name = 'home' %} - -
    +
    {% block main %}{% endblock main %}
    diff --git a/server/src/templates/pages/faircalendar_events_edit.njk b/server/src/templates/pages/faircalendar_events_edit.njk index 211f0223..49a31786 100644 --- a/server/src/templates/pages/faircalendar_events_edit.njk +++ b/server/src/templates/pages/faircalendar_events_edit.njk @@ -1,4 +1,7 @@ {% extends 'layouts/app.njk' %} + +{% block main_class %}pc-container{% endblock %} + {% block main %}

    @@ -11,7 +14,9 @@

    -
    - {% include 'components/faircalendar_event_form.njk' %} +
    +
    + {% include 'components/faircalendar_event_form.njk' %} +
    {% endblock main %} diff --git a/server/src/templates/pages/faircalendar_index.njk b/server/src/templates/pages/faircalendar_index.njk index 257df55b..1997aedc 100644 --- a/server/src/templates/pages/faircalendar_index.njk +++ b/server/src/templates/pages/faircalendar_index.njk @@ -1,5 +1,7 @@ {% extends 'layouts/app.njk' %} +{% block main_class %}pc-container{% endblock %} + {% block main %}

    {{ 'faircalendar-title'|trans }}

    diff --git a/server/src/templates/pages/login.njk b/server/src/templates/pages/login.njk index ac506559..62149174 100644 --- a/server/src/templates/pages/login.njk +++ b/server/src/templates/pages/login.njk @@ -7,7 +7,7 @@
    -
    +

    Connexion

    diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index cb350178..791d6333 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -11,7 +11,7 @@ faircalendar-events-edit-title = CRA du {$date} faircalendar-type-title = Type de CRA faircalendar-type-option = {$type -> [mission] Mission - [dojo] Dojo + [dojo] Dojos [support] Supports [formationConference] Formations / Confs *[other] Autre From a518cc280228c31ce2e700769441a71dc2c69ac1 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 10:45:56 +0200 Subject: [PATCH 11/49] Begin Faircalendar filters, add esbuild watch --- Makefile | 13 +++++++++++-- server/package.json | 3 ++- .../HumanResource/User/View/UserView.ts | 4 ++++ .../Controller/FairCalendarController.ts | 5 +++++ .../src/assets/styles/_components/nav/nav.css | 4 ++-- server/src/assets/styles/_utilities.css | 2 +- .../src/templates/pages/faircalendar_index.njk | 17 +++++++++++++++++ server/src/translations/fr-FR.ftl | 2 ++ 8 files changed, 44 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 9e8cf8c6..183521f5 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,9 @@ help: compose = docker-compose -p permacoop +run_server = ./tools/colorize_prefix.sh [server] 30 +run_watch = ./tools/colorize_prefix.sh [watch] 32 + install: ## Install cp -n server/.env.dist server/.env make install-deps @@ -18,7 +21,13 @@ install-dev: up ## Install local development dependencies and services make database-test-init start: up ## Start - cd server && npm run start:dev + make -j 2 start-server start-watch + +start-server: + ${run_server} "cd server && npm run start:dev" + +start-watch: + ${run_watch} "cd server && npm run assets:watch" compose: ## Run Docker compose command (args: CMD) ${compose} ${CMD} @@ -44,7 +53,7 @@ build-app: cd server && npm run build build-assets: - cd server && npm run build:assets + cd server && npm run assets:build start-dist: ## Serve built server cd server && npm run start:prod diff --git a/server/package.json b/server/package.json index 39757a97..867caa3a 100644 --- a/server/package.json +++ b/server/package.json @@ -7,7 +7,8 @@ "scripts": { "prebuild": "rimraf dist", "build": "nest build", - "build:assets": "esbuild src/assets/main.js --bundle --minify --outfile=dist/public/app.js", + "assets:build": "esbuild src/assets/main.js --bundle --minify --outfile=dist/public/app.js", + "assets:watch": "npm run assets:build -- --watch", "format": "prettier --write \"src/**/*.ts\" \"src/assets/**/*\" \"test/**/*.ts\"", "start": "nest start", "start:dev": "nest start --preserveWatchOutput --watch --debug", diff --git a/server/src/Application/HumanResource/User/View/UserView.ts b/server/src/Application/HumanResource/User/View/UserView.ts index a2d84ec0..75ae79bc 100644 --- a/server/src/Application/HumanResource/User/View/UserView.ts +++ b/server/src/Application/HumanResource/User/View/UserView.ts @@ -11,4 +11,8 @@ export class UserView { public readonly isAdministrativeEditable: boolean, public readonly administrativeView: UserAdministrativeView = null ) {} + + get fullName(): string { + return `${this.firstName} ${this.lastName}`; + } } diff --git a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts index f80c12f4..69e4e555 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts @@ -16,6 +16,8 @@ import { EventView } from 'src/Application/FairCalendar/View/EventView'; import { ITranslator } from 'src/Application/ITranslations'; import { minutesToHours } from 'src/Infrastructure/Common/Utils/dateUtils'; import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; +import { UserView } from 'src/Application/HumanResource/User/View/UserView'; +import { GetUsersQuery } from 'src/Application/HumanResource/User/Query/GetUsersQuery'; @Controller('app/faircalendar') @UseGuards(IsAuthenticatedGuard) @@ -37,6 +39,8 @@ export class FairCalendarController { const date = dto.date ? new Date(dto.date) : new Date(); const userId = dto.userId ? dto.userId : user['id']; + const users: UserView[] = await this.queryBus.execute(new GetUsersQuery()); + const events: EventView[] = await this.queryBus.execute( new GetMonthlyFairCalendarQuery(date, userId) ); @@ -64,6 +68,7 @@ export class FairCalendarController { }); return { + users, fullCalendarEvents, date }; diff --git a/server/src/assets/styles/_components/nav/nav.css b/server/src/assets/styles/_components/nav/nav.css index d79ce019..39658820 100644 --- a/server/src/assets/styles/_components/nav/nav.css +++ b/server/src/assets/styles/_components/nav/nav.css @@ -39,11 +39,11 @@ color: var(--text-muted); } -.pc-nav > ul > li > a[aria-current='page'] { +.pc-nav a[aria-current='page'] { position: relative; } -.pc-nav > ul > li > a[aria-current='page']::before { +.pc-nav a[aria-current='page']::before { position: absolute; content: ''; inset: 0; diff --git a/server/src/assets/styles/_utilities.css b/server/src/assets/styles/_utilities.css index 1619e7e0..10d88fe3 100644 --- a/server/src/assets/styles/_utilities.css +++ b/server/src/assets/styles/_utilities.css @@ -16,7 +16,7 @@ } .pc-cols--even { - --cols: auto; + --cols: 1; display: grid; grid-template-columns: repeat(var(--cols), 1fr); gap: var(--gap, calc(2 * var(--w))); diff --git a/server/src/templates/pages/faircalendar_index.njk b/server/src/templates/pages/faircalendar_index.njk index 1997aedc..ff71d0a1 100644 --- a/server/src/templates/pages/faircalendar_index.njk +++ b/server/src/templates/pages/faircalendar_index.njk @@ -5,6 +5,23 @@ {% block main %}

    {{ 'faircalendar-title'|trans }}

    + +
    +
    + + +
    +
    + + +
    +
    + +
    faircalendar-taskId-title = Mission faircalendar-projectId-title = Projet faircalendar-time-title = Temps passé +faircalendar-filters-month-title = Filtrer par mois +faircalendar-filters-userId-title = Filtrer par coopérateur-salarié crm-title = FairCRM crm-customers-title = Clients From 89d85888b654e18667c8a1743ae041bf7c9c62dd Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 12:12:56 +0200 Subject: [PATCH 12/49] Add customer table and add form --- Makefile | 4 +- .../Common/DTO/PaginationDTO.ts | 2 +- .../RouteNameResolver.ts | 30 +++------ .../{Routing => ExtendedRouting}/WithName.ts | 0 .../ExtendedRouting/extendedRouting.module.ts | 10 +++ .../Infrastructure/Common/Templating/index.ts | 10 ++- .../Controller/AddCustomerController.ts | 53 ++++++++++++++++ .../Controller/ListCustomersController.ts | 33 ++++++++++ .../Customer/DTO/AddCustomerDTO.ts | 20 ++++++ .../Customer/customer.module.ts | 13 +++- .../Controller/AddEventController.ts | 2 +- .../Controller/DeleteEventController.ts | 2 +- .../Controller/FairCalendarController.ts | 2 +- .../Controller/UpdateEventController.ts | 2 +- .../Home/Controller/HomeController.ts | 2 +- .../User/Controller/LogoutController.ts | 2 +- server/src/app.module.ts | 8 ++- .../src/assets/styles/_components/index.css | 1 + .../assets/styles/_components/table/table.css | 27 ++++++++ server/src/assets/styles/_defaults.css | 8 +-- server/src/assets/styles/_variables.css | 2 +- server/src/templates/components/nav.njk | 62 ++++++++++++++++++ server/src/templates/layouts/app.njk | 63 +------------------ server/src/templates/macros/customer_form.njk | 29 +++++++++ server/src/templates/macros/table.njk | 34 ++++++++++ server/src/templates/pages/customers_add.njk | 14 +++++ .../src/templates/pages/customers_index.njk | 13 ++++ server/src/translations/fr-FR.ftl | 9 +++ server/tsconfig.json | 2 +- 29 files changed, 350 insertions(+), 109 deletions(-) rename server/src/Infrastructure/Common/{Routing => ExtendedRouting}/RouteNameResolver.ts (79%) rename server/src/Infrastructure/Common/{Routing => ExtendedRouting}/WithName.ts (100%) create mode 100644 server/src/Infrastructure/Common/ExtendedRouting/extendedRouting.module.ts create mode 100644 server/src/Infrastructure/Customer/Controller/AddCustomerController.ts create mode 100644 server/src/Infrastructure/Customer/Controller/ListCustomersController.ts create mode 100644 server/src/Infrastructure/Customer/DTO/AddCustomerDTO.ts create mode 100644 server/src/assets/styles/_components/table/table.css create mode 100644 server/src/templates/components/nav.njk create mode 100644 server/src/templates/macros/customer_form.njk create mode 100644 server/src/templates/macros/table.njk create mode 100644 server/src/templates/pages/customers_add.njk create mode 100644 server/src/templates/pages/customers_index.njk diff --git a/Makefile b/Makefile index 183521f5..94bdc821 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ help: compose = docker-compose -p permacoop -run_server = ./tools/colorize_prefix.sh [server] 30 -run_watch = ./tools/colorize_prefix.sh [watch] 32 +run_server = ./tools/colorize_prefix.sh [server] 31 +run_watch = ./tools/colorize_prefix.sh [watch] 36 install: ## Install cp -n server/.env.dist server/.env diff --git a/server/src/Infrastructure/Common/DTO/PaginationDTO.ts b/server/src/Infrastructure/Common/DTO/PaginationDTO.ts index 05c862a1..b950de31 100644 --- a/server/src/Infrastructure/Common/DTO/PaginationDTO.ts +++ b/server/src/Infrastructure/Common/DTO/PaginationDTO.ts @@ -7,5 +7,5 @@ export class PaginationDTO { @Min(1) @Max(10000) @Type(() => Number) - public page: number = 1; + public page = 1; } diff --git a/server/src/Infrastructure/Common/Routing/RouteNameResolver.ts b/server/src/Infrastructure/Common/ExtendedRouting/RouteNameResolver.ts similarity index 79% rename from server/src/Infrastructure/Common/Routing/RouteNameResolver.ts rename to server/src/Infrastructure/Common/ExtendedRouting/RouteNameResolver.ts index 12eab0bf..3efb644a 100644 --- a/server/src/Infrastructure/Common/Routing/RouteNameResolver.ts +++ b/server/src/Infrastructure/Common/ExtendedRouting/RouteNameResolver.ts @@ -1,21 +1,21 @@ // Inspired by: https://github.com/nestjs/nest/blob/cb2af8a3723272bcbacde44dcaadab66a7ec8b7c/packages/core/router/route-alias-resolver.ts -import { INestApplication } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { PATH_METADATA } from '@nestjs/common/constants'; import { isObject } from '@nestjs/common/utils/shared.utils'; import { DiscoveryService } from '@nestjs/core'; import { ROUTE_NAME_METADATA } from './WithName'; +@Injectable() export class RouteNameResolver { private readonly nameMap: Map; - constructor() { + constructor(discoveryService: DiscoveryService) { this.nameMap = new Map(); + this.init(discoveryService); } - public static fromApp(app: INestApplication): RouteNameResolver { - const resolver = new RouteNameResolver(); - - const controllers = app.get(DiscoveryService).getControllers(); + private init(discoveryService: DiscoveryService) { + const controllers = discoveryService.getControllers(); controllers.forEach(controller => { const basePath: string = Reflect.getMetadata( @@ -36,12 +36,10 @@ export class RouteNameResolver { if (name) { const path: string = Reflect.getMetadata(PATH_METADATA, method); - resolver.register(name, basePath, [path]); + this.register(name, basePath, [path]); } }); }); - - return resolver; } public register(name: string, basePath: string, path: string[]) { @@ -51,12 +49,7 @@ export class RouteNameResolver { this.nameMap.set(name, this.createPath(basePath, path)); } - public createResolveFn(): (name: string, params?: object) => string { - const resolveFn = this.resolve.bind(this); - return (name: string, params?: object) => resolveFn(name, params); - } - - private resolve(name: string, params?: object): string { + public resolve(name: string, params?: object): string { if (!this.nameMap.has(name)) { throw new Error(`Not Found: ${name} not registered`); } @@ -72,12 +65,7 @@ export class RouteNameResolver { return path ? path : '/'; } - public createGetNameFn(): (path: string) => string | null { - const getNameFn = this.getName.bind(this); - return (path: string) => getNameFn(path); - } - - private getName(path: string): string | null { + public getName(path: string): string | null { const parts = this.splitPath([path]); const entries = Array.from(this.nameMap.entries()); diff --git a/server/src/Infrastructure/Common/Routing/WithName.ts b/server/src/Infrastructure/Common/ExtendedRouting/WithName.ts similarity index 100% rename from server/src/Infrastructure/Common/Routing/WithName.ts rename to server/src/Infrastructure/Common/ExtendedRouting/WithName.ts diff --git a/server/src/Infrastructure/Common/ExtendedRouting/extendedRouting.module.ts b/server/src/Infrastructure/Common/ExtendedRouting/extendedRouting.module.ts new file mode 100644 index 00000000..ebcd8faa --- /dev/null +++ b/server/src/Infrastructure/Common/ExtendedRouting/extendedRouting.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { DiscoveryModule } from '@nestjs/core'; +import { RouteNameResolver } from './RouteNameResolver'; + +@Module({ + imports: [DiscoveryModule], + providers: [RouteNameResolver], + exports: [RouteNameResolver] +}) +export class ExtendedRoutingModule {} diff --git a/server/src/Infrastructure/Common/Templating/index.ts b/server/src/Infrastructure/Common/Templating/index.ts index 4b16220b..e446c74f 100644 --- a/server/src/Infrastructure/Common/Templating/index.ts +++ b/server/src/Infrastructure/Common/Templating/index.ts @@ -1,7 +1,7 @@ import { NestExpressApplication } from '@nestjs/platform-express'; import { NextFunction, Request, Response } from 'express'; import { FileSystemLoader, Environment, TemplateCallback } from 'nunjucks'; -import { RouteNameResolver } from '../Routing/RouteNameResolver'; +import { RouteNameResolver } from '../ExtendedRouting/RouteNameResolver'; type ContextProcessorFn = ( ctx: Record, @@ -26,9 +26,7 @@ export const nunjucks = async ( env.render(name, { ...ctx, ...ctx._locals.njkCtx }, cb); }; - const routeNameResolver = RouteNameResolver.fromApp(app); - const resolve = routeNameResolver.createResolveFn(); - const getName = routeNameResolver.createGetNameFn(); + const routeNameResolver = app.get(RouteNameResolver); const ctxProcessors: ContextProcessorFn[] = [ (ctx, req, _res) => { @@ -36,13 +34,13 @@ export const nunjucks = async ( ctx.path = (name: string, params: object = {}) => { try { - return resolve(name, params); + return routeNameResolver.resolve(name, params); } catch { return '#'; } }; - ctx.view_name = getName(req.url); + ctx.view_name = routeNameResolver.getName(req.url); } ]; diff --git a/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts b/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts new file mode 100644 index 00000000..876d046c --- /dev/null +++ b/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts @@ -0,0 +1,53 @@ +import { + BadRequestException, + Body, + Controller, + Get, + Inject, + Post, + Render, + Res, + UseGuards +} from '@nestjs/common'; +import { Response } from 'express'; +import { ICommandBus } from 'src/Application/ICommandBus'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; +import { CreateCustomerCommand } from 'src/Application/Customer/Command/CreateCustomerCommand'; +import { AddCustomerDTO } from '../DTO/AddCustomerDTO'; +import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; + +@Controller('app/faircalendar/events/add') +@UseGuards(IsAuthenticatedGuard) +export class AddCustomerController { + constructor( + @Inject('ICommandBus') + private readonly commandBus: ICommandBus, + private readonly routeNameResolver: RouteNameResolver + ) {} + + @Get() + @WithName('crm_customers_add') + @Render('pages/customers_add') + public async get() { + return {}; + } + + @Post() + public async index( + @Body() customerDto: AddCustomerDTO, + @Res() res: Response + ) { + const { street, city, zipCode, country, name } = customerDto; + + try { + await this.commandBus.execute( + new CreateCustomerCommand(name, street, city, zipCode, country) + ); + + res.redirect(303, this.routeNameResolver.resolve('crm_customers_list')); + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/Customer/Controller/ListCustomersController.ts b/server/src/Infrastructure/Customer/Controller/ListCustomersController.ts new file mode 100644 index 00000000..62ee78de --- /dev/null +++ b/server/src/Infrastructure/Customer/Controller/ListCustomersController.ts @@ -0,0 +1,33 @@ +import { + Controller, + Inject, + UseGuards, + Get, + Query, + Render +} from '@nestjs/common'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { GetCustomersQuery } from 'src/Application/Customer/Query/GetCustomersQuery'; +import { PaginationDTO } from 'src/Infrastructure/Common/DTO/PaginationDTO'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; + +@Controller('app/customers') +@UseGuards(IsAuthenticatedGuard) +export class ListCustomersController { + constructor( + @Inject('IQueryBus') + private readonly queryBus: IQueryBus + ) {} + + @Get() + @WithName('crm_customers_list') + @Render('pages/customers_index.njk') + public async index(@Query() pagination: PaginationDTO) { + const customers = await this.queryBus.execute( + new GetCustomersQuery(pagination.page) + ); + + return { customers }; + } +} diff --git a/server/src/Infrastructure/Customer/DTO/AddCustomerDTO.ts b/server/src/Infrastructure/Customer/DTO/AddCustomerDTO.ts new file mode 100644 index 00000000..79bab38c --- /dev/null +++ b/server/src/Infrastructure/Customer/DTO/AddCustomerDTO.ts @@ -0,0 +1,20 @@ +import { IsNotEmpty, MaxLength, IsISO31661Alpha2 } from 'class-validator'; + +export class AddCustomerDTO { + @IsNotEmpty() + public name: string; + + @IsNotEmpty() + public street: string; + + @IsNotEmpty() + public city: string; + + @IsNotEmpty() + @MaxLength(6) + public zipCode: string; + + @IsNotEmpty() + @IsISO31661Alpha2() + public country: string; +} diff --git a/server/src/Infrastructure/Customer/customer.module.ts b/server/src/Infrastructure/Customer/customer.module.ts index fe98dfcb..518e7252 100644 --- a/server/src/Infrastructure/Customer/customer.module.ts +++ b/server/src/Infrastructure/Customer/customer.module.ts @@ -14,14 +14,23 @@ import { UpdateCustomerAction } from './Action/UpdateCustomerAction'; import { GetCustomerAction } from './Action/GetCustomerAction'; import { AddressRepository } from './Repository/AddressRepository'; import { Address } from 'src/Domain/Customer/Address.entity'; +import { ListCustomersController } from './Controller/ListCustomersController'; +import { AddCustomerController } from './Controller/AddCustomerController'; +import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; @Module({ - imports: [BusModule, TypeOrmModule.forFeature([Customer, Address])], + imports: [ + BusModule, + TypeOrmModule.forFeature([Customer, Address]), + ExtendedRoutingModule + ], controllers: [ CreateCustomerAction, UpdateCustomerAction, GetCustomerAction, - GetCustomersAction + GetCustomersAction, + ListCustomersController, + AddCustomerController ], providers: [ { provide: 'ICustomerRepository', useClass: CustomerRepository }, diff --git a/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts b/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts index f2ae5eed..10b050c8 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts @@ -13,7 +13,7 @@ import { import { Response } from 'express'; import { ICommandBus } from 'src/Application/ICommandBus'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; -import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; import { AddEventControllerDTO } from '../DTO/AddEventControllerDTO'; import { AddEventDTO } from '../DTO/AddEventDTO'; import { AddEventCommand } from 'src/Application/FairCalendar/Command/AddEventCommand'; diff --git a/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts b/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts index 30470b24..c0046766 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts @@ -13,7 +13,7 @@ import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Secu import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; import { User } from 'src/Domain/HumanResource/User/User.entity'; import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; import { DeleteEventCommand } from 'src/Application/FairCalendar/Command/DeleteEventCommand'; @Controller('app/faircalendar/events/delete') diff --git a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts index 69e4e555..215cb694 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts @@ -10,7 +10,7 @@ import { User } from 'src/Domain/HumanResource/User/User.entity'; import { GetMonthlyFairCalendarQuery } from 'src/Application/FairCalendar/Query/GetMonthlyFairCalendarQuery'; import { IQueryBus } from 'src/Application/IQueryBus'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; -import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; import { FairCalendarControllerDTO } from '../DTO/FairCalendarControllerDTO'; import { EventView } from 'src/Application/FairCalendar/View/EventView'; import { ITranslator } from 'src/Application/ITranslations'; diff --git a/server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts b/server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts index 2e8ee41a..a78b02bb 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts @@ -12,7 +12,7 @@ import { } from '@nestjs/common'; import { ICommandBus } from 'src/Application/ICommandBus'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; -import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; import { AddEventControllerDTO } from '../DTO/AddEventControllerDTO'; import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; import { User } from 'src/Domain/HumanResource/User/User.entity'; diff --git a/server/src/Infrastructure/Home/Controller/HomeController.ts b/server/src/Infrastructure/Home/Controller/HomeController.ts index 2cfd5db9..62054e11 100644 --- a/server/src/Infrastructure/Home/Controller/HomeController.ts +++ b/server/src/Infrastructure/Home/Controller/HomeController.ts @@ -1,5 +1,5 @@ import { Controller, Get, Render, UseGuards } from '@nestjs/common'; -import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; @Controller('') diff --git a/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts index bcb201d3..409cb3ff 100644 --- a/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts +++ b/server/src/Infrastructure/HumanResource/User/Controller/LogoutController.ts @@ -6,7 +6,7 @@ import { Res } from '@nestjs/common'; import { Request, Response } from 'express'; -import { WithName } from 'src/Infrastructure/Common/Routing/WithName'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; @Controller('logout') export class LogoutController { diff --git a/server/src/app.module.ts b/server/src/app.module.ts index d79c2999..007fc3cc 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Module, Provider } from '@nestjs/common'; import { APP_FILTER, DiscoveryModule } from '@nestjs/core'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ConfigModule } from '@nestjs/config'; @@ -13,8 +13,9 @@ import { SettingsModule } from './Infrastructure/Settings/settings.module'; import { UnexpectedErrorFilter } from './Infrastructure/Common/ExceptionFilter/UnexpectedErrorFilter'; import { AuthRequiredFilter } from './Infrastructure/Common/ExceptionFilter/AuthRequiredFilter'; import { dataSourceOptions } from './datasource'; +import { ExtendedRoutingModule } from './Infrastructure/Common/ExtendedRouting/extendedRouting.module'; -const providers = []; +const providers: Provider[] = []; if (process.env.NODE_ENV !== 'production') { providers.push({ @@ -40,7 +41,8 @@ providers.push({ HumanResourceModule, ProjectModule, TaskModule, - SettingsModule + SettingsModule, + ExtendedRoutingModule ], providers }) diff --git a/server/src/assets/styles/_components/index.css b/server/src/assets/styles/_components/index.css index 0ec6b06e..92a0f311 100644 --- a/server/src/assets/styles/_components/index.css +++ b/server/src/assets/styles/_components/index.css @@ -7,3 +7,4 @@ @import './input/input.css'; @import './link/link.css'; @import './nav/nav.css'; +@import './table/table.css'; diff --git a/server/src/assets/styles/_components/table/table.css b/server/src/assets/styles/_components/table/table.css new file mode 100644 index 00000000..10be7b54 --- /dev/null +++ b/server/src/assets/styles/_components/table/table.css @@ -0,0 +1,27 @@ +.app-table { + border-collapse: collapse; + width: 100%; + white-space: nowrap; + box-shadow: var(--shadow-default); +} + +.app-table thead { + font-size: var(--font-size-sm); + font-weight: var(--font-weight-md); + text-align: left; + color: var(--text-muted); + text-transform: uppercase; + background-color: var(--background-alt-grey); +} + +.app-table :where(th, td) { + padding: calc(3 * var(--v)) calc(4 * var(--v)); +} + +.app-table tbody { + background-color: var(--background-default); +} + +.app-table tr { + border-bottom: 1px solid var(--border-default); +} diff --git a/server/src/assets/styles/_defaults.css b/server/src/assets/styles/_defaults.css index 76b8ce65..c9a6304e 100644 --- a/server/src/assets/styles/_defaults.css +++ b/server/src/assets/styles/_defaults.css @@ -22,12 +22,12 @@ button:not(:disabled):hover { background-color: var(--hover-tint); } -a { - color: inherit; +a:not(.pc-btn) { + color: currentColor; } -a:visited { - color: inherit; +a:not(.pc-btn):visited { + color: currentColor; } select { diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/_variables.css index 483bfa2c..b0274fd6 100644 --- a/server/src/assets/styles/_variables.css +++ b/server/src/assets/styles/_variables.css @@ -31,7 +31,7 @@ --background-error-hover: #b92020; --border-default: #e2e8f0; --text-default: #282828; - --text-muted: #555555; + --text-muted: #636363; --text-on-background-action-violet: #ffffff; --text-error: #ff0000; --text-on-error: #ffffff; diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk new file mode 100644 index 00000000..d7d1bb64 --- /dev/null +++ b/server/src/templates/components/nav.njk @@ -0,0 +1,62 @@ + diff --git a/server/src/templates/layouts/app.njk b/server/src/templates/layouts/app.njk index 4ac255f6..ea0ab5dc 100644 --- a/server/src/templates/layouts/app.njk +++ b/server/src/templates/layouts/app.njk @@ -34,68 +34,7 @@ - + {% include 'components/nav.njk' %}
    {% block main %}{% endblock main %} diff --git a/server/src/templates/macros/customer_form.njk b/server/src/templates/macros/customer_form.njk new file mode 100644 index 00000000..9e5a2927 --- /dev/null +++ b/server/src/templates/macros/customer_form.njk @@ -0,0 +1,29 @@ +{% macro customer_form(class_name='') %} +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + + + + +
    +{% endmacro %} diff --git a/server/src/templates/macros/table.njk b/server/src/templates/macros/table.njk new file mode 100644 index 00000000..3f06fc89 --- /dev/null +++ b/server/src/templates/macros/table.njk @@ -0,0 +1,34 @@ +{% macro table(items) %} + + + + + + + + + + {% for item in items %} + + + + + + {% else %} + + + + {% endfor %} + +
    {{ 'crm-customers-name'|trans }}{{ 'crm-customers-street'|trans }}{{ 'common-actions'|trans }}
    {{ item.name }} + {{ item.address.street }} +
    + {{ item.address.zipCode }} {{ item.address.city }} +
    + {{ item.address.country }} +
    +
    + {# #} +
    +
    Vide
    +{% endmacro %} diff --git a/server/src/templates/pages/customers_add.njk b/server/src/templates/pages/customers_add.njk new file mode 100644 index 00000000..13773b49 --- /dev/null +++ b/server/src/templates/pages/customers_add.njk @@ -0,0 +1,14 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/customer_form.njk' import customer_form %} + +{% block main_class %}pc-container{% endblock %} + +{% block main %} +

    + {{ 'crm-customers-add-title'|trans }} +

    + +
    + {{ customer_form(class_name='pc-card__content') }} +
    +{% endblock main %} diff --git a/server/src/templates/pages/customers_index.njk b/server/src/templates/pages/customers_index.njk new file mode 100644 index 00000000..2a3db217 --- /dev/null +++ b/server/src/templates/pages/customers_index.njk @@ -0,0 +1,13 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/table.njk' import table %} + +{% block main_class %}pc-container{% endblock %} + +{% block main %} +
    +

    {{ 'crm-customers-title'|trans }}

    + {{ 'common-add'|trans }} +
    + + {{ table(customers.items) }} +{% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index d37f800f..80509c69 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -1,5 +1,7 @@ common-form-save = Enregistrer common-form-delete = Supprimer +common-add = Ajouter +common-actions = Actions site-title = Permacoop @@ -23,7 +25,14 @@ faircalendar-filters-month-title = Filtrer par mois faircalendar-filters-userId-title = Filtrer par coopérateur-salarié crm-title = FairCRM + crm-customers-title = Clients +crm-customers-add-title = Ajouter un client +crm-customers-name = Nom du client +crm-customers-street = Adresse +crm-customers-zipCode = Code postal +crm-customers-city = Ville + crm-projects-title = Projets accounts-title = FairRH diff --git a/server/tsconfig.json b/server/tsconfig.json index 69f185fd..5d454b79 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -11,5 +11,5 @@ "baseUrl": "./", "incremental": true }, - "exclude": ["node_modules", "dist"] + "exclude": ["node_modules", "dist", "tsconfig.json"] } From 22665683c017b231212ea36e148a56b9bbe2a353 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 14:40:02 +0200 Subject: [PATCH 13/49] Add customer edit, update nav --- .../Customer/Action/CreateCustomerAction.ts | 47 ------------ .../Customer/Action/GetCustomerAction.ts | 39 ---------- .../Customer/Action/GetCustomersAction.ts | 31 -------- .../Customer/Action/UpdateCustomerAction.ts | 50 ------------- .../Controller/AddCustomerController.ts | 11 +-- .../Controller/EditCustomerController.ts | 73 +++++++++++++++++++ .../Customer/DTO/AddCustomerDTO.ts | 20 ----- .../Customer/DTO/CustomerDTO.ts | 22 +++--- .../Customer/customer.module.ts | 12 +-- .../styles/_components/button/button.css | 4 - .../assets/styles/_components/icon/icon.css | 4 + .../assets/styles/_components/input/input.css | 14 ++++ .../src/assets/styles/_components/nav/nav.css | 26 +++++-- .../assets/styles/_components/table/table.css | 1 - server/src/assets/styles/_defaults.css | 10 --- server/src/assets/styles/_variables.css | 7 +- server/src/templates/components/nav.njk | 4 +- server/src/templates/macros/customer_form.njk | 12 +-- .../faircalendar_event_form.njk | 4 +- server/src/templates/macros/icons.njk | 6 ++ server/src/templates/macros/table.njk | 8 +- server/src/templates/pages/customers_edit.njk | 14 ++++ .../src/templates/pages/customers_index.njk | 2 +- .../pages/faircalendar_events_add.njk | 8 +- .../pages/faircalendar_events_edit.njk | 7 +- server/src/translations/fr-FR.ftl | 2 + 26 files changed, 183 insertions(+), 255 deletions(-) delete mode 100644 server/src/Infrastructure/Customer/Action/CreateCustomerAction.ts delete mode 100644 server/src/Infrastructure/Customer/Action/GetCustomerAction.ts delete mode 100644 server/src/Infrastructure/Customer/Action/GetCustomersAction.ts delete mode 100644 server/src/Infrastructure/Customer/Action/UpdateCustomerAction.ts create mode 100644 server/src/Infrastructure/Customer/Controller/EditCustomerController.ts delete mode 100644 server/src/Infrastructure/Customer/DTO/AddCustomerDTO.ts rename server/src/templates/{components => macros}/faircalendar_event_form.njk (91%) create mode 100644 server/src/templates/pages/customers_edit.njk diff --git a/server/src/Infrastructure/Customer/Action/CreateCustomerAction.ts b/server/src/Infrastructure/Customer/Action/CreateCustomerAction.ts deleted file mode 100644 index d27e956a..00000000 --- a/server/src/Infrastructure/Customer/Action/CreateCustomerAction.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { - Body, - Post, - Controller, - Inject, - BadRequestException, - UseGuards -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { CreateCustomerCommand } from 'src/Application/Customer/Command/CreateCustomerCommand'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { CustomerDTO } from '../DTO/CustomerDTO'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; - -@Controller('customers') -@ApiTags('Customer') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class CreateCustomerAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Post() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Create new customer' }) - public async index(@Body() customerDto: CustomerDTO) { - const { - address: { street, city, zipCode, country }, - name - } = customerDto; - - try { - const id = await this.commandBus.execute( - new CreateCustomerCommand(name, street, city, zipCode, country) - ); - - return { id }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/Customer/Action/GetCustomerAction.ts b/server/src/Infrastructure/Customer/Action/GetCustomerAction.ts deleted file mode 100644 index b86bc422..00000000 --- a/server/src/Infrastructure/Customer/Action/GetCustomerAction.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - Controller, - Inject, - UseGuards, - Get, - Param, - NotFoundException -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { CustomerView } from 'src/Application/Customer/View/CustomerView'; -import { GetCustomerByIdQuery } from 'src/Application/Customer/Query/GetCustomerByIdQuery'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; - -@Controller('customers') -@ApiTags('Customer') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetCustomerAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get customer' }) - public async index(@Param() dto: IdDTO): Promise { - try { - return await this.queryBus.execute(new GetCustomerByIdQuery(dto.id)); - } catch (e) { - throw new NotFoundException(e.message); - } - } -} diff --git a/server/src/Infrastructure/Customer/Action/GetCustomersAction.ts b/server/src/Infrastructure/Customer/Action/GetCustomersAction.ts deleted file mode 100644 index a87530a8..00000000 --- a/server/src/Infrastructure/Customer/Action/GetCustomersAction.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Controller, Inject, UseGuards, Get, Query } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { CustomerView } from 'src/Application/Customer/View/CustomerView'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { GetCustomersQuery } from 'src/Application/Customer/Query/GetCustomersQuery'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { PaginationDTO } from 'src/Infrastructure/Common/DTO/PaginationDTO'; -import { Pagination } from 'src/Application/Common/Pagination'; - -@Controller('customers') -@ApiTags('Customer') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetCustomersAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get all customers' }) - public async index( - @Query() pagination: PaginationDTO - ): Promise> { - return await this.queryBus.execute(new GetCustomersQuery(pagination.page)); - } -} diff --git a/server/src/Infrastructure/Customer/Action/UpdateCustomerAction.ts b/server/src/Infrastructure/Customer/Action/UpdateCustomerAction.ts deleted file mode 100644 index 843ada7c..00000000 --- a/server/src/Infrastructure/Customer/Action/UpdateCustomerAction.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { - Body, - Controller, - Inject, - BadRequestException, - UseGuards, - Put, - Param -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { UpdateCustomerCommand } from 'src/Application/Customer/Command/UpdateCustomerCommand'; -import { CustomerDTO } from '../DTO/CustomerDTO'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; - -@Controller('customers') -@ApiTags('Customer') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class UpdateCustomerAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Put(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Update customer' }) - public async index(@Param() dto: IdDTO, @Body() customerDto: CustomerDTO) { - try { - const { - address: { street, city, zipCode, country }, - name - } = customerDto; - const { id } = dto; - - await this.commandBus.execute( - new UpdateCustomerCommand(id, name, street, city, zipCode, country) - ); - - return { id }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts b/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts index 876d046c..579f6943 100644 --- a/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts +++ b/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts @@ -14,7 +14,7 @@ import { ICommandBus } from 'src/Application/ICommandBus'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; import { CreateCustomerCommand } from 'src/Application/Customer/Command/CreateCustomerCommand'; -import { AddCustomerDTO } from '../DTO/AddCustomerDTO'; +import { CustomerDTO } from '../DTO/CustomerDTO'; import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; @Controller('app/faircalendar/events/add') @@ -23,7 +23,7 @@ export class AddCustomerController { constructor( @Inject('ICommandBus') private readonly commandBus: ICommandBus, - private readonly routeNameResolver: RouteNameResolver + private readonly resolver: RouteNameResolver ) {} @Get() @@ -34,10 +34,7 @@ export class AddCustomerController { } @Post() - public async index( - @Body() customerDto: AddCustomerDTO, - @Res() res: Response - ) { + public async index(@Body() customerDto: CustomerDTO, @Res() res: Response) { const { street, city, zipCode, country, name } = customerDto; try { @@ -45,7 +42,7 @@ export class AddCustomerController { new CreateCustomerCommand(name, street, city, zipCode, country) ); - res.redirect(303, this.routeNameResolver.resolve('crm_customers_list')); + res.redirect(303, this.resolver.resolve('crm_customers_list')); } catch (e) { throw new BadRequestException(e.message); } diff --git a/server/src/Infrastructure/Customer/Controller/EditCustomerController.ts b/server/src/Infrastructure/Customer/Controller/EditCustomerController.ts new file mode 100644 index 00000000..51bd307a --- /dev/null +++ b/server/src/Infrastructure/Customer/Controller/EditCustomerController.ts @@ -0,0 +1,73 @@ +import { + BadRequestException, + Body, + Controller, + Get, + Inject, + Param, + Post, + Render, + Res, + UseGuards +} from '@nestjs/common'; +import { ICommandBus } from 'src/Application/ICommandBus'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { Response } from 'express'; +import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; +import { GetCustomerByIdQuery } from 'src/Application/Customer/Query/GetCustomerByIdQuery'; +import { CustomerDTO } from '../DTO/CustomerDTO'; +import { UpdateCustomerCommand } from 'src/Application/Customer/Command/UpdateCustomerCommand'; +import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; + +@Controller('app/customers/edit') +@UseGuards(IsAuthenticatedGuard) +export class EditCustomerController { + constructor( + @Inject('ICommandBus') + private readonly commandBus: ICommandBus, + @Inject('IQueryBus') + private readonly queryBus: IQueryBus, + private readonly resolver: RouteNameResolver + ) {} + + @Get(':id') + @WithName('crm_customers_edit') + @Render('pages/customers_edit') + public async get(@Param() idDto: IdDTO) { + const customer = await this.queryBus.execute( + new GetCustomerByIdQuery(idDto.id) + ); + + return { + customer + }; + } + + @Post(':id') + public async post( + @Param() idDto: IdDTO, + @Body() dto: CustomerDTO, + @Res() res: Response + ) { + const { name, street, zipCode, city, country } = dto; + + try { + await this.commandBus.execute( + new UpdateCustomerCommand( + idDto.id, + name, + street, + city, + zipCode, + country + ) + ); + + res.redirect(303, this.resolver.resolve('crm_customers_list')); + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/Customer/DTO/AddCustomerDTO.ts b/server/src/Infrastructure/Customer/DTO/AddCustomerDTO.ts deleted file mode 100644 index 79bab38c..00000000 --- a/server/src/Infrastructure/Customer/DTO/AddCustomerDTO.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { IsNotEmpty, MaxLength, IsISO31661Alpha2 } from 'class-validator'; - -export class AddCustomerDTO { - @IsNotEmpty() - public name: string; - - @IsNotEmpty() - public street: string; - - @IsNotEmpty() - public city: string; - - @IsNotEmpty() - @MaxLength(6) - public zipCode: string; - - @IsNotEmpty() - @IsISO31661Alpha2() - public country: string; -} diff --git a/server/src/Infrastructure/Customer/DTO/CustomerDTO.ts b/server/src/Infrastructure/Customer/DTO/CustomerDTO.ts index 6f420580..ff9146ae 100644 --- a/server/src/Infrastructure/Customer/DTO/CustomerDTO.ts +++ b/server/src/Infrastructure/Customer/DTO/CustomerDTO.ts @@ -1,16 +1,20 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; -import { IsNotEmpty, ValidateNested } from 'class-validator'; -import { AddressDTO } from './AddressDTO'; +import { IsNotEmpty, MaxLength, IsISO31661Alpha2 } from 'class-validator'; export class CustomerDTO { - @ApiProperty() @IsNotEmpty() public name: string; - @ApiProperty({ type: AddressDTO }) - @ValidateNested() @IsNotEmpty() - @Type(() => AddressDTO) - public address: AddressDTO; + public street: string; + + @IsNotEmpty() + public city: string; + + @IsNotEmpty() + @MaxLength(6) + public zipCode: string; + + @IsNotEmpty() + @IsISO31661Alpha2() + public country: string; } diff --git a/server/src/Infrastructure/Customer/customer.module.ts b/server/src/Infrastructure/Customer/customer.module.ts index 518e7252..a160c39a 100644 --- a/server/src/Infrastructure/Customer/customer.module.ts +++ b/server/src/Infrastructure/Customer/customer.module.ts @@ -3,20 +3,17 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { BusModule } from '../bus.module'; import { CustomerRepository } from './Repository/CustomerRepository'; import { Customer } from 'src/Domain/Customer/Customer.entity'; -import { CreateCustomerAction } from './Action/CreateCustomerAction'; import { IsCustomerAlreadyExist } from 'src/Domain/Customer/Specification/IsCustomerAlreadyExist'; import { CreateCustomerCommandHandler } from 'src/Application/Customer/Command/CreateCustomerCommandHandler'; import { GetCustomerByIdQueryHandler } from 'src/Application/Customer/Query/GetCustomerByIdQueryHandler'; import { GetCustomersQueryHandler } from 'src/Application/Customer/Query/GetCustomersQueryHandler'; -import { GetCustomersAction } from './Action/GetCustomersAction'; import { UpdateCustomerCommandHandler } from 'src/Application/Customer/Command/UpdateCustomerCommandHandler'; -import { UpdateCustomerAction } from './Action/UpdateCustomerAction'; -import { GetCustomerAction } from './Action/GetCustomerAction'; import { AddressRepository } from './Repository/AddressRepository'; import { Address } from 'src/Domain/Customer/Address.entity'; import { ListCustomersController } from './Controller/ListCustomersController'; import { AddCustomerController } from './Controller/AddCustomerController'; import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; +import { EditCustomerController } from './Controller/EditCustomerController'; @Module({ imports: [ @@ -25,12 +22,9 @@ import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting ExtendedRoutingModule ], controllers: [ - CreateCustomerAction, - UpdateCustomerAction, - GetCustomerAction, - GetCustomersAction, ListCustomersController, - AddCustomerController + AddCustomerController, + EditCustomerController ], providers: [ { provide: 'ICustomerRepository', useClass: CustomerRepository }, diff --git a/server/src/assets/styles/_components/button/button.css b/server/src/assets/styles/_components/button/button.css index adbf6aa7..b8fa9c7f 100644 --- a/server/src/assets/styles/_components/button/button.css +++ b/server/src/assets/styles/_components/button/button.css @@ -7,10 +7,6 @@ font-weight: var(--font-weight-md); } -.pc-btn--small { - font-size: var(--font-size-sm); -} - .pc-btn:hover { background-color: var(--hover-tint); } diff --git a/server/src/assets/styles/_components/icon/icon.css b/server/src/assets/styles/_components/icon/icon.css index 5d213cdd..04e415a3 100644 --- a/server/src/assets/styles/_components/icon/icon.css +++ b/server/src/assets/styles/_components/icon/icon.css @@ -2,6 +2,10 @@ color: var(--text-error); } +.pc-icon--action-violet { + color: var(--text-action-violet); +} + .pc-icon--sm { width: calc(6 * var(--v)); height: calc(6 * var(--v)); diff --git a/server/src/assets/styles/_components/input/input.css b/server/src/assets/styles/_components/input/input.css index d3e92a8c..e2db3bd3 100644 --- a/server/src/assets/styles/_components/input/input.css +++ b/server/src/assets/styles/_components/input/input.css @@ -3,8 +3,13 @@ } .pc-input-group > input { + appearance: none; display: block; width: 100%; + background-color: var(--background-default); + border: 1px solid var(--border-default); + border-radius: var(--radius-sm); + padding: calc(2 * var(--v)) calc(3 * var(--v)); } .pc-select-group { @@ -13,7 +18,16 @@ .pc-input-group > select { display: block; + appearance: none; width: 100%; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23a0aec0'%3E%3Cpath d='M15.3 9.3a1 1 0 011.4 1.4l-4 4a1 1 0 01-1.4 0l-4-4a1 1 0 011.4-1.4l3.3 3.29 3.3-3.3z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-color: var(--background-default); + background-position: right var(--w) center; + background-size: calc(3 * var(--w)) calc(3 * var(--w)); + border: 1px solid var(--border-default); + border-radius: var(--radius-sm); + padding: var(--w) calc(5 * var(--w)) var(--w) calc(3 * var(--v)); } :where(.pc-input-group, .pc-select-group) > label { diff --git a/server/src/assets/styles/_components/nav/nav.css b/server/src/assets/styles/_components/nav/nav.css index 39658820..22ee8ac3 100644 --- a/server/src/assets/styles/_components/nav/nav.css +++ b/server/src/assets/styles/_components/nav/nav.css @@ -7,30 +7,40 @@ padding: 0; } +.pc-nav li.active { + position: relative; +} + +.pc-nav li.active > details > summary { + font-weight: bold; +} + .pc-nav > ul > li ul { list-style-type: none; padding: 0; margin: 0 calc(2 * var(--w)); - font-size: var(--font-size-sm); box-shadow: var(--shadow-inner); background-color: var(--background-alt-grey); } +.pc-nav details > summary { + cursor: pointer; + color: var(--text-muted); +} + +.pc-nav details > summary::after { + content: '⌄'; +} + .pc-nav a, .pc-nav details > summary { display: inline-flex; column-gap: calc(2 * var(--v)); align-items: center; width: 100%; - font-size: var(--font-size-sm); padding: calc(3 * var(--v)) calc(5 * var(--v)); } -.pc-nav details > summary { - cursor: pointer; - color: var(--text-muted); -} - .pc-nav a[aria-current='page'] { font-weight: bold; } @@ -43,7 +53,7 @@ position: relative; } -.pc-nav a[aria-current='page']::before { +.pc-nav :where(li.active, > ul > li > a[aria-current='page'])::before { position: absolute; content: ''; inset: 0; diff --git a/server/src/assets/styles/_components/table/table.css b/server/src/assets/styles/_components/table/table.css index 10be7b54..21cf52b7 100644 --- a/server/src/assets/styles/_components/table/table.css +++ b/server/src/assets/styles/_components/table/table.css @@ -6,7 +6,6 @@ } .app-table thead { - font-size: var(--font-size-sm); font-weight: var(--font-weight-md); text-align: left; color: var(--text-muted); diff --git a/server/src/assets/styles/_defaults.css b/server/src/assets/styles/_defaults.css index c9a6304e..a35b271e 100644 --- a/server/src/assets/styles/_defaults.css +++ b/server/src/assets/styles/_defaults.css @@ -32,14 +32,4 @@ a:not(.pc-btn):visited { select { display: block; - appearance: none; - width: 100%; - background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23a0aec0'%3E%3Cpath d='M15.3 9.3a1 1 0 011.4 1.4l-4 4a1 1 0 01-1.4 0l-4-4a1 1 0 011.4-1.4l3.3 3.29 3.3-3.3z'/%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-color: var(--background-default); - background-position: right var(--w) center; - background-size: calc(3 * var(--w)) calc(3 * var(--w)); - border: 1px solid var(--border-default); - border-radius: var(--v); - padding: var(--w) calc(5 * var(--w)) var(--w) calc(3 * var(--v)); } diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/_variables.css index b0274fd6..ca9fcb9f 100644 --- a/server/src/assets/styles/_variables.css +++ b/server/src/assets/styles/_variables.css @@ -16,7 +16,7 @@ --font-default: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; - --font-size-md: 1.1rem; + --font-size-md: 0.95rem; --font-size-sm: calc(0.8 * var(--font-size-md)); --font-size-lg: calc(1.2 * var(--font-size-md)); --font-size-default: var(--font-size-md); @@ -29,12 +29,15 @@ --background-action-violet-hover: #52289b; --background-error: #dd1d1d; --background-error-hover: #b92020; - --border-default: #e2e8f0; --text-default: #282828; --text-muted: #636363; --text-on-background-action-violet: #ffffff; + --text-action-violet: #6c2bd9; --text-error: #ff0000; --text-on-error: #ffffff; + /* Borders */ + --border-default: #e2e8f0; + --radius-sm: var(--v); /* Shadows */ --shadow-default: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk index d7d1bb64..86a8f3fe 100644 --- a/server/src/templates/components/nav.njk +++ b/server/src/templates/components/nav.njk @@ -24,12 +24,12 @@
    • - + {{ "crm-customers-title"|trans|capitalize }}
    • - + {{ "crm-projects-title"|trans|capitalize }}
    • diff --git a/server/src/templates/macros/customer_form.njk b/server/src/templates/macros/customer_form.njk index 9e5a2927..69569cff 100644 --- a/server/src/templates/macros/customer_form.njk +++ b/server/src/templates/macros/customer_form.njk @@ -1,26 +1,26 @@ -{% macro customer_form(class_name='') %} +{% macro customer_form(customer=null, class_name='') %}
      - +
      - +
      - +
      - +
      - + +
      +{% endmacro %} diff --git a/server/src/templates/macros/table.njk b/server/src/templates/macros/table.njk index cbb1b718..88066620 100644 --- a/server/src/templates/macros/table.njk +++ b/server/src/templates/macros/table.njk @@ -1,34 +1,40 @@ {% import 'macros/icons.njk' as icons %} -{% macro table(items) %} +{% macro render_table(table) %} - - - + {% for column in table.columns %} + + {% endfor %} - {% for item in items %} + {% for row in table.rows %} - - - + {% for value in row %} + {% if value.actions %} + + {% else %} + + {% endif %} + {% endfor %} {% else %} - + {% endfor %} diff --git a/server/src/templates/pages/customers_index.njk b/server/src/templates/pages/customers_index.njk index 10d73e53..4bd8c694 100644 --- a/server/src/templates/pages/customers_index.njk +++ b/server/src/templates/pages/customers_index.njk @@ -1,5 +1,5 @@ {% extends 'layouts/app.njk' %} -{% from 'macros/table.njk' import table with context %} +{% from 'macros/table.njk' import render_table with context %} {% block main_class %}pc-container{% endblock %} @@ -9,5 +9,5 @@ {{ 'common-add'|trans }} - {{ table(customers.items) }} + {{ render_table(table) }} {% endblock main %} diff --git a/server/src/templates/pages/projects_add.njk b/server/src/templates/pages/projects_add.njk new file mode 100644 index 00000000..b666155b --- /dev/null +++ b/server/src/templates/pages/projects_add.njk @@ -0,0 +1,14 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/project_form.njk' import project_form %} + +{% block main_class %}pc-container{% endblock %} + +{% block main %} +

      + {{ 'crm-projects-add-title'|trans }} +

      + +
      + {{ project_form(null, customers, class_name='pc-card__content') }} +
      +{% endblock main %} diff --git a/server/src/templates/pages/projects_edit.njk b/server/src/templates/pages/projects_edit.njk new file mode 100644 index 00000000..8e92674e --- /dev/null +++ b/server/src/templates/pages/projects_edit.njk @@ -0,0 +1,14 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/project_form.njk' import project_form %} + +{% block main_class %}pc-container{% endblock %} + +{% block main %} +

      + {{ 'crm-projects-edit-title'|trans({name: project.name }) }} +

      + +
      + {{ project_form(project, customers, class_name='pc-card__content') }} +
      +{% endblock main %} diff --git a/server/src/templates/pages/projects_list.njk b/server/src/templates/pages/projects_list.njk new file mode 100644 index 00000000..b1f085f0 --- /dev/null +++ b/server/src/templates/pages/projects_list.njk @@ -0,0 +1,13 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/table.njk' import render_table with context %} + +{% block main_class %}pc-container{% endblock %} + +{% block main %} +
      +

      {{ 'crm-projects-title'|trans }}

      + {{ 'common-add'|trans }} +
      + + {{ render_table(table) }} +{% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index 08b549f0..ac8d7bea 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -36,6 +36,10 @@ crm-customers-zipCode = Code postal crm-customers-city = Ville crm-projects-title = Projets +crm-projects-add-title = Ajouter un projet +crm-projects-edit-title = Édition du projet "{$name}" +crm-projects-name-title = Nom du projet +crm-projects-customer-title = Client accounts-title = FairRH accounts-workers-title = Coopérateurs - salariés From 28aa0c0eb869657740942b11398da726ffe4bbb3 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 16:19:00 +0200 Subject: [PATCH 16/49] Add breadcrumbs --- .../assets/styles/_components/brand/brand.css | 13 ---------- .../_components/breadcrumb/breadcrumb.css | 21 ++++++++++++++++ .../src/assets/styles/_components/index.css | 2 +- server/src/assets/styles/_utilities.css | 1 + server/src/templates/macros/breadcrumb.njk | 25 +++++++++++++++++++ server/src/templates/pages/customers_edit.njk | 7 +++++- .../src/templates/pages/customers_index.njk | 7 ++++-- .../templates/pages/faircalendar_index.njk | 7 +++++- server/src/templates/pages/projects_edit.njk | 7 +++++- server/src/templates/pages/projects_list.njk | 7 ++++-- 10 files changed, 76 insertions(+), 21 deletions(-) delete mode 100644 server/src/assets/styles/_components/brand/brand.css create mode 100644 server/src/assets/styles/_components/breadcrumb/breadcrumb.css create mode 100644 server/src/templates/macros/breadcrumb.njk diff --git a/server/src/assets/styles/_components/brand/brand.css b/server/src/assets/styles/_components/brand/brand.css deleted file mode 100644 index de659ca1..00000000 --- a/server/src/assets/styles/_components/brand/brand.css +++ /dev/null @@ -1,13 +0,0 @@ -.pc-brand { - display: inline-flex; - align-items: center; - column-gap: calc(3 * var(--v)); - padding: calc(6 * var(--v)); - font-size: var(--font-size-lg); - font-weight: bold; -} - -.pc-brand__logo { - width: calc(8 * var(--v)); - height: calc(8 * var(--v)); -} diff --git a/server/src/assets/styles/_components/breadcrumb/breadcrumb.css b/server/src/assets/styles/_components/breadcrumb/breadcrumb.css new file mode 100644 index 00000000..a29fe798 --- /dev/null +++ b/server/src/assets/styles/_components/breadcrumb/breadcrumb.css @@ -0,0 +1,21 @@ +nav[role='navigation'][aria-label].pc-breadcrumb { + color: var(--text-muted); + background-color: var(--background-default); + box-shadow: var(--shadow-default); + padding: var(--w); + margin-bottom: calc(4 * var(--v)); + /* flex p-2 mt-6 mb-6 text-sm text-gray-500 bg-white rounded-lg shadow-md dark:bg-gray-800 */ +} + +.pc-breadcrumb > ol { + list-style-type: none; + padding: 0; + margin: 0; + display: inline-flex; + align-items: center; +} + +.pc-breadcrumb li:not(:first-child)::before { + content: '/'; + margin-inline: var(--w); +} diff --git a/server/src/assets/styles/_components/index.css b/server/src/assets/styles/_components/index.css index 92a0f311..ffe41087 100644 --- a/server/src/assets/styles/_components/index.css +++ b/server/src/assets/styles/_components/index.css @@ -1,4 +1,4 @@ -@import './brand/brand.css'; +@import './breadcrumb/breadcrumb.css'; @import './button/button.css'; @import './card/card.css'; @import './container/container.css'; diff --git a/server/src/assets/styles/_utilities.css b/server/src/assets/styles/_utilities.css index 10d88fe3..8e765aa8 100644 --- a/server/src/assets/styles/_utilities.css +++ b/server/src/assets/styles/_utilities.css @@ -5,6 +5,7 @@ .pc-row { display: flex; + gap: var(--row-gap, 0); } .pc-row--middle { diff --git a/server/src/templates/macros/breadcrumb.njk b/server/src/templates/macros/breadcrumb.njk new file mode 100644 index 00000000..e98c829a --- /dev/null +++ b/server/src/templates/macros/breadcrumb.njk @@ -0,0 +1,25 @@ +{% import 'macros/icons.njk' as icons %} + +{% macro breadcrumb(items) %} + +{% endmacro %} diff --git a/server/src/templates/pages/customers_edit.njk b/server/src/templates/pages/customers_edit.njk index ee83569b..fc0cb8e0 100644 --- a/server/src/templates/pages/customers_edit.njk +++ b/server/src/templates/pages/customers_edit.njk @@ -1,11 +1,16 @@ {% extends 'layouts/app.njk' %} {% from 'macros/customer_form.njk' import customer_form %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% block main_class %}pc-container{% endblock %} +{% set title = 'crm-customers-edit-title'|trans({name: customer.name }) %} + {% block main %} + {{ breadcrumb([{ title: 'crm-customers-title'|trans, href: path('crm_customers_list') }, { title: title }]) }} +

      - {{ 'crm-customers-edit-title'|trans({name: customer.name }) }} + {{ title }}

      diff --git a/server/src/templates/pages/customers_index.njk b/server/src/templates/pages/customers_index.njk index 4bd8c694..13b40d5d 100644 --- a/server/src/templates/pages/customers_index.njk +++ b/server/src/templates/pages/customers_index.njk @@ -1,12 +1,15 @@ {% extends 'layouts/app.njk' %} {% from 'macros/table.njk' import render_table with context %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% block main_class %}pc-container{% endblock %} {% block main %} -
      + {{ breadcrumb([{ title: 'crm-customers-title'|trans }]) }} + +

      {{ 'crm-customers-title'|trans }}

      - {{ 'common-add'|trans }} + {{ 'common-add'|trans }}
      {{ render_table(table) }} diff --git a/server/src/templates/pages/faircalendar_index.njk b/server/src/templates/pages/faircalendar_index.njk index 8d0978b6..54af635f 100644 --- a/server/src/templates/pages/faircalendar_index.njk +++ b/server/src/templates/pages/faircalendar_index.njk @@ -1,9 +1,14 @@ {% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% block main_class %}pc-container{% endblock %} +{% set title = 'faircalendar-title'|trans %} + {% block main %} -

      {{ 'faircalendar-title'|trans }}

      +{{ breadcrumb([{ title: title}]) }} + +

      {{ title }}

      diff --git a/server/src/templates/pages/projects_edit.njk b/server/src/templates/pages/projects_edit.njk index 8e92674e..804dcc6e 100644 --- a/server/src/templates/pages/projects_edit.njk +++ b/server/src/templates/pages/projects_edit.njk @@ -1,11 +1,16 @@ {% extends 'layouts/app.njk' %} {% from 'macros/project_form.njk' import project_form %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% block main_class %}pc-container{% endblock %} +{% set title = 'crm-projects-edit-title'|trans({name: project.name }) %} + {% block main %} + {{ breadcrumb([{ title: 'crm-projects-title'|trans, href: path('crm_projects_list') }, { title: title }]) }} +

      - {{ 'crm-projects-edit-title'|trans({name: project.name }) }} + {{ title }}

      diff --git a/server/src/templates/pages/projects_list.njk b/server/src/templates/pages/projects_list.njk index b1f085f0..07a2fd3b 100644 --- a/server/src/templates/pages/projects_list.njk +++ b/server/src/templates/pages/projects_list.njk @@ -1,12 +1,15 @@ {% extends 'layouts/app.njk' %} {% from 'macros/table.njk' import render_table with context %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% block main_class %}pc-container{% endblock %} {% block main %} -
      + {{ breadcrumb([{ title: 'crm-projects-title'|trans }]) }} + +

      {{ 'crm-projects-title'|trans }}

      - {{ 'common-add'|trans }} + {{ 'common-add'|trans }}
      {{ render_table(table) }} From 9252a759390944e47789be043f0cacaf20635b5f Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 18:21:33 +0200 Subject: [PATCH 17/49] Add tasks, refactor templates per resource --- .../Controller/AddCustomerController.ts | 4 +- .../Controller/EditCustomerController.ts | 2 +- .../Controller/ListCustomersController.ts | 4 +- .../Controller/AddEventController.ts | 2 +- .../Controller/DeleteEventController.ts | 2 +- ...ntController.ts => EditEventController.ts} | 4 +- .../Controller/FairCalendarController.ts | 2 +- .../FairCalendar/faircalendar.module.ts | 4 +- .../Controller/AddProjectController.ts | 4 +- .../Controller/EditProjectController.ts | 2 +- .../Controller/ListProjectsController.ts | 4 +- .../Task/Action/CreateTaskAction.ts | 42 ------------- .../Task/Action/GetTaskAction.ts | 39 ------------ .../Task/Action/GetTasksAction.ts | 31 ---------- .../Task/Action/UpdateTaskAction.ts | 43 ------------- .../Task/Controller/AddTaskController.ts | 48 ++++++++++++++ .../Task/Controller/EditTaskController.ts | 62 +++++++++++++++++++ .../Task/Controller/ListTasksController.ts | 39 ++++++++++++ server/src/Infrastructure/Task/DTO/TaskDTO.ts | 2 - .../Task/Table/TaskTableFactory.ts | 28 +++++++++ server/src/Infrastructure/Task/task.module.ts | 21 +++---- server/src/templates/components/nav.njk | 5 ++ .../customers/_form.njk} | 0 .../{customers_add.njk => customers/add.njk} | 2 +- .../edit.njk} | 2 +- .../list.njk} | 0 .../faircalendar/events/_form.njk} | 2 +- .../events/add.njk} | 4 +- .../events/edit.njk} | 4 +- .../index.njk} | 0 server/src/templates/pages/home.njk | 6 +- .../projects/_form.njk} | 0 .../{projects_add.njk => projects/add.njk} | 2 +- .../{projects_edit.njk => projects/edit.njk} | 2 +- .../{projects_list.njk => projects/list.njk} | 0 server/src/templates/pages/tasks/_form.njk | 12 ++++ server/src/templates/pages/tasks/add.njk | 14 +++++ server/src/templates/pages/tasks/edit.njk | 19 ++++++ server/src/templates/pages/tasks/list.njk | 16 +++++ server/src/translations/fr-FR.ftl | 6 ++ 40 files changed, 289 insertions(+), 196 deletions(-) rename server/src/Infrastructure/FairCalendar/Controller/{UpdateEventController.ts => EditEventController.ts} (97%) delete mode 100644 server/src/Infrastructure/Task/Action/CreateTaskAction.ts delete mode 100644 server/src/Infrastructure/Task/Action/GetTaskAction.ts delete mode 100644 server/src/Infrastructure/Task/Action/GetTasksAction.ts delete mode 100644 server/src/Infrastructure/Task/Action/UpdateTaskAction.ts create mode 100644 server/src/Infrastructure/Task/Controller/AddTaskController.ts create mode 100644 server/src/Infrastructure/Task/Controller/EditTaskController.ts create mode 100644 server/src/Infrastructure/Task/Controller/ListTasksController.ts create mode 100644 server/src/Infrastructure/Task/Table/TaskTableFactory.ts rename server/src/templates/{macros/customer_form.njk => pages/customers/_form.njk} (100%) rename server/src/templates/pages/{customers_add.njk => customers/add.njk} (82%) rename server/src/templates/pages/{customers_edit.njk => customers/edit.njk} (90%) rename server/src/templates/pages/{customers_index.njk => customers/list.njk} (100%) rename server/src/templates/{macros/faircalendar_event_form.njk => pages/faircalendar/events/_form.njk} (95%) rename server/src/templates/pages/{faircalendar_events_add.njk => faircalendar/events/add.njk} (56%) rename server/src/templates/pages/{faircalendar_events_edit.njk => faircalendar/events/edit.njk} (78%) rename server/src/templates/pages/{faircalendar_index.njk => faircalendar/index.njk} (100%) rename server/src/templates/{macros/project_form.njk => pages/projects/_form.njk} (100%) rename server/src/templates/pages/{projects_add.njk => projects/add.njk} (83%) rename server/src/templates/pages/{projects_edit.njk => projects/edit.njk} (91%) rename server/src/templates/pages/{projects_list.njk => projects/list.njk} (100%) create mode 100644 server/src/templates/pages/tasks/_form.njk create mode 100644 server/src/templates/pages/tasks/add.njk create mode 100644 server/src/templates/pages/tasks/edit.njk create mode 100644 server/src/templates/pages/tasks/list.njk diff --git a/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts b/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts index e867f042..12d070e6 100644 --- a/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts +++ b/server/src/Infrastructure/Customer/Controller/AddCustomerController.ts @@ -28,13 +28,13 @@ export class AddCustomerController { @Get() @WithName('crm_customers_add') - @Render('pages/customers_add') + @Render('pages/customers/add.njk') public async get() { return {}; } @Post() - public async index(@Body() customerDto: CustomerDTO, @Res() res: Response) { + public async post(@Body() customerDto: CustomerDTO, @Res() res: Response) { const { street, city, zipCode, country, name } = customerDto; try { diff --git a/server/src/Infrastructure/Customer/Controller/EditCustomerController.ts b/server/src/Infrastructure/Customer/Controller/EditCustomerController.ts index 51bd307a..dd5fd125 100644 --- a/server/src/Infrastructure/Customer/Controller/EditCustomerController.ts +++ b/server/src/Infrastructure/Customer/Controller/EditCustomerController.ts @@ -34,7 +34,7 @@ export class EditCustomerController { @Get(':id') @WithName('crm_customers_edit') - @Render('pages/customers_edit') + @Render('pages/customers/edit.njk') public async get(@Param() idDto: IdDTO) { const customer = await this.queryBus.execute( new GetCustomerByIdQuery(idDto.id) diff --git a/server/src/Infrastructure/Customer/Controller/ListCustomersController.ts b/server/src/Infrastructure/Customer/Controller/ListCustomersController.ts index 19fa7d8f..2c3ba740 100644 --- a/server/src/Infrastructure/Customer/Controller/ListCustomersController.ts +++ b/server/src/Infrastructure/Customer/Controller/ListCustomersController.ts @@ -26,8 +26,8 @@ export class ListCustomersController { @Get() @WithName('crm_customers_list') - @Render('pages/customers_index.njk') - public async index(@Query() pagination: PaginationDTO) { + @Render('pages/customers/list.njk') + public async get(@Query() pagination: PaginationDTO) { const customers: Pagination = await this.queryBus.execute( new GetCustomersQuery(pagination.page) ); diff --git a/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts b/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts index 10b050c8..dcdede7e 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/AddEventController.ts @@ -37,7 +37,7 @@ export class AddEventController { @Get(':date') @WithName('faircalendar_events_add') - @Render('pages/faircalendar_events_add') + @Render('pages/faircalendar/events/add.njk') public async get(@Param() dto: AddEventControllerDTO) { const types = [ 'mission', diff --git a/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts b/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts index c0046766..3ce4bf44 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/DeleteEventController.ts @@ -26,7 +26,7 @@ export class DeleteEventController { @Post(':id') @WithName('faircalendar_event_delete') - public async index( + public async post( @Param() dto: IdDTO, @LoggedUser() user: User, @Res() res: Response diff --git a/server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts b/server/src/Infrastructure/FairCalendar/Controller/EditEventController.ts similarity index 97% rename from server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts rename to server/src/Infrastructure/FairCalendar/Controller/EditEventController.ts index a78b02bb..a5f17351 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/UpdateEventController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/EditEventController.ts @@ -33,7 +33,7 @@ import { GetEventByIdQuery } from 'src/Application/FairCalendar/Query/GetEventBy @Controller('app/faircalendar/events/edit') @UseGuards(IsAuthenticatedGuard) -export class UpdateEventController { +export class EditEventController { constructor( @Inject('ICommandBus') private readonly commandBus: ICommandBus, @@ -43,7 +43,7 @@ export class UpdateEventController { @Get(':id') @WithName('faircalendar_events_edit') - @Render('pages/faircalendar_events_edit') + @Render('pages/faircalendar/events/edit.njk') public async get(@Param() idDto: IdDTO) { const event = await this.queryBus.execute(new GetEventByIdQuery(idDto.id)); diff --git a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts index 215cb694..5cd5785f 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts @@ -31,7 +31,7 @@ export class FairCalendarController { @Get() @WithName('faircalendar_index') - @Render('pages/faircalendar_index') + @Render('pages/faircalendar/index.njk') public async get( @Query() dto: FairCalendarControllerDTO, @LoggedUser() user: User diff --git a/server/src/Infrastructure/FairCalendar/faircalendar.module.ts b/server/src/Infrastructure/FairCalendar/faircalendar.module.ts index 2275db88..cd8a3d13 100644 --- a/server/src/Infrastructure/FairCalendar/faircalendar.module.ts +++ b/server/src/Infrastructure/FairCalendar/faircalendar.module.ts @@ -24,7 +24,7 @@ import { Cooperative } from 'src/Domain/Settings/Cooperative.entity'; import { FluentTranslatorAdapter } from '../Adapter/FluentTranslatorAdapter'; import { FairCalendarController } from './Controller/FairCalendarController'; import { AddEventController } from './Controller/AddEventController'; -import { UpdateEventController } from './Controller/UpdateEventController'; +import { EditEventController } from './Controller/EditEventController'; import { DeleteEventController } from './Controller/DeleteEventController'; @Module({ @@ -36,7 +36,7 @@ import { DeleteEventController } from './Controller/DeleteEventController'; controllers: [ FairCalendarController, AddEventController, - UpdateEventController, + EditEventController, DeleteEventController ], providers: [ diff --git a/server/src/Infrastructure/Project/Controller/AddProjectController.ts b/server/src/Infrastructure/Project/Controller/AddProjectController.ts index eff742dc..873ca5a1 100644 --- a/server/src/Infrastructure/Project/Controller/AddProjectController.ts +++ b/server/src/Infrastructure/Project/Controller/AddProjectController.ts @@ -35,7 +35,7 @@ export class AddProjectController { @Get() @WithName('crm_projects_add') - @Render('pages/projects_add') + @Render('pages/projects/add.njk') public async get() { const customers: Pagination = await this.queryBus.execute( new GetCustomersQuery(1) @@ -47,7 +47,7 @@ export class AddProjectController { } @Post() - public async index(@Body() projectDto: ProjectDTO, @Res() res: Response) { + public async poqr(@Body() projectDto: ProjectDTO, @Res() res: Response) { const { name, customerId } = projectDto; try { diff --git a/server/src/Infrastructure/Project/Controller/EditProjectController.ts b/server/src/Infrastructure/Project/Controller/EditProjectController.ts index c70bd7d8..c5fe67bd 100644 --- a/server/src/Infrastructure/Project/Controller/EditProjectController.ts +++ b/server/src/Infrastructure/Project/Controller/EditProjectController.ts @@ -38,7 +38,7 @@ export class EditProjectController { @Get(':id') @WithName('crm_projects_edit') - @Render('pages/projects_edit') + @Render('pages/projects/edit.njk') public async get(@Param() idDto: IdDTO) { const project = await this.queryBus.execute( new GetProjectByIdQuery(idDto.id) diff --git a/server/src/Infrastructure/Project/Controller/ListProjectsController.ts b/server/src/Infrastructure/Project/Controller/ListProjectsController.ts index d9d21bca..3ef567f4 100644 --- a/server/src/Infrastructure/Project/Controller/ListProjectsController.ts +++ b/server/src/Infrastructure/Project/Controller/ListProjectsController.ts @@ -26,8 +26,8 @@ export class ListProjectsController { @Get() @WithName('crm_projects_list') - @Render('pages/projects_list.njk') - public async index(@Query() pagination: PaginationDTO) { + @Render('pages/projects/list.njk') + public async gzt(@Query() pagination: PaginationDTO) { const projects: Pagination = await this.queryBus.execute( new GetProjectsQuery(pagination.page) ); diff --git a/server/src/Infrastructure/Task/Action/CreateTaskAction.ts b/server/src/Infrastructure/Task/Action/CreateTaskAction.ts deleted file mode 100644 index 5f35b984..00000000 --- a/server/src/Infrastructure/Task/Action/CreateTaskAction.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { - Body, - Post, - Controller, - Inject, - BadRequestException, - UseGuards -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { CreateTaskCommand } from 'src/Application/Task/Command/CreateTaskCommand'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { TaskDTO } from '../DTO/TaskDTO'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; - -@Controller('tasks') -@ApiTags('Task') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class CreateTaskAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Post() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Create new task' }) - public async index(@Body() taskDto: TaskDTO) { - try { - const id = await this.commandBus.execute( - new CreateTaskCommand(taskDto.name) - ); - - return { id }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/Task/Action/GetTaskAction.ts b/server/src/Infrastructure/Task/Action/GetTaskAction.ts deleted file mode 100644 index 0c258cc9..00000000 --- a/server/src/Infrastructure/Task/Action/GetTaskAction.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - Controller, - Inject, - UseGuards, - Get, - Param, - NotFoundException -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { TaskView } from 'src/Application/Task/View/TaskView'; -import { GetTaskByIdQuery } from 'src/Application/Task/Query/GetTaskByIdQuery'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; - -@Controller('tasks') -@ApiTags('Task') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetTaskAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get task' }) - public async index(@Param() dto: IdDTO): Promise { - try { - return await this.queryBus.execute(new GetTaskByIdQuery(dto.id)); - } catch (e) { - throw new NotFoundException(e.message); - } - } -} diff --git a/server/src/Infrastructure/Task/Action/GetTasksAction.ts b/server/src/Infrastructure/Task/Action/GetTasksAction.ts deleted file mode 100644 index 7239ba4f..00000000 --- a/server/src/Infrastructure/Task/Action/GetTasksAction.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Controller, Inject, UseGuards, Get, Query } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { TaskView } from 'src/Application/Task/View/TaskView'; -import { GetTasksQuery } from 'src/Application/Task/Query/GetTasksQuery'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { PaginationDTO } from 'src/Infrastructure/Common/DTO/PaginationDTO'; -import { Pagination } from 'src/Application/Common/Pagination'; - -@Controller('tasks') -@ApiTags('Task') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetTasksAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get all tasks' }) - public async index( - @Query() pagination: PaginationDTO - ): Promise> { - return await this.queryBus.execute(new GetTasksQuery(pagination.page)); - } -} diff --git a/server/src/Infrastructure/Task/Action/UpdateTaskAction.ts b/server/src/Infrastructure/Task/Action/UpdateTaskAction.ts deleted file mode 100644 index 2c4068f3..00000000 --- a/server/src/Infrastructure/Task/Action/UpdateTaskAction.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { - Body, - Controller, - Inject, - BadRequestException, - UseGuards, - Put, - Param -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { UpdateTaskCommand } from 'src/Application/Task/Command/UpdateTaskCommand'; -import { TaskDTO } from '../DTO/TaskDTO'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; - -@Controller('tasks') -@ApiTags('Task') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class UpdateTaskAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Put(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Update task' }) - public async index(@Param() dto: IdDTO, @Body() taskDto: TaskDTO) { - try { - const { id } = dto; - await this.commandBus.execute(new UpdateTaskCommand(id, taskDto.name)); - - return { id }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/Task/Controller/AddTaskController.ts b/server/src/Infrastructure/Task/Controller/AddTaskController.ts new file mode 100644 index 00000000..eed979cc --- /dev/null +++ b/server/src/Infrastructure/Task/Controller/AddTaskController.ts @@ -0,0 +1,48 @@ +import { + BadRequestException, + Body, + Controller, + Get, + Inject, + Post, + Render, + Res, + UseGuards +} from '@nestjs/common'; +import { Response } from 'express'; +import { ICommandBus } from 'src/Application/ICommandBus'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; +import { CreateTaskCommand } from 'src/Application/Task/Command/CreateTaskCommand'; +import { TaskDTO } from '../DTO/TaskDTO'; +import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; + +@Controller('app/tasks/add') +@UseGuards(IsAuthenticatedGuard) +export class AddTaskController { + constructor( + @Inject('ICommandBus') + private readonly commandBus: ICommandBus, + private readonly resolver: RouteNameResolver + ) {} + + @Get() + @WithName('crm_tasks_add') + @Render('pages/tasks/add.njk') + public async get() { + return {}; + } + + @Post() + public async post(@Body() taskDto: TaskDTO, @Res() res: Response) { + const { name } = taskDto; + + try { + await this.commandBus.execute(new CreateTaskCommand(name)); + + res.redirect(303, this.resolver.resolve('crm_tasks_list')); + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/Task/Controller/EditTaskController.ts b/server/src/Infrastructure/Task/Controller/EditTaskController.ts new file mode 100644 index 00000000..a4eaa328 --- /dev/null +++ b/server/src/Infrastructure/Task/Controller/EditTaskController.ts @@ -0,0 +1,62 @@ +import { + BadRequestException, + Body, + Controller, + Get, + Inject, + Param, + Post, + Render, + Res, + UseGuards +} from '@nestjs/common'; +import { ICommandBus } from 'src/Application/ICommandBus'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { Response } from 'express'; +import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; +import { TaskDTO } from '../DTO/TaskDTO'; +import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; +import { GetTaskByIdQuery } from 'src/Application/Task/Query/GetTaskByIdQuery'; +import { UpdateTaskCommand } from 'src/Application/Task/Command/UpdateTaskCommand'; + +@Controller('app/tasks/edit') +@UseGuards(IsAuthenticatedGuard) +export class EditTaskController { + constructor( + @Inject('ICommandBus') + private readonly commandBus: ICommandBus, + @Inject('IQueryBus') + private readonly queryBus: IQueryBus, + private readonly resolver: RouteNameResolver + ) {} + + @Get(':id') + @WithName('crm_tasks_edit') + @Render('pages/tasks/edit.njk') + public async get(@Param() idDto: IdDTO) { + const task = await this.queryBus.execute(new GetTaskByIdQuery(idDto.id)); + + return { + task + }; + } + + @Post(':id') + public async post( + @Param() idDto: IdDTO, + @Body() dto: TaskDTO, + @Res() res: Response + ) { + const { name } = dto; + + try { + await this.commandBus.execute(new UpdateTaskCommand(idDto.id, name)); + + res.redirect(303, this.resolver.resolve('crm_tasks_list')); + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/Task/Controller/ListTasksController.ts b/server/src/Infrastructure/Task/Controller/ListTasksController.ts new file mode 100644 index 00000000..028acfb7 --- /dev/null +++ b/server/src/Infrastructure/Task/Controller/ListTasksController.ts @@ -0,0 +1,39 @@ +import { + Controller, + Inject, + UseGuards, + Get, + Query, + Render +} from '@nestjs/common'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { GetTasksQuery } from 'src/Application/Task/Query/GetTasksQuery'; +import { PaginationDTO } from 'src/Infrastructure/Common/DTO/PaginationDTO'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; +import { Pagination } from 'src/Application/Common/Pagination'; +import { TaskView } from 'src/Application/Task/View/TaskView'; +import { TaskTableFactory } from '../Table/TaskTableFactory'; + +@Controller('app/tasks') +@UseGuards(IsAuthenticatedGuard) +export class ListTasksController { + constructor( + @Inject('IQueryBus') + private readonly queryBus: IQueryBus, + private readonly tableFactory: TaskTableFactory + ) {} + + @Get() + @WithName('crm_tasks_list') + @Render('pages/tasks/list.njk') + public async get(@Query() pagination: PaginationDTO) { + const tasks: Pagination = await this.queryBus.execute( + new GetTasksQuery(pagination.page) + ); + + const table = this.tableFactory.create(tasks.items); + + return { table }; + } +} diff --git a/server/src/Infrastructure/Task/DTO/TaskDTO.ts b/server/src/Infrastructure/Task/DTO/TaskDTO.ts index bbf364c7..796e70f4 100644 --- a/server/src/Infrastructure/Task/DTO/TaskDTO.ts +++ b/server/src/Infrastructure/Task/DTO/TaskDTO.ts @@ -1,8 +1,6 @@ -import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty } from 'class-validator'; export class TaskDTO { - @ApiProperty() @IsNotEmpty() public name: string; } diff --git a/server/src/Infrastructure/Task/Table/TaskTableFactory.ts b/server/src/Infrastructure/Task/Table/TaskTableFactory.ts new file mode 100644 index 00000000..a37f3a66 --- /dev/null +++ b/server/src/Infrastructure/Task/Table/TaskTableFactory.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@nestjs/common'; +import { TaskView } from 'src/Application/Task/View/TaskView'; +import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; +import { Row, Table } from 'src/Infrastructure/Common/Table/Table'; + +@Injectable() +export class TaskTableFactory { + constructor(private readonly resolver: RouteNameResolver) {} + + public create(tasks: TaskView[]): Table { + const columns = ['crm-tasks-name', 'common-actions']; + + const rows = tasks.map( + (task): Row => [ + task.name, + { + actions: { + edit: { + url: this.resolver.resolve('crm_tasks_edit', { id: task.id }) + } + } + } + ] + ); + + return new Table(columns, rows); + } +} diff --git a/server/src/Infrastructure/Task/task.module.ts b/server/src/Infrastructure/Task/task.module.ts index f5809ab0..806c4e6a 100644 --- a/server/src/Infrastructure/Task/task.module.ts +++ b/server/src/Infrastructure/Task/task.module.ts @@ -4,30 +4,27 @@ import { BusModule } from '../bus.module'; import { TaskRepository } from '../Task/Repository/TaskRepository'; import { Task } from 'src/Domain/Task/Task.entity'; import { IsTaskAlreadyExist } from 'src/Domain/Task/Specification/IsTaskAlreadyExist'; -import { CreateTaskAction } from '../Task/Action/CreateTaskAction'; -import { GetTasksAction } from '../Task/Action/GetTasksAction'; -import { UpdateTaskAction } from '../Task/Action/UpdateTaskAction'; -import { GetTaskAction } from '../Task/Action/GetTaskAction'; import { CreateTaskCommandHandler } from 'src/Application/Task/Command/CreateTaskCommandHandler'; import { GetTasksQueryHandler } from 'src/Application/Task/Query/GetTasksQueryHandler'; import { UpdateTaskCommandHandler } from 'src/Application/Task/Command/UpdateTaskCommandHandler'; import { GetTaskByIdQueryHandler } from 'src/Application/Task/Query/GetTaskByIdQueryHandler'; +import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; +import { ListTasksController } from './Controller/ListTasksController'; +import { AddTaskController } from './Controller/AddTaskController'; +import { EditTaskController } from './Controller/EditTaskController'; +import { TaskTableFactory } from './Table/TaskTableFactory'; @Module({ - imports: [BusModule, TypeOrmModule.forFeature([Task])], - controllers: [ - GetTasksAction, - GetTaskAction, - CreateTaskAction, - UpdateTaskAction - ], + imports: [BusModule, TypeOrmModule.forFeature([Task]), ExtendedRoutingModule], + controllers: [ListTasksController, AddTaskController, EditTaskController], providers: [ { provide: 'ITaskRepository', useClass: TaskRepository }, CreateTaskCommandHandler, IsTaskAlreadyExist, GetTasksQueryHandler, UpdateTaskCommandHandler, - GetTaskByIdQueryHandler + GetTaskByIdQueryHandler, + TaskTableFactory ] }) export class TaskModule {} diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk index 86a8f3fe..e75a48eb 100644 --- a/server/src/templates/components/nav.njk +++ b/server/src/templates/components/nav.njk @@ -33,6 +33,11 @@ {{ "crm-projects-title"|trans|capitalize }} +
    • + + {{ "crm-tasks-title"|trans|capitalize }} + +
    • diff --git a/server/src/templates/macros/customer_form.njk b/server/src/templates/pages/customers/_form.njk similarity index 100% rename from server/src/templates/macros/customer_form.njk rename to server/src/templates/pages/customers/_form.njk diff --git a/server/src/templates/pages/customers_add.njk b/server/src/templates/pages/customers/add.njk similarity index 82% rename from server/src/templates/pages/customers_add.njk rename to server/src/templates/pages/customers/add.njk index 13773b49..07d39f3b 100644 --- a/server/src/templates/pages/customers_add.njk +++ b/server/src/templates/pages/customers/add.njk @@ -1,5 +1,5 @@ {% extends 'layouts/app.njk' %} -{% from 'macros/customer_form.njk' import customer_form %} +{% from './_form.njk' import customer_form %} {% block main_class %}pc-container{% endblock %} diff --git a/server/src/templates/pages/customers_edit.njk b/server/src/templates/pages/customers/edit.njk similarity index 90% rename from server/src/templates/pages/customers_edit.njk rename to server/src/templates/pages/customers/edit.njk index fc0cb8e0..a421abac 100644 --- a/server/src/templates/pages/customers_edit.njk +++ b/server/src/templates/pages/customers/edit.njk @@ -1,6 +1,6 @@ {% extends 'layouts/app.njk' %} -{% from 'macros/customer_form.njk' import customer_form %} {% from 'macros/breadcrumb.njk' import breadcrumb %} +{% from './_form.njk' import customer_form %} {% block main_class %}pc-container{% endblock %} diff --git a/server/src/templates/pages/customers_index.njk b/server/src/templates/pages/customers/list.njk similarity index 100% rename from server/src/templates/pages/customers_index.njk rename to server/src/templates/pages/customers/list.njk diff --git a/server/src/templates/macros/faircalendar_event_form.njk b/server/src/templates/pages/faircalendar/events/_form.njk similarity index 95% rename from server/src/templates/macros/faircalendar_event_form.njk rename to server/src/templates/pages/faircalendar/events/_form.njk index a0958add..5afb29b1 100644 --- a/server/src/templates/macros/faircalendar_event_form.njk +++ b/server/src/templates/pages/faircalendar/events/_form.njk @@ -1,4 +1,4 @@ -{% macro faircalendar_event_form(event, types, projects, tasks, times, date=null, class_name='') %} +{% macro event_form(event, types, projects, tasks, times, date=null, class_name='') %}
      diff --git a/server/src/templates/pages/faircalendar_events_add.njk b/server/src/templates/pages/faircalendar/events/add.njk similarity index 56% rename from server/src/templates/pages/faircalendar_events_add.njk rename to server/src/templates/pages/faircalendar/events/add.njk index 0bac29b5..a08b10b3 100644 --- a/server/src/templates/pages/faircalendar_events_add.njk +++ b/server/src/templates/pages/faircalendar/events/add.njk @@ -1,5 +1,5 @@ {% extends 'layouts/app.njk' %} -{% from 'macros/faircalendar_event_form.njk' import faircalendar_event_form %} +{% from './_form.njk' import event_form %} {% block main_class %}pc-container{% endblock %} @@ -9,6 +9,6 @@
      - {{ faircalendar_event_form(null, types, projects, tasks, times, date, class_name='pc-card__content') }} + {{ event_form(null, types, projects, tasks, times, date, class_name='pc-card__content') }}
      {% endblock main %} diff --git a/server/src/templates/pages/faircalendar_events_edit.njk b/server/src/templates/pages/faircalendar/events/edit.njk similarity index 78% rename from server/src/templates/pages/faircalendar_events_edit.njk rename to server/src/templates/pages/faircalendar/events/edit.njk index 629c7d4d..8fc97b09 100644 --- a/server/src/templates/pages/faircalendar_events_edit.njk +++ b/server/src/templates/pages/faircalendar/events/edit.njk @@ -1,5 +1,5 @@ {% extends 'layouts/app.njk' %} -{% from 'macros/faircalendar_event_form.njk' import faircalendar_event_form %} +{% from './_form.njk' import event_form %} {% block main_class %}pc-container{% endblock %} @@ -16,6 +16,6 @@
      - {{ faircalendar_event_form(event, types, projects, tasks, times, class_name='pc-card__content') }} + {{ event_form(event, types, projects, tasks, times, class_name='pc-card__content') }}
      {% endblock main %} diff --git a/server/src/templates/pages/faircalendar_index.njk b/server/src/templates/pages/faircalendar/index.njk similarity index 100% rename from server/src/templates/pages/faircalendar_index.njk rename to server/src/templates/pages/faircalendar/index.njk diff --git a/server/src/templates/pages/home.njk b/server/src/templates/pages/home.njk index f12f5503..9e9441c3 100644 --- a/server/src/templates/pages/home.njk +++ b/server/src/templates/pages/home.njk @@ -1,5 +1,9 @@ {% extends 'layouts/app.njk' %} +{% block main_class %}pc-container{% endblock %} + {% block main %} -

      Bonjour, {{ req.user.firstName|capitalize }} {{ req.user.lastName|capitalize }} !

      +

      + {{ 'home-title'|trans({ user: req.user.firstName|capitalize + ' ' + req.user.lastName|capitalize }) }} +

      {% endblock main %} diff --git a/server/src/templates/macros/project_form.njk b/server/src/templates/pages/projects/_form.njk similarity index 100% rename from server/src/templates/macros/project_form.njk rename to server/src/templates/pages/projects/_form.njk diff --git a/server/src/templates/pages/projects_add.njk b/server/src/templates/pages/projects/add.njk similarity index 83% rename from server/src/templates/pages/projects_add.njk rename to server/src/templates/pages/projects/add.njk index b666155b..74e29aa8 100644 --- a/server/src/templates/pages/projects_add.njk +++ b/server/src/templates/pages/projects/add.njk @@ -1,5 +1,5 @@ {% extends 'layouts/app.njk' %} -{% from 'macros/project_form.njk' import project_form %} +{% from './_form.njk' import project_form %} {% block main_class %}pc-container{% endblock %} diff --git a/server/src/templates/pages/projects_edit.njk b/server/src/templates/pages/projects/edit.njk similarity index 91% rename from server/src/templates/pages/projects_edit.njk rename to server/src/templates/pages/projects/edit.njk index 804dcc6e..e312fbda 100644 --- a/server/src/templates/pages/projects_edit.njk +++ b/server/src/templates/pages/projects/edit.njk @@ -1,6 +1,6 @@ {% extends 'layouts/app.njk' %} -{% from 'macros/project_form.njk' import project_form %} {% from 'macros/breadcrumb.njk' import breadcrumb %} +{% from './_form.njk' import project_form %} {% block main_class %}pc-container{% endblock %} diff --git a/server/src/templates/pages/projects_list.njk b/server/src/templates/pages/projects/list.njk similarity index 100% rename from server/src/templates/pages/projects_list.njk rename to server/src/templates/pages/projects/list.njk diff --git a/server/src/templates/pages/tasks/_form.njk b/server/src/templates/pages/tasks/_form.njk new file mode 100644 index 00000000..3c3657a8 --- /dev/null +++ b/server/src/templates/pages/tasks/_form.njk @@ -0,0 +1,12 @@ +{% macro task_form(task=null, class_name='') %} + +
      + + +
      + + + +{% endmacro %} diff --git a/server/src/templates/pages/tasks/add.njk b/server/src/templates/pages/tasks/add.njk new file mode 100644 index 00000000..50efb3d7 --- /dev/null +++ b/server/src/templates/pages/tasks/add.njk @@ -0,0 +1,14 @@ +{% extends 'layouts/app.njk' %} +{% from './_form.njk' import task_form %} + +{% block main_class %}pc-container{% endblock %} + +{% block main %} +

      + {{ 'crm-tasks-add-title'|trans }} +

      + +
      + {{ task_form(class_name='pc-card__content') }} +
      +{% endblock main %} diff --git a/server/src/templates/pages/tasks/edit.njk b/server/src/templates/pages/tasks/edit.njk new file mode 100644 index 00000000..ac741835 --- /dev/null +++ b/server/src/templates/pages/tasks/edit.njk @@ -0,0 +1,19 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} +{% from './_form.njk' import task_form %} + +{% block main_class %}pc-container{% endblock %} + +{% set title = 'crm-tasks-edit-title'|trans({name: task.name }) %} + +{% block main %} + {{ breadcrumb([{ title: 'crm-tasks-title'|trans, href: path('crm_tasks_list') }, { title: title }]) }} + +

      + {{ title }} +

      + +
      + {{ task_form(task, class_name='pc-card__content') }} +
      +{% endblock main %} diff --git a/server/src/templates/pages/tasks/list.njk b/server/src/templates/pages/tasks/list.njk new file mode 100644 index 00000000..6206bf80 --- /dev/null +++ b/server/src/templates/pages/tasks/list.njk @@ -0,0 +1,16 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/table.njk' import render_table with context %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} + +{% block main_class %}pc-container{% endblock %} + +{% block main %} + {{ breadcrumb([{ title: 'crm-tasks-title'|trans }]) }} + +
      +

      {{ 'crm-tasks-title'|trans }}

      + {{ 'common-add'|trans }} +
      + + {{ render_table(table) }} +{% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index ac8d7bea..0eebc8ba 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -6,6 +6,8 @@ common-actions = Actions site-title = Permacoop +home-title = Bonjour, {$user} ! + dashboard-title = Tableau de bord faircalendar-title = FairCalendar @@ -41,6 +43,10 @@ crm-projects-edit-title = Édition du projet "{$name}" crm-projects-name-title = Nom du projet crm-projects-customer-title = Client +crm-tasks-title = Missions +crm-tasks-name = Nom de la mission +crm-tasks-edit-title = Édition de la mission "{$name}" + accounts-title = FairRH accounts-workers-title = Coopérateurs - salariés From 9788c04f13c1c80042aa8ee2af11d6f6715ed8a6 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 18:26:08 +0200 Subject: [PATCH 18/49] Rework home and login routing --- .../Home/Controller/HomeController.ts | 17 +++++++++++++---- server/src/Infrastructure/Home/home.module.ts | 2 ++ .../User/Controller/LoginController.ts | 7 +++++-- .../HumanResource/humanResource.module.ts | 4 +++- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/server/src/Infrastructure/Home/Controller/HomeController.ts b/server/src/Infrastructure/Home/Controller/HomeController.ts index 62054e11..60a73402 100644 --- a/server/src/Infrastructure/Home/Controller/HomeController.ts +++ b/server/src/Infrastructure/Home/Controller/HomeController.ts @@ -1,14 +1,23 @@ -import { Controller, Get, Render, UseGuards } from '@nestjs/common'; +import { Controller, Get, Render, Res, UseGuards } from '@nestjs/common'; +import { Response } from 'express'; +import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; -@Controller('') +@Controller() @UseGuards(IsAuthenticatedGuard) export class HomeController { - @Get() + constructor(private readonly resolver: RouteNameResolver) {} + + @Get('app') @WithName('home') - @Render('pages/home') + @Render('pages/home.njk') public get() { return {}; } + + @Get() + public index(@Res() res: Response) { + res.redirect(303, this.resolver.resolve('home')); + } } diff --git a/server/src/Infrastructure/Home/home.module.ts b/server/src/Infrastructure/Home/home.module.ts index a5a73ffb..517266ad 100644 --- a/server/src/Infrastructure/Home/home.module.ts +++ b/server/src/Infrastructure/Home/home.module.ts @@ -1,7 +1,9 @@ import { Module } from '@nestjs/common'; import { HomeController } from './Controller/HomeController'; +import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; @Module({ + imports: [ExtendedRoutingModule], controllers: [HomeController] }) export class HomeModule {} diff --git a/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts b/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts index 53b1c8eb..18c36d1c 100644 --- a/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts +++ b/server/src/Infrastructure/HumanResource/User/Controller/LoginController.ts @@ -1,11 +1,14 @@ import { Controller, Get, Post, Render, Res, UseGuards } from '@nestjs/common'; import { Response } from 'express'; import { LocalAuthGuard } from '../Security/LocalAuthGuard'; +import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; @Controller('login') export class LoginController { + constructor(private readonly resolver: RouteNameResolver) {} + @Get() - @Render('pages/login') + @Render('pages/login.njk') public get() { return {}; } @@ -13,6 +16,6 @@ export class LoginController { @Post() @UseGuards(LocalAuthGuard) public async post(@Res() res: Response) { - res.redirect(303, '/'); + res.redirect(303, this.resolver.resolve('home')); } } diff --git a/server/src/Infrastructure/HumanResource/humanResource.module.ts b/server/src/Infrastructure/HumanResource/humanResource.module.ts index 1245f580..0c19eb69 100644 --- a/server/src/Infrastructure/HumanResource/humanResource.module.ts +++ b/server/src/Infrastructure/HumanResource/humanResource.module.ts @@ -82,6 +82,7 @@ import { GetPendingLeaveRequestsCountAction } from './Leave/Action/GetPendingLea import { GetPendingLeaveRequestsCountQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetPendingLeaveRequestsCountQueryHandler'; import session = require('express-session'); import { LogoutController } from './User/Controller/LogoutController'; +import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; @Module({ imports: [ @@ -101,7 +102,8 @@ import { LogoutController } from './User/Controller/LogoutController'; MealTicketRemoval, UserSavingsRecord, InterestRate - ]) + ]), + ExtendedRoutingModule ], controllers: [ LoginController, From f23e366b5376406bdba709d3531a3bd82a90b8ab Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 18:31:57 +0200 Subject: [PATCH 19/49] Remove File --- Makefile | 2 +- server/.env.dist | 2 - server/migrations/1695400222241-removeFile.ts | 12 +++ .../File/Command/UploadFileCommand.ts | 6 -- .../Command/UploadFileCommandHandler.spec.ts | 75 ------------- .../File/Command/UploadFileCommandHandler.ts | 32 ------ .../File/Query/DownloadFileQuery.ts | 5 - .../Query/DownloadFileQueryHandler.spec.ts | 101 ------------------ .../File/Query/DownloadFileQueryHandler.ts | 35 ------ .../File/View/DownloadedFileView.ts | 7 -- server/src/Application/File/View/FileView.ts | 7 -- server/src/Application/IFileEncryption.ts | 4 - server/src/Application/IFileStorage.ts | 7 -- .../File/Exception/FileNotFoundException.ts | 5 - server/src/Domain/File/File.entity.spec.ts | 18 ---- server/src/Domain/File/File.entity.ts | 52 --------- server/src/Domain/File/IUploadedFile.ts | 6 -- .../Domain/File/Repository/IFileRepository.ts | 7 -- .../Strategy/FileDirectoryStrategy.spec.ts | 17 --- .../File/Strategy/FileDirectoryStrategy.ts | 15 --- .../Strategy/FileDirectorytrategy.spec.ts | 17 --- .../File/Validator/PDFValidator.spec.ts | 27 ----- .../src/Domain/File/Validator/PDFValidator.ts | 7 -- .../Adapter/FileEncryptionAdapter.ts | 35 ------ .../Adapter/LocalFileStorageAdapter.ts | 64 ----------- .../File/Repository/FileRepository.ts | 27 ----- server/src/Infrastructure/File/file.module.ts | 28 ----- .../HumanResource/humanResource.module.ts | 5 - server/src/app.module.ts | 2 - 29 files changed, 13 insertions(+), 614 deletions(-) create mode 100644 server/migrations/1695400222241-removeFile.ts delete mode 100644 server/src/Application/File/Command/UploadFileCommand.ts delete mode 100644 server/src/Application/File/Command/UploadFileCommandHandler.spec.ts delete mode 100644 server/src/Application/File/Command/UploadFileCommandHandler.ts delete mode 100644 server/src/Application/File/Query/DownloadFileQuery.ts delete mode 100644 server/src/Application/File/Query/DownloadFileQueryHandler.spec.ts delete mode 100644 server/src/Application/File/Query/DownloadFileQueryHandler.ts delete mode 100644 server/src/Application/File/View/DownloadedFileView.ts delete mode 100644 server/src/Application/File/View/FileView.ts delete mode 100644 server/src/Application/IFileEncryption.ts delete mode 100644 server/src/Application/IFileStorage.ts delete mode 100644 server/src/Domain/File/Exception/FileNotFoundException.ts delete mode 100644 server/src/Domain/File/File.entity.spec.ts delete mode 100644 server/src/Domain/File/File.entity.ts delete mode 100644 server/src/Domain/File/IUploadedFile.ts delete mode 100644 server/src/Domain/File/Repository/IFileRepository.ts delete mode 100644 server/src/Domain/File/Strategy/FileDirectoryStrategy.spec.ts delete mode 100644 server/src/Domain/File/Strategy/FileDirectoryStrategy.ts delete mode 100644 server/src/Domain/File/Strategy/FileDirectorytrategy.spec.ts delete mode 100644 server/src/Domain/File/Validator/PDFValidator.spec.ts delete mode 100644 server/src/Domain/File/Validator/PDFValidator.ts delete mode 100644 server/src/Infrastructure/Adapter/FileEncryptionAdapter.ts delete mode 100644 server/src/Infrastructure/Adapter/LocalFileStorageAdapter.ts delete mode 100644 server/src/Infrastructure/File/Repository/FileRepository.ts delete mode 100644 server/src/Infrastructure/File/file.module.ts diff --git a/Makefile b/Makefile index 94bdc821..077d1861 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,7 @@ database-test-init: ## Initialize test database DATABASE_NAME=permacoop_test make database-migrate database-migration: ## Generate a database migration - cd server && npm run migration:generate -- migrations/$(NAME) + cd server && npm run migration:create -- migrations/$(NAME) database-seed: ## Seed database cd server && npm run build && npm run seed:run diff --git a/server/.env.dist b/server/.env.dist index 355bc52e..967bf46d 100644 --- a/server/.env.dist +++ b/server/.env.dist @@ -6,8 +6,6 @@ DATABASE_NAME=permacoop ACCOUNTING_PAD=4 ACCOUNTING_INVOICE_PREFIX='FS' -UPLOAD_LOCATION='uploads' -FILE_ENCRYPTION_KEY='my_secret_key' CALENDAR_TOKEN='abcd1234' FLUENT_PATH=src/translations/fr-FR.ftl diff --git a/server/migrations/1695400222241-removeFile.ts b/server/migrations/1695400222241-removeFile.ts new file mode 100644 index 00000000..713a73a9 --- /dev/null +++ b/server/migrations/1695400222241-removeFile.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm" + +export class RemoveFile1695400222241 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "file"`); + } + + public async down(queryRunner: QueryRunner): Promise { + // noop + } +} diff --git a/server/src/Application/File/Command/UploadFileCommand.ts b/server/src/Application/File/Command/UploadFileCommand.ts deleted file mode 100644 index 6e013fd4..00000000 --- a/server/src/Application/File/Command/UploadFileCommand.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IUploadedFile } from 'src/Domain/File/IUploadedFile'; -import { ICommand } from 'src/Application/ICommand'; - -export class UploadFileCommand implements ICommand { - constructor(public readonly uploadedFile: IUploadedFile) {} -} diff --git a/server/src/Application/File/Command/UploadFileCommandHandler.spec.ts b/server/src/Application/File/Command/UploadFileCommandHandler.spec.ts deleted file mode 100644 index 2575f144..00000000 --- a/server/src/Application/File/Command/UploadFileCommandHandler.spec.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { mock, instance, when, verify, deepEqual, anything } from 'ts-mockito'; -import { FileRepository } from 'src/Infrastructure/File/Repository/FileRepository'; -import { UploadFileCommandHandler } from './UploadFileCommandHandler'; -import { LocalFileStorageAdapter } from 'src/Infrastructure/Adapter/LocalFileStorageAdapter'; -import { IUploadedFile } from 'src/Domain/File/IUploadedFile'; -import { UploadFileCommand } from './UploadFileCommand'; -import { File } from 'src/Domain/File/File.entity'; -import { FileNotFoundException } from 'src/Domain/File/Exception/FileNotFoundException'; - -describe('UpdateFileCommandHandler', () => { - let handler: UploadFileCommandHandler; - let localFileStorageAdapter: LocalFileStorageAdapter; - let fileRepository: FileRepository; - - beforeEach(() => { - localFileStorageAdapter = mock(LocalFileStorageAdapter); - fileRepository = mock(FileRepository); - - handler = new UploadFileCommandHandler( - instance(localFileStorageAdapter), - instance(fileRepository) - ); - }); - - it('testUploadFile', async () => { - const uploadedFile: IUploadedFile = { - originalname: 'file.pdf', - mimetype: 'application/pdf', - buffer: instance(mock(Buffer)), - size: 120 - }; - const file = mock(File); - when(file.getId()).thenReturn('cfdd06eb-cd71-44b9-82c6-46110b30ce05'); - - when(localFileStorageAdapter.upload(uploadedFile)).thenResolve( - 'prefix_file.pdf' - ); - when( - fileRepository.save( - deepEqual(new File('prefix_file.pdf', 120, 'application/pdf')) - ) - ).thenResolve(instance(file)); - - expect(await handler.execute(new UploadFileCommand(uploadedFile))).toBe( - 'cfdd06eb-cd71-44b9-82c6-46110b30ce05' - ); - - verify(localFileStorageAdapter.upload(uploadedFile)).once(); - verify( - fileRepository.save( - deepEqual(new File('prefix_file.pdf', 120, 'application/pdf')) - ) - ).once(); - verify(file.getId()).once(); - }); - - it('testFileNotFound', async () => { - const uploadedFile: IUploadedFile = { - originalname: 'file.pdf', - mimetype: 'application/pdf', - buffer: instance(mock(Buffer)), - size: 120 - }; - when(localFileStorageAdapter.upload(uploadedFile)).thenResolve(null); - - try { - await handler.execute(new UploadFileCommand(uploadedFile)); - } catch (e) { - expect(e).toBeInstanceOf(FileNotFoundException); - expect(e.message).toBe('common.errors.file_not_found'); - verify(localFileStorageAdapter.upload(uploadedFile)).once(); - verify(fileRepository.save(anything())).never(); - } - }); -}); diff --git a/server/src/Application/File/Command/UploadFileCommandHandler.ts b/server/src/Application/File/Command/UploadFileCommandHandler.ts deleted file mode 100644 index c3e9d7f4..00000000 --- a/server/src/Application/File/Command/UploadFileCommandHandler.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { CommandHandler } from '@nestjs/cqrs'; -import { Inject } from '@nestjs/common'; -import { UploadFileCommand } from './UploadFileCommand'; -import { IFileStorage } from 'src/Application/IFileStorage'; -import { IFileRepository } from 'src/Domain/File/Repository/IFileRepository'; -import { File } from 'src/Domain/File/File.entity'; -import { FileNotFoundException } from 'src/Domain/File/Exception/FileNotFoundException'; - -@CommandHandler(UploadFileCommand) -export class UploadFileCommandHandler { - constructor( - @Inject('IFileStorage') - public readonly fileStorage: IFileStorage, - @Inject('IFileRepository') - public readonly fileRepository: IFileRepository - ) {} - - public async execute(command: UploadFileCommand): Promise { - const { uploadedFile } = command; - - const fileName = await this.fileStorage.upload(uploadedFile); - if (!fileName) { - throw new FileNotFoundException(); - } - - const file = await this.fileRepository.save( - new File(fileName, uploadedFile.size, uploadedFile.mimetype) - ); - - return file.getId(); - } -} diff --git a/server/src/Application/File/Query/DownloadFileQuery.ts b/server/src/Application/File/Query/DownloadFileQuery.ts deleted file mode 100644 index 52da18ef..00000000 --- a/server/src/Application/File/Query/DownloadFileQuery.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IQuery } from 'src/Application/IQuery'; - -export class DownloadFileQuery implements IQuery { - constructor(public readonly id: string) {} -} diff --git a/server/src/Application/File/Query/DownloadFileQueryHandler.spec.ts b/server/src/Application/File/Query/DownloadFileQueryHandler.spec.ts deleted file mode 100644 index 81060170..00000000 --- a/server/src/Application/File/Query/DownloadFileQueryHandler.spec.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { mock, instance, when, verify, anything } from 'ts-mockito'; -import { FileRepository } from 'src/Infrastructure/File/Repository/FileRepository'; -import { LocalFileStorageAdapter } from 'src/Infrastructure/Adapter/LocalFileStorageAdapter'; -import { File } from 'src/Domain/File/File.entity'; -import { DownloadFileQueryHandler } from './DownloadFileQueryHandler'; -import { DownloadFileQuery } from './DownloadFileQuery'; -import { DownloadedFileView } from '../View/DownloadedFileView'; -import { FileNotFoundException } from 'src/Domain/File/Exception/FileNotFoundException'; - -describe('DownloadFileQueryHandler', () => { - let handler: DownloadFileQueryHandler; - let localFileStorageAdapter: LocalFileStorageAdapter; - let fileRepository: FileRepository; - - beforeEach(() => { - localFileStorageAdapter = mock(LocalFileStorageAdapter); - fileRepository = mock(FileRepository); - - handler = new DownloadFileQueryHandler( - instance(fileRepository), - instance(localFileStorageAdapter) - ); - }); - - it('testDownloadFile', async () => { - const buffer = mock(Buffer); - const file = mock(File); - when(file.getOriginalName()).thenReturn('file_mathieu_marchois.pdf'); - when(file.getMimeType()).thenReturn('application/pdf'); - - when( - fileRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') - ).thenResolve(instance(file)); - when(localFileStorageAdapter.download(instance(file))).thenResolve( - instance(buffer) - ); - expect( - await handler.execute( - new DownloadFileQuery('cfdd06eb-cd71-44b9-82c6-46110b30ce05') - ) - ).toMatchObject( - new DownloadedFileView( - 'file_mathieu_marchois.pdf', - 'application/pdf', - instance(buffer) - ) - ); - - verify( - fileRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') - ).once(); - verify(localFileStorageAdapter.download(instance(file))).once(); - verify(file.getOriginalName()).once(); - verify(file.getMimeType()).once(); - }); - - it('testBufferNullable', async () => { - const file = mock(File); - when(file.getOriginalName()).thenReturn('file_mathieu_marchois.pdf'); - when(file.getMimeType()).thenReturn('application/pdf'); - - when( - fileRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') - ).thenResolve(instance(file)); - when(localFileStorageAdapter.download(instance(file))).thenResolve(null); - - try { - await handler.execute( - new DownloadFileQuery('cfdd06eb-cd71-44b9-82c6-46110b30ce05') - ); - } catch (e) { - expect(e).toBeInstanceOf(FileNotFoundException); - expect(e.message).toBe('common.errors.file_not_found'); - verify( - fileRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') - ).once(); - verify(file.getOriginalName()).never(); - verify(file.getMimeType()).never(); - verify(localFileStorageAdapter.download(instance(file))).once(); - } - }); - - it('testFileNotFound', async () => { - when( - fileRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') - ).thenResolve(null); - - try { - await handler.execute( - new DownloadFileQuery('cfdd06eb-cd71-44b9-82c6-46110b30ce05') - ); - } catch (e) { - expect(e).toBeInstanceOf(FileNotFoundException); - expect(e.message).toBe('common.errors.file_not_found'); - verify( - fileRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') - ).once(); - verify(localFileStorageAdapter.download(anything())).never(); - } - }); -}); diff --git a/server/src/Application/File/Query/DownloadFileQueryHandler.ts b/server/src/Application/File/Query/DownloadFileQueryHandler.ts deleted file mode 100644 index 99a6074f..00000000 --- a/server/src/Application/File/Query/DownloadFileQueryHandler.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Inject } from '@nestjs/common'; -import { QueryHandler } from '@nestjs/cqrs'; -import { IFileRepository } from 'src/Domain/File/Repository/IFileRepository'; -import { DownloadFileQuery } from './DownloadFileQuery'; -import { IFileStorage } from 'src/Application/IFileStorage'; -import { DownloadedFileView } from '../View/DownloadedFileView'; -import { FileNotFoundException } from 'src/Domain/File/Exception/FileNotFoundException'; - -@QueryHandler(DownloadFileQuery) -export class DownloadFileQueryHandler { - constructor( - @Inject('IFileRepository') - private readonly fileRepository: IFileRepository, - @Inject('IFileStorage') - public readonly fileStorage: IFileStorage - ) {} - - public async execute(query: DownloadFileQuery): Promise { - const file = await this.fileRepository.findOneById(query.id); - if (!file) { - throw new FileNotFoundException(); - } - - const buffer = await this.fileStorage.download(file); - if (!buffer) { - throw new FileNotFoundException(); - } - - return new DownloadedFileView( - file.getOriginalName(), - file.getMimeType(), - buffer - ); - } -} diff --git a/server/src/Application/File/View/DownloadedFileView.ts b/server/src/Application/File/View/DownloadedFileView.ts deleted file mode 100644 index c5d5f950..00000000 --- a/server/src/Application/File/View/DownloadedFileView.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class DownloadedFileView { - constructor( - public readonly originalName: string, - public readonly mimeType: string, - public readonly buffer: Buffer - ) {} -} diff --git a/server/src/Application/File/View/FileView.ts b/server/src/Application/File/View/FileView.ts deleted file mode 100644 index 73e0fdcf..00000000 --- a/server/src/Application/File/View/FileView.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class FileView { - constructor( - public readonly id: string, - public readonly originalName: string, - public readonly size: number - ) {} -} diff --git a/server/src/Application/IFileEncryption.ts b/server/src/Application/IFileEncryption.ts deleted file mode 100644 index 919fdc80..00000000 --- a/server/src/Application/IFileEncryption.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface IFileEncryption { - encrypt(buffer: Buffer): Promise; - decrypt(buffer: Buffer): Promise; -} diff --git a/server/src/Application/IFileStorage.ts b/server/src/Application/IFileStorage.ts deleted file mode 100644 index 558b7052..00000000 --- a/server/src/Application/IFileStorage.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IUploadedFile } from '../Domain/File/IUploadedFile'; -import { File } from 'src/Domain/File/File.entity'; - -export interface IFileStorage { - upload(file: IUploadedFile): Promise; - download(file: File): Promise; -} diff --git a/server/src/Domain/File/Exception/FileNotFoundException.ts b/server/src/Domain/File/Exception/FileNotFoundException.ts deleted file mode 100644 index 67da2b3e..00000000 --- a/server/src/Domain/File/Exception/FileNotFoundException.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class FileNotFoundException extends Error { - constructor() { - super('common.errors.file_not_found'); - } -} diff --git a/server/src/Domain/File/File.entity.spec.ts b/server/src/Domain/File/File.entity.spec.ts deleted file mode 100644 index 27221512..00000000 --- a/server/src/Domain/File/File.entity.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { File } from './File.entity'; - -describe('File.entity', () => { - it('testGetters', () => { - const file = new File( - 'xbn7s_file_mathieu_marchois.pdf', - 600, - 'application/pdf' - ); - - expect(file.getId()).toBe(undefined); - expect(file.getMimeType()).toBe('application/pdf'); - expect(file.getName()).toBe('xbn7s_file_mathieu_marchois.pdf'); - expect(file.getOriginalName()).toBe('file_mathieu_marchois.pdf'); - expect(file.getSize()).toBe(600); - expect(file.getUploadedAt()).toBe(undefined); - }); -}); diff --git a/server/src/Domain/File/File.entity.ts b/server/src/Domain/File/File.entity.ts deleted file mode 100644 index 6599023e..00000000 --- a/server/src/Domain/File/File.entity.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; - -@Entity() -export class File { - @PrimaryGeneratedColumn('uuid') - private id: string; - - @Column({ type: 'varchar', nullable: false }) - private name: string; - - @Column({ type: 'integer', nullable: false }) - private size: number; - - @Column({ type: 'varchar', nullable: false }) - private mimeType: string; - - @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) - private uploadedAt: Date; - - constructor(name: string, size: number, mimeType: string) { - this.name = name; - this.size = size; - this.mimeType = mimeType; - } - - public getId(): string { - return this.id; - } - - public getName(): string { - return this.name; - } - - public getSize(): number { - return this.size; - } - - public getMimeType(): string { - return this.mimeType; - } - - public getUploadedAt(): Date { - return this.uploadedAt; - } - - public getOriginalName(): string { - return this.name - .split('_') - .splice(1) - .join('_'); - } -} diff --git a/server/src/Domain/File/IUploadedFile.ts b/server/src/Domain/File/IUploadedFile.ts deleted file mode 100644 index 32cffda3..00000000 --- a/server/src/Domain/File/IUploadedFile.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface IUploadedFile { - originalname: string; - mimetype: string; - buffer: Buffer; - size: number; -} diff --git a/server/src/Domain/File/Repository/IFileRepository.ts b/server/src/Domain/File/Repository/IFileRepository.ts deleted file mode 100644 index ac61d5c3..00000000 --- a/server/src/Domain/File/Repository/IFileRepository.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { File } from '../File.entity'; - -export interface IFileRepository { - save(file: File): Promise; - remove(file: File): void; - findOneById(id: string): Promise; -} diff --git a/server/src/Domain/File/Strategy/FileDirectoryStrategy.spec.ts b/server/src/Domain/File/Strategy/FileDirectoryStrategy.spec.ts deleted file mode 100644 index b5ba3aa8..00000000 --- a/server/src/Domain/File/Strategy/FileDirectoryStrategy.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ConfigService } from '@nestjs/config'; -import { mock, instance, when } from 'ts-mockito'; -import { FileDirectoryStrategy } from './FileDirectoryStrategy'; - -describe('FileDirectoryStrategy', () => { - it('testFileLocation', async () => { - const configService: ConfigService = mock(ConfigService); - const strategy: FileDirectoryStrategy = new FileDirectoryStrategy( - instance(configService) - ); - - when(configService.get('UPLOAD_LOCATION')).thenReturn('uploads'); - expect(await strategy.location(new Date('2020-04-29'))).toBe( - 'uploads/2020/4' - ); - }); -}); diff --git a/server/src/Domain/File/Strategy/FileDirectoryStrategy.ts b/server/src/Domain/File/Strategy/FileDirectoryStrategy.ts deleted file mode 100644 index 7c9bc591..00000000 --- a/server/src/Domain/File/Strategy/FileDirectoryStrategy.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ConfigService } from '@nestjs/config'; -import { Injectable } from '@nestjs/common'; - -@Injectable() -export class FileDirectoryStrategy { - constructor(private readonly configService: ConfigService) {} - - public async location(uploadedDate: Date): Promise { - const destination = await this.configService.get('UPLOAD_LOCATION'); - const month = uploadedDate.getMonth() + 1; - const year = uploadedDate.getFullYear(); - - return `${destination}/${year}/${month}`; - } -} diff --git a/server/src/Domain/File/Strategy/FileDirectorytrategy.spec.ts b/server/src/Domain/File/Strategy/FileDirectorytrategy.spec.ts deleted file mode 100644 index b5ba3aa8..00000000 --- a/server/src/Domain/File/Strategy/FileDirectorytrategy.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ConfigService } from '@nestjs/config'; -import { mock, instance, when } from 'ts-mockito'; -import { FileDirectoryStrategy } from './FileDirectoryStrategy'; - -describe('FileDirectoryStrategy', () => { - it('testFileLocation', async () => { - const configService: ConfigService = mock(ConfigService); - const strategy: FileDirectoryStrategy = new FileDirectoryStrategy( - instance(configService) - ); - - when(configService.get('UPLOAD_LOCATION')).thenReturn('uploads'); - expect(await strategy.location(new Date('2020-04-29'))).toBe( - 'uploads/2020/4' - ); - }); -}); diff --git a/server/src/Domain/File/Validator/PDFValidator.spec.ts b/server/src/Domain/File/Validator/PDFValidator.spec.ts deleted file mode 100644 index 2f87dcd5..00000000 --- a/server/src/Domain/File/Validator/PDFValidator.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { mock, instance } from 'ts-mockito'; -import { PDFValidator } from './PDFValidator'; -import { IUploadedFile } from 'src/Domain/File/IUploadedFile'; - -describe('PDFValidator', () => { - it('testPdfFile', async () => { - const file: IUploadedFile = { - originalname: 'file.pdf', - mimetype: 'application/pdf', - buffer: instance(mock(Buffer)), - size: 120 - }; - - expect(PDFValidator.isValid(file)).toBeTruthy(); - }); - - it('testNotPdfFile', async () => { - const file: IUploadedFile = { - originalname: 'file.jpg', - mimetype: 'application/jpg', - buffer: instance(mock(Buffer)), - size: 120 - }; - - expect(PDFValidator.isValid(file)).toBeFalsy(); - }); -}); diff --git a/server/src/Domain/File/Validator/PDFValidator.ts b/server/src/Domain/File/Validator/PDFValidator.ts deleted file mode 100644 index 1e4bfd35..00000000 --- a/server/src/Domain/File/Validator/PDFValidator.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IUploadedFile } from 'src/Domain/File/IUploadedFile'; - -export class PDFValidator { - public static isValid(file: IUploadedFile): boolean { - return 'application/pdf' === file.mimetype; - } -} diff --git a/server/src/Infrastructure/Adapter/FileEncryptionAdapter.ts b/server/src/Infrastructure/Adapter/FileEncryptionAdapter.ts deleted file mode 100644 index 6e102070..00000000 --- a/server/src/Infrastructure/Adapter/FileEncryptionAdapter.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as crypto from 'crypto'; -import { Injectable } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { IFileEncryption } from 'src/Application/IFileEncryption'; - -@Injectable() -export class FileEncryptionAdapter implements IFileEncryption { - constructor(private readonly configService: ConfigService) {} - - public async encrypt(buffer: Buffer): Promise { - const iv = crypto.randomBytes(16); - const key = await this.getEncryptionKey(); - const cipher = crypto.createCipheriv('aes-256-ctr', key, iv); - - return Buffer.concat([iv, cipher.update(buffer), cipher.final()]); - } - - public async decrypt(buffer: Buffer): Promise { - const key = await this.getEncryptionKey(); - const iv = buffer.slice(0, 16); - const decipher = crypto.createDecipheriv('aes-256-ctr', key, iv); - - return Buffer.concat([decipher.update(buffer.slice(16)), decipher.final()]); - } - - private async getEncryptionKey(): Promise { - const key = await this.configService.get('FILE_ENCRYPTION_KEY'); - - return crypto - .createHash('sha256') - .update(key) - .digest('base64') - .substr(0, 32); - } -} diff --git a/server/src/Infrastructure/Adapter/LocalFileStorageAdapter.ts b/server/src/Infrastructure/Adapter/LocalFileStorageAdapter.ts deleted file mode 100644 index 375ba38f..00000000 --- a/server/src/Infrastructure/Adapter/LocalFileStorageAdapter.ts +++ /dev/null @@ -1,64 +0,0 @@ -import * as fs from 'fs'; -import * as shortid from 'shortid'; -import { Injectable, Inject } from '@nestjs/common'; -import { IFileStorage } from 'src/Application/IFileStorage'; -import { IUploadedFile } from 'src/Domain/File/IUploadedFile'; -import { FileDirectoryStrategy } from 'src/Domain/File/Strategy/FileDirectoryStrategy'; -import { IDateUtils } from 'src/Application/IDateUtils'; -import { IFileEncryption } from 'src/Application/IFileEncryption'; -import { File } from 'src/Domain/File/File.entity'; - -@Injectable() -export class LocalFileStorageAdapter implements IFileStorage { - constructor( - @Inject('IDateUtils') - private readonly dateUtils: IDateUtils, - @Inject('IFileEncryption') - private readonly fileEncryptionAdapter: IFileEncryption, - private readonly fileDirectoryStrategy: FileDirectoryStrategy - ) {} - - public async upload(file: IUploadedFile): Promise { - const fileName = `${this.getShortId()}_${file.originalname}`; - const date = this.dateUtils.getCurrentDate(); - const dir = await this.fileDirectoryStrategy.location(date); - const directory = `${__dirname}/../../../../${dir}`; - - try { - if (!fs.existsSync(directory)) { - fs.mkdirSync(directory, { recursive: true }); - } - - const encryptedBuffer = await this.fileEncryptionAdapter.encrypt( - file.buffer - ); - - fs.writeFileSync(`${directory}/${fileName}`, encryptedBuffer); - - return fileName; - } catch (e) { - return null; - } - } - - public async download(file: File): Promise { - const dir = await this.fileDirectoryStrategy.location(file.getUploadedAt()); - const directory = `${__dirname}/../../../../${dir}`; - - try { - const buffer = fs.readFileSync(`${directory}/${file.getName()}`); - - return await this.fileEncryptionAdapter.decrypt(buffer); - } catch (e) { - return null; - } - } - - private getShortId(): string { - shortid.characters( - '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$@' - ); - - return shortid(); - } -} diff --git a/server/src/Infrastructure/File/Repository/FileRepository.ts b/server/src/Infrastructure/File/Repository/FileRepository.ts deleted file mode 100644 index fa1361fe..00000000 --- a/server/src/Infrastructure/File/Repository/FileRepository.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { IFileRepository } from 'src/Domain/File/Repository/IFileRepository'; -import { File } from 'src/Domain/File/File.entity'; - -export class FileRepository implements IFileRepository { - constructor( - @InjectRepository(File) - private readonly repository: Repository - ) {} - - public save(file: File): Promise { - return this.repository.save(file); - } - - public remove(file: File): void { - this.repository.delete(file.getId()); - } - - public findOneById(id: string): Promise { - return this.repository - .createQueryBuilder('file') - .select(['file.id', 'file.name', 'file.mimeType', 'file.uploadedAt']) - .where('file.id = :id', { id }) - .getOne(); - } -} diff --git a/server/src/Infrastructure/File/file.module.ts b/server/src/Infrastructure/File/file.module.ts deleted file mode 100644 index a4690379..00000000 --- a/server/src/Infrastructure/File/file.module.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { BusModule } from '../bus.module'; -import { File } from 'src/Domain/File/File.entity'; -import { FileRepository } from './Repository/FileRepository'; -import { LocalFileStorageAdapter } from '../Adapter/LocalFileStorageAdapter'; -import { UploadFileCommandHandler } from 'src/Application/File/Command/UploadFileCommandHandler'; -import { DateUtilsAdapter } from '../Adapter/DateUtilsAdapter'; -import { FileDirectoryStrategy } from 'src/Domain/File/Strategy/FileDirectoryStrategy'; -import { FileEncryptionAdapter } from '../Adapter/FileEncryptionAdapter'; -import { DownloadFileQueryHandler } from 'src/Application/File/Query/DownloadFileQueryHandler'; - -@Module({ - imports: [BusModule, ConfigModule, TypeOrmModule.forFeature([File])], - controllers: [], - providers: [ - { provide: 'IFileRepository', useClass: FileRepository }, - { provide: 'IFileStorage', useClass: LocalFileStorageAdapter }, - { provide: 'IDateUtils', useClass: DateUtilsAdapter }, - { provide: 'IFileEncryption', useClass: FileEncryptionAdapter }, - Date, - UploadFileCommandHandler, - FileDirectoryStrategy, - DownloadFileQueryHandler - ] -}) -export class FileModule {} diff --git a/server/src/Infrastructure/HumanResource/humanResource.module.ts b/server/src/Infrastructure/HumanResource/humanResource.module.ts index 0c19eb69..915855f7 100644 --- a/server/src/Infrastructure/HumanResource/humanResource.module.ts +++ b/server/src/Infrastructure/HumanResource/humanResource.module.ts @@ -4,7 +4,6 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { PassportModule } from '@nestjs/passport'; import { BusModule } from '../bus.module'; import { User } from 'src/Domain/HumanResource/User/User.entity'; -import { File } from 'src/Domain/File/File.entity'; import { LoginController } from './User/Controller/LoginController'; import { LoginAction } from './User/Action/LoginAction'; import { CreateUserAction } from './User/Action/CreateUserAction'; @@ -14,7 +13,6 @@ import { GetUsersAction } from './User/Action/GetUsersAction'; import { UserRepository } from './User/Repository/UserRepository'; import { PasswordEncoderAdapter } from '../Adapter/PasswordEncoderAdapter'; import { DateUtilsAdapter } from '../Adapter/DateUtilsAdapter'; -import { FileRepository } from '../File/Repository/FileRepository'; import { LoginQueryHandler } from 'src/Application/HumanResource/User/Query/LoginQueryHandler'; import { CreateUserCommandHandler } from 'src/Application/HumanResource/User/Command/CreateUserCommandHandler'; import { GetUsersQueryHandler } from 'src/Application/HumanResource/User/Query/GetUsersQueryHandler'; @@ -80,7 +78,6 @@ import { GetLeavesCalendarAction } from './Leave/Action/GetLeavesCalendarAction' import { GetLeavesCalendarQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetLeavesCalendarQueryHandler'; import { GetPendingLeaveRequestsCountAction } from './Leave/Action/GetPendingLeaveRequestsCountAction'; import { GetPendingLeaveRequestsCountQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetPendingLeaveRequestsCountQueryHandler'; -import session = require('express-session'); import { LogoutController } from './User/Controller/LogoutController'; import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; @@ -94,7 +91,6 @@ import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting TypeOrmModule.forFeature([ User, UserAdministrative, - File, LeaveRequest, Leave, Event, @@ -138,7 +134,6 @@ import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting { provide: 'ILeaveRequestRepository', useClass: LeaveRequestRepository }, { provide: 'IPasswordEncoder', useClass: PasswordEncoderAdapter }, { provide: 'IDateUtils', useClass: DateUtilsAdapter }, - { provide: 'IFileRepository', useClass: FileRepository }, { provide: 'IEventRepository', useClass: EventRepository }, { provide: 'ICooperativeRepository', useClass: CooperativeRepository }, { diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 007fc3cc..e1ab5ad7 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -7,7 +7,6 @@ import { ProjectModule } from './Infrastructure/Project/project.module'; import { CustomerModule } from './Infrastructure/Customer/customer.module'; import { TaskModule } from './Infrastructure/Task/task.module'; import { FairCalendarModule } from './Infrastructure/FairCalendar/faircalendar.module'; -import { FileModule } from './Infrastructure/File/file.module'; import { HumanResourceModule } from './Infrastructure/HumanResource/humanResource.module'; import { SettingsModule } from './Infrastructure/Settings/settings.module'; import { UnexpectedErrorFilter } from './Infrastructure/Common/ExceptionFilter/UnexpectedErrorFilter'; @@ -37,7 +36,6 @@ providers.push({ HomeModule, CustomerModule, FairCalendarModule, - FileModule, HumanResourceModule, ProjectModule, TaskModule, From 7072be9ade098884c69a413cb06969523e227830 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 18:49:44 +0200 Subject: [PATCH 20/49] Add EditProfileController --- .../User/Controller/EditProfileController.ts | 65 +++++++++++++++++++ .../HumanResource/User/DTO/ProfileDTO.ts | 5 -- .../HumanResource/humanResource.module.ts | 2 + server/src/templates/components/header.njk | 25 +++++++ server/src/templates/components/nav.njk | 2 + server/src/templates/layouts/app.njk | 25 +------ server/src/templates/pages/profile/_form.njk | 27 ++++++++ server/src/templates/pages/profile/edit.njk | 19 ++++++ server/src/translations/fr-FR.ftl | 6 ++ 9 files changed, 147 insertions(+), 29 deletions(-) create mode 100644 server/src/Infrastructure/HumanResource/User/Controller/EditProfileController.ts create mode 100644 server/src/templates/components/header.njk create mode 100644 server/src/templates/pages/profile/_form.njk create mode 100644 server/src/templates/pages/profile/edit.njk diff --git a/server/src/Infrastructure/HumanResource/User/Controller/EditProfileController.ts b/server/src/Infrastructure/HumanResource/User/Controller/EditProfileController.ts new file mode 100644 index 00000000..6ab87ce5 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/User/Controller/EditProfileController.ts @@ -0,0 +1,65 @@ +import { + BadRequestException, + Body, + Controller, + Get, + Inject, + Post, + Render, + Res, + UseGuards +} from '@nestjs/common'; +import { LoggedUser } from '../Decorator/LoggedUser'; +import { User } from 'src/Domain/HumanResource/User/User.entity'; +import { UserView } from 'src/Application/HumanResource/User/View/UserView'; +import { IsAuthenticatedGuard } from '../Security/IsAuthenticatedGuard'; +import { ICommandBus } from 'src/Application/ICommandBus'; +import { ProfileDTO } from '../DTO/ProfileDTO'; +import { UpdateProfileCommand } from 'src/Application/HumanResource/User/Command/UpdateProfileCommand'; +import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; +import { Response } from 'express'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; + +@Controller('app/profile/edit') +@UseGuards(IsAuthenticatedGuard) +export class EditProfileController { + constructor( + @Inject('ICommandBus') + private readonly commandBus: ICommandBus, + private readonly resolver: RouteNameResolver + ) {} + + @Get() + @WithName('profile_edit') + @Render('pages/profile/edit.njk') + public async get(@LoggedUser() user: User) { + const me = new UserView( + user.getId(), + user.getFirstName(), + user.getLastName(), + user.getEmail(), + user.getRole(), + false + ); + + return { user: me }; + } + + @Post() + public async post( + @Body() dto: ProfileDTO, + @LoggedUser() user: User, + @Res() res: Response + ) { + try { + const { firstName, lastName, email, password } = dto; + await this.commandBus.execute( + new UpdateProfileCommand(user, firstName, lastName, email, password) + ); + + res.redirect(303, this.resolver.resolve('home')); + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/HumanResource/User/DTO/ProfileDTO.ts b/server/src/Infrastructure/HumanResource/User/DTO/ProfileDTO.ts index 6c7fc96e..03563d56 100644 --- a/server/src/Infrastructure/HumanResource/User/DTO/ProfileDTO.ts +++ b/server/src/Infrastructure/HumanResource/User/DTO/ProfileDTO.ts @@ -1,21 +1,16 @@ -import { ApiProperty } from '@nestjs/swagger'; import { IsEmail, IsNotEmpty } from 'class-validator'; export class ProfileDTO { @IsNotEmpty() - @ApiProperty() public firstName: string; @IsNotEmpty() - @ApiProperty() public lastName: string; @IsNotEmpty() @IsEmail() - @ApiProperty() public email: string; @IsNotEmpty() - @ApiProperty() public password: string; } diff --git a/server/src/Infrastructure/HumanResource/humanResource.module.ts b/server/src/Infrastructure/HumanResource/humanResource.module.ts index 915855f7..5b0beeab 100644 --- a/server/src/Infrastructure/HumanResource/humanResource.module.ts +++ b/server/src/Infrastructure/HumanResource/humanResource.module.ts @@ -80,6 +80,7 @@ import { GetPendingLeaveRequestsCountAction } from './Leave/Action/GetPendingLea import { GetPendingLeaveRequestsCountQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetPendingLeaveRequestsCountQueryHandler'; import { LogoutController } from './User/Controller/LogoutController'; import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; +import { EditProfileController } from './User/Controller/EditProfileController'; @Module({ imports: [ @@ -104,6 +105,7 @@ import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting controllers: [ LoginController, LogoutController, + EditProfileController, LoginAction, CreateUserAction, GetLeavesAction, diff --git a/server/src/templates/components/header.njk b/server/src/templates/components/header.njk new file mode 100644 index 00000000..83bc4b4d --- /dev/null +++ b/server/src/templates/components/header.njk @@ -0,0 +1,25 @@ +{% import 'macros/icons.njk' as icons %} + +
      +
      + + {{ req.user.firstName|first|upper }} + + +
      +
      diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk index e75a48eb..f0336c21 100644 --- a/server/src/templates/components/nav.njk +++ b/server/src/templates/components/nav.njk @@ -1,3 +1,5 @@ +{% import 'macros/icons.njk' as icons %} +
      + + + {% endfor %} + +
      {{ 'crm-customers-name'|trans }}{{ 'crm-customers-street'|trans }}{{ 'common-actions'|trans }}{{ column|trans }}
      {{ item.name }} - {{ item.address.street }} -
      - {{ item.address.zipCode }} {{ item.address.city }} -
      - {{ item.address.country }} -
      - - {{ icons.pencil(class_name='pc-icon pc-icon--sm pc-icon--action-violet') }} - - + {% if value.actions.edit %} + + {{ icons.pencil(class_name='pc-icon pc-icon--sm pc-icon--action-violet') }} + + {% endif %} + + {% if value.safe %} + {{ value.safe|safe }} + {% else %} + {{ value }} + {% endif %} +
      VideVide
      {% if value.safe %} {{ value.safe|safe }} + {% elseif value.trans %} + {{ value.trans.message|trans(value.trans.params) }} {% else %} {{ value }} {% endif %} diff --git a/server/src/templates/pages/faircalendar/index.njk b/server/src/templates/pages/faircalendar/index.njk index 54af635f..e261c82b 100644 --- a/server/src/templates/pages/faircalendar/index.njk +++ b/server/src/templates/pages/faircalendar/index.njk @@ -20,7 +20,7 @@ diff --git a/server/src/templates/pages/home.njk b/server/src/templates/pages/home.njk index 9e9441c3..fba9fe7d 100644 --- a/server/src/templates/pages/home.njk +++ b/server/src/templates/pages/home.njk @@ -4,6 +4,6 @@ {% block main %}

      - {{ 'home-title'|trans({ user: req.user.firstName|capitalize + ' ' + req.user.lastName|capitalize }) }} + {{ 'home-title'|trans({ user: req.user|fullName }) }}

      {% endblock main %} diff --git a/server/src/templates/pages/profile/_form.njk b/server/src/templates/pages/profile/_form.njk index 8029e689..432c5fb1 100644 --- a/server/src/templates/pages/profile/_form.njk +++ b/server/src/templates/pages/profile/_form.njk @@ -1,24 +1,28 @@ -{% macro profile_form(user, class_name='') %} -
      +{% macro profile_fields(user, require_password=false) %}
      - +
      - +
      - +
      - - + +
      +{% endmacro %} + +{% macro profile_form(user, class_name='') %} + + {{ profile_fields(user) }} +
      +{% endmacro %} + +{% macro user_edit_form(user, roles, contracts, workingTimes, class_name='') %} +
      + {{ _user_role_field(user, roles) }} + {{ _user_administrative_fields(user.administrativeView, contracts, workingTimes) }} + + +
      +{% endmacro %} diff --git a/server/src/templates/pages/users/add.njk b/server/src/templates/pages/users/add.njk new file mode 100644 index 00000000..96a78643 --- /dev/null +++ b/server/src/templates/pages/users/add.njk @@ -0,0 +1,17 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} +{% from './_form.njk' import user_add_form %} + +{% block main_class %}pc-container{% endblock %} + +{% set title = 'users-add-title'|trans %} + +{% block main %} + {{ breadcrumb([{ title: 'people-title'|trans }, { title: 'users-title'|trans, href: path('people_users_list') }, { title: title }]) }} + +

      {{ title }}

      + +
      + {{ user_add_form(roles, contracts, workingTimes, class_name='pc-card__content') }} +
      +{% endblock main %} diff --git a/server/src/templates/pages/users/edit.njk b/server/src/templates/pages/users/edit.njk new file mode 100644 index 00000000..32dc8107 --- /dev/null +++ b/server/src/templates/pages/users/edit.njk @@ -0,0 +1,17 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} +{% from './_form.njk' import user_edit_form %} + +{% block main_class %}pc-container{% endblock %} + +{% set title = 'users-edit-title'|trans({user: user|fullName }) %} + +{% block main %} + {{ breadcrumb([{ title: 'people-title'|trans }, { title: 'users-title'|trans, href: path('people_users_list') }, { title: title }]) }} + +

      {{ title }}

      + +
      + {{ user_edit_form(user, roles, contracts, workingTimes, class_name='pc-card__content') }} +
      +{% endblock main %} diff --git a/server/src/templates/pages/users/list.njk b/server/src/templates/pages/users/list.njk new file mode 100644 index 00000000..fcdcd7ab --- /dev/null +++ b/server/src/templates/pages/users/list.njk @@ -0,0 +1,20 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/table.njk' import render_table with context %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} + +{% block main_class %}pc-container{% endblock %} + +{% set title = 'users-title'|trans %} + +{% block main %} + {{ breadcrumb([{ title: 'people-title'|trans }, { title: title }]) }} + +
      +

      + {{ title }} +

      + {{ 'common-add'|trans }} +
      + + {{ render_table(table) }} +{% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index d9da1387..5cfef00b 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -3,9 +3,14 @@ common-form-delete = Supprimer common-add = Ajouter common-edit = Modifier common-actions = Actions +common-yes = Oui +common-no = Non site-title = Permacoop +header-profile = Mon compte +header-logout = Se déconnecter + home-title = Bonjour, {$user} ! dashboard-title = Tableau de bord @@ -48,13 +53,45 @@ crm-tasks-name = Nom de la mission crm-tasks-edit-title = Édition de la mission "{$name}" profile-title = Mon compte -profile-firstName = Nom -profile-lastName = Prénom +profile-firstName = Prénom +profile-lastName = Nom profile-email = Adresse e-mail profile-password = Mot de passe -accounts-title = FairRH -accounts-workers-title = Coopérateurs - salariés +people-title = FairRH -header-account = Mon compte -header-logout = Se déconnecter +users-title = Coopérateur·ices et salarié·es +users-add-title = Ajouter un·e coopérateur·ice-salarié·e +users-edit-title = Mise à jour des informations administratives de {$user} +users-firstName = Prénom +users-lastName = Nom +users-email = Adresse e-mail +users-role = Rôle +users-role-value = {$role -> + [cooperator] Coopérateur·ice + [employee] Salarié·e + [accountant] Comptable + *[other] Autre +} +users-contract = Contrat de travail +users-contract-value = {$contract -> + [cdi] CDI + [cdd] CDD + [ctt] CTT + [apprenticeship] Apprentissage + [professionalization] Professionalisation + *[other] Autre +} +users-workingTime = Temps de travail +users-workingTime-value = {$workingTime -> + [full_time] Temps plein + [part_time] Temps partiel + *[other] Autre +} +users-executivePosition = Statut cadre +users-healthInsurance = Mutuelle +users-annualEarnings = Salaire annuel brut +users-transportFee = Frais de transport +users-sustainableMobilityFee = Forfait mobilité durable +users-joiningDate = Date d'entrée +users-leavingDate = Date de sortie From 84e7a56fe6e3d9b1d14748512e6b8287f46c5c04 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 22:35:28 +0200 Subject: [PATCH 22/49] Tweak margins, tweak calendar, tweak dark mode --- .../Common/Templating/filters.ts | 10 +++++ .../src/assets/customElements/fullcalendar.js | 2 + .../assets/styles/_components/icon/icon.css | 6 +++ .../assets/styles/_components/table/table.css | 6 +++ server/src/assets/styles/_overrides.css | 5 --- server/src/assets/styles/_reset.css | 1 + server/src/assets/styles/_utilities.css | 4 ++ server/src/assets/styles/_variables.css | 41 ++++++++++++++----- server/src/templates/components/attr.njk | 1 + server/src/templates/macros/table.njk | 5 ++- server/src/templates/pages/customers/edit.njk | 4 +- server/src/templates/pages/customers/list.njk | 2 +- .../pages/faircalendar/events/add.njk | 9 ++-- .../pages/faircalendar/events/edit.njk | 13 ++++-- server/src/templates/pages/projects/add.njk | 7 +++- server/src/templates/pages/projects/edit.njk | 4 +- server/src/templates/pages/projects/list.njk | 2 +- server/src/templates/pages/tasks/add.njk | 7 +++- server/src/templates/pages/tasks/edit.njk | 4 +- server/src/templates/pages/tasks/list.njk | 4 +- server/src/templates/pages/users/edit.njk | 2 +- server/src/templates/pages/users/list.njk | 2 +- server/src/translations/fr-FR.ftl | 5 ++- 23 files changed, 106 insertions(+), 40 deletions(-) create mode 100644 server/src/templates/components/attr.njk diff --git a/server/src/Infrastructure/Common/Templating/filters.ts b/server/src/Infrastructure/Common/Templating/filters.ts index 8567d9d3..e409ec9c 100644 --- a/server/src/Infrastructure/Common/Templating/filters.ts +++ b/server/src/Infrastructure/Common/Templating/filters.ts @@ -17,4 +17,14 @@ export const registerFilters = (env: Environment, translator: ITranslator) => { 'fullName', obj => `${capitalize(obj.firstName)} ${capitalize(obj.lastName)}` ); + env.addFilter('merge', (left, right) => { + const result = {}; + for (const key in left) { + result[key] = left[key]; + } + for (const key in right) { + result[key] = right[key]; + } + return result; + }); }; diff --git a/server/src/assets/customElements/fullcalendar.js b/server/src/assets/customElements/fullcalendar.js index fcd67efb..41ee5c15 100644 --- a/server/src/assets/customElements/fullcalendar.js +++ b/server/src/assets/customElements/fullcalendar.js @@ -16,9 +16,11 @@ export default class extends HTMLElement { initialView: 'dayGridMonth', locale: 'fr', nowIndicator: true, + showNonCurrentDates: false, selectable: true, weekends: false, height: 700, + headerToolbar: false, dayHeaderFormat: { weekday: 'long' }, events, select: info => { diff --git a/server/src/assets/styles/_components/icon/icon.css b/server/src/assets/styles/_components/icon/icon.css index 04e415a3..bec18166 100644 --- a/server/src/assets/styles/_components/icon/icon.css +++ b/server/src/assets/styles/_components/icon/icon.css @@ -6,6 +6,12 @@ color: var(--text-action-violet); } +@media (prefers-color-scheme: dark) { + .pc-icon--action-violet { + color: var(--text-default); + } +} + .pc-icon--sm { width: calc(6 * var(--v)); height: calc(6 * var(--v)); diff --git a/server/src/assets/styles/_components/table/table.css b/server/src/assets/styles/_components/table/table.css index 21cf52b7..c3649a3b 100644 --- a/server/src/assets/styles/_components/table/table.css +++ b/server/src/assets/styles/_components/table/table.css @@ -13,6 +13,12 @@ background-color: var(--background-alt-grey); } +@media (prefers-color-scheme: dark) { + .app-table thead { + background-color: var(--background-default); + } +} + .app-table :where(th, td) { padding: calc(3 * var(--v)) calc(4 * var(--v)); } diff --git a/server/src/assets/styles/_overrides.css b/server/src/assets/styles/_overrides.css index 52074d5c..798e0a73 100644 --- a/server/src/assets/styles/_overrides.css +++ b/server/src/assets/styles/_overrides.css @@ -8,8 +8,3 @@ .fc-view-harness { background-color: var(--background-default); } - -.fc-day-other { - position: static !important; - background-color: var(--background-muted); -} diff --git a/server/src/assets/styles/_reset.css b/server/src/assets/styles/_reset.css index c39ab155..7e369501 100644 --- a/server/src/assets/styles/_reset.css +++ b/server/src/assets/styles/_reset.css @@ -42,6 +42,7 @@ button, textarea, select { font: inherit; + color: currentColor; } /* 7. Avoid text overflows diff --git a/server/src/assets/styles/_utilities.css b/server/src/assets/styles/_utilities.css index f7cb8f6c..d72944c1 100644 --- a/server/src/assets/styles/_utilities.css +++ b/server/src/assets/styles/_utilities.css @@ -38,6 +38,10 @@ margin-top: var(--mt); } +.pc-mb { + margin-bottom: var(--mb); +} + .pc-ml { margin-left: var(--ml); } diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/_variables.css index ca9fcb9f..7b140960 100644 --- a/server/src/assets/styles/_variables.css +++ b/server/src/assets/styles/_variables.css @@ -1,13 +1,3 @@ -@media (prefers-color-scheme: dark) { - :root { - /* Colors */ - --background-default: #1a1b23; - --background-alt-grey: #121317; - --text-default: #ffffff; - --text-muted: #bbbbbb; - } -} - :root { /* Spacing */ --v: 0.25rem; @@ -62,3 +52,34 @@ --event-holiday-border: rgb(237, 235, 254); --event-holiday-text: rgb(108, 43, 217); } + +@media (prefers-color-scheme: dark) { + :root { + /* Colors */ + --background-default: #1a1b23; + --background-alt-grey: #121317; + --background-muted: #272930; + --text-default: #ffffff; + --text-muted: #bbbbbb; + --border-default: #636363; + /* FairCalendar */ + --event-mission-background: rgb(4, 108, 78); + --event-mission-border: rgb(4, 108, 78); + --event-mission-text: var(--text-default); + --event-dojo-background: rgb(26, 86, 219); + --event-dojo-border: rgb(26, 86, 219); + --event-dojo-text: var(--text-default); + --event-support-background: rgb(81, 69, 205); + --event-support-border: rgb(81, 69, 205); + --event-support-text: var(--text-default); + --event-formation_conference-background: rgb(180, 52, 3); + --event-formation_conference-border: rgb(180, 52, 3); + --event-formation_conference-text: var(--text-default); + --event-other-background: rgb(36, 38, 45); + --event-other-border: rgb(36, 38, 45); + --event-other-text: var(--text-default); + --event-holiday-background: rgb(159, 88, 10); + --event-holiday-border: rgb(159, 88, 10); + --event-holiday-text: var(--text-default); + } +} diff --git a/server/src/templates/components/attr.njk b/server/src/templates/components/attr.njk new file mode 100644 index 00000000..c06561a0 --- /dev/null +++ b/server/src/templates/components/attr.njk @@ -0,0 +1 @@ +{% for name, value in attr %}{% if value == true %}{{ name }}{% else %}{{ name }}="{{ value }}"{% endif %}{% endfor %} diff --git a/server/src/templates/macros/table.njk b/server/src/templates/macros/table.njk index a15e12e0..ea73bdbe 100644 --- a/server/src/templates/macros/table.njk +++ b/server/src/templates/macros/table.njk @@ -1,7 +1,8 @@ {% import 'macros/icons.njk' as icons %} -{% macro render_table(table) %} - +{% macro render_table(table, attr={}) %} +{% set attr = attr|merge({class: 'app-table ' + attr.class|default('')}) %} +
      {% for column in table.columns %} diff --git a/server/src/templates/pages/customers/edit.njk b/server/src/templates/pages/customers/edit.njk index a421abac..2aac3955 100644 --- a/server/src/templates/pages/customers/edit.njk +++ b/server/src/templates/pages/customers/edit.njk @@ -9,11 +9,11 @@ {% block main %} {{ breadcrumb([{ title: 'crm-customers-title'|trans, href: path('crm_customers_list') }, { title: title }]) }} -

      +

      {{ title }}

      -
      +
      {{ customer_form(customer, class_name='pc-card__content') }}
      {% endblock main %} diff --git a/server/src/templates/pages/customers/list.njk b/server/src/templates/pages/customers/list.njk index 13b40d5d..f7991da8 100644 --- a/server/src/templates/pages/customers/list.njk +++ b/server/src/templates/pages/customers/list.njk @@ -12,5 +12,5 @@ {{ 'common-add'|trans }}
      - {{ render_table(table) }} + {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} {% endblock main %} diff --git a/server/src/templates/pages/faircalendar/events/add.njk b/server/src/templates/pages/faircalendar/events/add.njk index a08b10b3..148f1333 100644 --- a/server/src/templates/pages/faircalendar/events/add.njk +++ b/server/src/templates/pages/faircalendar/events/add.njk @@ -1,12 +1,15 @@ {% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import event_form %} {% block main_class %}pc-container{% endblock %} +{% set title = 'faircalendar-events-add-title'|trans({ date: date }) %} + {% block main %} -

      - {{ 'faircalendar-events-add-title'|trans({ date: date }) }} -

      + {{ breadcrumb([{ title: 'faircalendar-title'|trans, href: path('faircalendar_index') }, { title: title }]) }} + +

      {{ title }}

      {{ event_form(null, types, projects, tasks, times, date, class_name='pc-card__content') }} diff --git a/server/src/templates/pages/faircalendar/events/edit.njk b/server/src/templates/pages/faircalendar/events/edit.njk index 8fc97b09..c5c0641e 100644 --- a/server/src/templates/pages/faircalendar/events/edit.njk +++ b/server/src/templates/pages/faircalendar/events/edit.njk @@ -1,21 +1,26 @@ {% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import event_form %} {% block main_class %}pc-container{% endblock %} +{% set title = 'faircalendar-events-edit-title'|trans({ date: event.date }) %} + {% block main %} -
      + {{ breadcrumb([{ title: 'faircalendar-title'|trans, href: path('faircalendar_index') }, { title: title }]) }} + +

      - {{ 'faircalendar-events-edit-title'|trans({ date: event.date }) }} + {{ title }}

      -
      +
      -
      +
      {{ event_form(event, types, projects, tasks, times, class_name='pc-card__content') }}
      {% endblock main %} diff --git a/server/src/templates/pages/projects/add.njk b/server/src/templates/pages/projects/add.njk index 74e29aa8..c1d91690 100644 --- a/server/src/templates/pages/projects/add.njk +++ b/server/src/templates/pages/projects/add.njk @@ -1,11 +1,16 @@ {% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import project_form %} {% block main_class %}pc-container{% endblock %} +{% set title = 'crm-projects-add-title'|trans %} + {% block main %} + {{ breadcrumb([{ title: 'crm-projects-title'|trans, href: path('crm_projects_list') }, { title: title }]) }} +

      - {{ 'crm-projects-add-title'|trans }} + {{ title }}

      diff --git a/server/src/templates/pages/projects/edit.njk b/server/src/templates/pages/projects/edit.njk index e312fbda..c36ca0e3 100644 --- a/server/src/templates/pages/projects/edit.njk +++ b/server/src/templates/pages/projects/edit.njk @@ -9,11 +9,11 @@ {% block main %} {{ breadcrumb([{ title: 'crm-projects-title'|trans, href: path('crm_projects_list') }, { title: title }]) }} -

      +

      {{ title }}

      -
      +
      {{ project_form(project, customers, class_name='pc-card__content') }}
      {% endblock main %} diff --git a/server/src/templates/pages/projects/list.njk b/server/src/templates/pages/projects/list.njk index 07a2fd3b..ebb09d6c 100644 --- a/server/src/templates/pages/projects/list.njk +++ b/server/src/templates/pages/projects/list.njk @@ -12,5 +12,5 @@ {{ 'common-add'|trans }}
      - {{ render_table(table) }} + {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} {% endblock main %} diff --git a/server/src/templates/pages/tasks/add.njk b/server/src/templates/pages/tasks/add.njk index 50efb3d7..4b9584db 100644 --- a/server/src/templates/pages/tasks/add.njk +++ b/server/src/templates/pages/tasks/add.njk @@ -1,11 +1,16 @@ {% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import task_form %} {% block main_class %}pc-container{% endblock %} +{% set title = 'crm-tasks-add-title'|trans %} + {% block main %} + {{ breadcrumb([{ title: 'crm-tasks-title'|trans, href: path('crm_tasks_list') }, { title: title }]) }} +

      - {{ 'crm-tasks-add-title'|trans }} + {{ title }}

      diff --git a/server/src/templates/pages/tasks/edit.njk b/server/src/templates/pages/tasks/edit.njk index ac741835..92e2d647 100644 --- a/server/src/templates/pages/tasks/edit.njk +++ b/server/src/templates/pages/tasks/edit.njk @@ -9,11 +9,11 @@ {% block main %} {{ breadcrumb([{ title: 'crm-tasks-title'|trans, href: path('crm_tasks_list') }, { title: title }]) }} -

      +

      {{ title }}

      -
      +
      {{ task_form(task, class_name='pc-card__content') }}
      {% endblock main %} diff --git a/server/src/templates/pages/tasks/list.njk b/server/src/templates/pages/tasks/list.njk index 6206bf80..dae7ed8f 100644 --- a/server/src/templates/pages/tasks/list.njk +++ b/server/src/templates/pages/tasks/list.njk @@ -7,10 +7,10 @@ {% block main %} {{ breadcrumb([{ title: 'crm-tasks-title'|trans }]) }} -
      +

      {{ 'crm-tasks-title'|trans }}

      {{ 'common-add'|trans }}
      - {{ render_table(table) }} + {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} {% endblock main %} diff --git a/server/src/templates/pages/users/edit.njk b/server/src/templates/pages/users/edit.njk index 32dc8107..4f7a33b4 100644 --- a/server/src/templates/pages/users/edit.njk +++ b/server/src/templates/pages/users/edit.njk @@ -11,7 +11,7 @@

      {{ title }}

      -
      +
      {{ user_edit_form(user, roles, contracts, workingTimes, class_name='pc-card__content') }}
      {% endblock main %} diff --git a/server/src/templates/pages/users/list.njk b/server/src/templates/pages/users/list.njk index fcdcd7ab..9f1d8149 100644 --- a/server/src/templates/pages/users/list.njk +++ b/server/src/templates/pages/users/list.njk @@ -16,5 +16,5 @@ {{ 'common-add'|trans }}
      - {{ render_table(table) }} + {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} {% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index 5cfef00b..36546bce 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -16,8 +16,8 @@ home-title = Bonjour, {$user} ! dashboard-title = Tableau de bord faircalendar-title = FairCalendar -faircalendar-events-add-title = CRA du {$date} -faircalendar-events-edit-title = CRA du {$date} +faircalendar-events-add-title = Ajout d'un CRA le {$date} +faircalendar-events-edit-title = Édition du CRA du {$date} faircalendar-type-title = Type de CRA faircalendar-type-option = {$type -> [mission] Mission @@ -50,6 +50,7 @@ crm-projects-customer-title = Client crm-tasks-title = Missions crm-tasks-name = Nom de la mission +crm-tasks-add-title = Ajouter une mission crm-tasks-edit-title = Édition de la mission "{$name}" profile-title = Mon compte From ddb4bfa2092b31333fa054cc9b269dedc884ecf0 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 22 Sep 2023 23:53:30 +0200 Subject: [PATCH 23/49] Fix tests, add more e2e tests, update README --- Makefile | 30 ++++----- README.md | 24 +------ server/.gitignore | 2 + server/e2e/auth.setup.js | 13 ++++ server/e2e/home.spec.js | 65 +++++++++++++++++++ server/e2e/login.spec.js | 28 ++++---- server/package.json | 4 +- server/playwright.config.ts | 20 +++++- .../Adapter/FluentTranslatorAdapter.ts | 2 +- .../Customer/DTO/AddressDTO.spec.ts | 38 ----------- .../Infrastructure/Customer/DTO/AddressDTO.ts | 22 ------- .../Customer/DTO/CustomerDTO.spec.ts | 41 ++++++------ .../FairCalendar/DTO/AbstractEventDTO.ts | 2 +- .../User/DTO/UserAdministrativeDTO.spec.ts | 10 +-- .../User/DTO/UserAdministrativeDTO.ts | 6 +- .../HumanResource/User/DTO/UserDTO.spec.ts | 47 +++++++++----- .../Project/DTO/ProjectDTO.spec.ts | 8 +-- .../styles/_components/dropdown/dropdown.css | 1 + .../assets/styles/_components/icon/icon.css | 9 ++- .../assets/styles/_components/input/input.css | 3 +- .../src/assets/styles/_components/nav/nav.css | 3 +- .../assets/styles/_components/table/table.css | 3 +- server/src/templates/components/header.njk | 32 ++++----- server/src/templates/components/nav.njk | 10 ++- server/src/templates/macros/icons.njk | 6 ++ server/src/templates/macros/table.njk | 2 +- server/src/templates/pages/home.njk | 4 +- server/src/translations/fr-FR.ftl | 2 + 28 files changed, 238 insertions(+), 199 deletions(-) create mode 100644 server/e2e/auth.setup.js create mode 100644 server/e2e/home.spec.js delete mode 100644 server/src/Infrastructure/Customer/DTO/AddressDTO.spec.ts delete mode 100644 server/src/Infrastructure/Customer/DTO/AddressDTO.ts diff --git a/Makefile b/Makefile index 077d1861..57778bef 100644 --- a/Makefile +++ b/Makefile @@ -16,14 +16,15 @@ endif install-deps: ## Install dependencies cd server && npm ci -install-dev: up ## Install local development dependencies and services +install-dev: ## Install local development dependencies and services cd server && npx playwright install firefox + make build make database-test-init -start: up ## Start +start: ## Start make -j 2 start-server start-watch -start-server: +start-server: up ${run_server} "cd server && npm run start:dev" start-watch: @@ -47,15 +48,15 @@ rm: stop ## Stop and remove containers ps: ## Show running containers make compose CMD=ps -build: build-app build-assets ## Build dist +build: build-server build-assets ## Build dist -build-app: +build-server: cd server && npm run build build-assets: cd server && npm run assets:build -start-dist: ## Serve built server +start-dist: up ## Serve built server cd server && npm run start:prod test: ## Run tests @@ -79,25 +80,22 @@ format: ## Run code formatting database-migrate: ## Database migrations cd server && npm run migration:migrate -database-test-init: ## Initialize test database +database-test-init: up ## Initialize test database make compose CMD="exec -T database createdb permacoop_test" || echo 'Does the test DB already exist? Ignoring...' - DATABASE_NAME=permacoop_test make database-migrate + make database-migrate DATABASE_NAME=permacoop_test + make database-seed DATABASE_NAME=permacoop_test database-migration: ## Generate a database migration cd server && npm run migration:create -- migrations/$(NAME) database-seed: ## Seed database - cd server && npm run build && npm run seed:run + cd server && npm run seed:run database-connect: ## Connect to the database container ${compose} exec database psql -h database -d permacoop -ci: ## Run CI checks - make compose CMD="up -d" +ci: up ## Run CI checks make install - make build - make database-migrate - make test-cov - make database-test-init - make test-e2e make linter + make test-cov + make test-e2e CI=1 diff --git a/README.md b/README.md index fdd3b087..f27d84d8 100644 --- a/README.md +++ b/README.md @@ -61,10 +61,7 @@ This command will create the default user "John Doe" : } ``` -The server and client will be started: - -- API documentation available on -- Client available on +The server will be available at . ## Helpers @@ -91,16 +88,10 @@ To run tests, use: make test ``` -For E2E tests, you will need to install additional dependencies first: - -```bash -make install-client-e2e -``` - Run E2E tests using: ```bash -make test-client-e2e +make test-e2e ``` ### Code quality @@ -125,12 +116,6 @@ To generate a migration from the current state of the code, run: make database-migration NAME=add_some_column ``` -## Security - -The client must send the user `apiToken` in the Authorization header when making requests to protected resources : `Authorization: Bearer ` - -To retrieve the `apiToken`, make a post request on `/login` with a user email and password. - ## Features - Tasks management @@ -142,11 +127,6 @@ To retrieve the `apiToken`, make a post request on `/login` with a user email an - Leaves - Cooperators / employee - Savings records -- Accounting - - Quotations - - Daily rates - - Invoicing -- Contacts managment ## Credits diff --git a/server/.gitignore b/server/.gitignore index 0027a30a..8d865966 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -13,3 +13,5 @@ lerna-debug.log* # Tests /coverage /.nyc_output +test-results/ +playwright/ diff --git a/server/e2e/auth.setup.js b/server/e2e/auth.setup.js new file mode 100644 index 00000000..34033b41 --- /dev/null +++ b/server/e2e/auth.setup.js @@ -0,0 +1,13 @@ +// @ts-check +import { test } from '@playwright/test'; + +const authFile = 'playwright/.auth/johnDoe.json'; + +test('authenticate', async ({ page }) => { + await page.goto('/login'); + await page.fill("input[name='email']", 'john@doe.com'); + await page.fill("input[name='password']", 'john'); + await page.getByRole('button', { name: 'Se connecter' }).click(); + await page.waitForURL('/app'); + await page.context().storageState({ path: authFile }); +}); diff --git a/server/e2e/home.spec.js b/server/e2e/home.spec.js new file mode 100644 index 00000000..49bd7444 --- /dev/null +++ b/server/e2e/home.spec.js @@ -0,0 +1,65 @@ +// @ts-check +import { test, expect } from '@playwright/test'; + +test.use({ storageState: 'playwright/.auth/johnDoe.json' }); + +test('redirects from index', async ({ page }) => { + await page.goto('/'); + await page.waitForURL('/app'); +}); + +test('home content', async ({ page }) => { + await page.goto('/app'); + await expect(page.getByRole('heading', { level: 1 })).toHaveText( + 'Bonjour, John Doe !' + ); +}); + +test('page navigation', async ({ page }) => { + await page.goto('/app'); + + const homeLink = page.getByRole('link', { name: 'Tableau de bord' }); + await expect(homeLink).toHaveAttribute('aria-current', 'page'); + await homeLink.click(); + await page.waitForURL('/app'); + + const fairCalendarLink = page.getByRole('link', { name: 'FairCalendar' }); + await expect(fairCalendarLink).not.toHaveAttribute('aria-current', 'page'); + await fairCalendarLink.click(); + await page.getByRole('heading', { level: 1, name: 'FairCalendar' }).waitFor(); + await expect(homeLink).not.toHaveAttribute('aria-current', 'page'); + await expect(fairCalendarLink).toHaveAttribute('aria-current', 'page'); +}); + +test('nav links', async ({ page }) => { + await page.goto('/app'); + + const links = await page + .getByRole('navigation') + .getByRole('link') + .evaluateAll(links => + links.map(link => [link.textContent?.trim(), link.getAttribute('href')]) + ); + + expect(links).toEqual([ + ['Tableau de bord', '/app'], + ['FairCalendar', '/app/faircalendar'], + ['Clients', '/app/customers'], + ['Projets', '/app/projects'], + ['Missions', '/app/tasks'], + ['Coopérateur·ices et salarié·es', '/app/people/users'] + ]); +}); + +test('header actions', async ({ page }) => { + await page.goto('/app'); + + await page.getByRole('link', { name: 'Mon compte' }).click(); + await page.getByRole('heading', { level: 1, name: 'Mon compte' }).waitFor(); + + const logoutButton = page.getByRole('button', { name: 'Se déconnecter' }); + await expect(logoutButton).not.toBeVisible(); + await page.getByRole('group', { name: "Voir plus d'actions" }).click(); + await logoutButton.click(); + await page.waitForURL('/login'); +}); diff --git a/server/e2e/login.spec.js b/server/e2e/login.spec.js index e39ff89c..bb9ce298 100644 --- a/server/e2e/login.spec.js +++ b/server/e2e/login.spec.js @@ -1,22 +1,24 @@ +// @ts-check import { test, expect } from '@playwright/test'; test('redirects to login', async ({ page }) => { - await page.goto('/'); - await page.waitForURL('/login'); + await page.goto('/'); + await page.waitForURL('/login'); }); test('logs in', async ({ page }) => { - await page.goto('/login'); + await page.goto('/login'); - const emailField = page.getByRole('textbox', { name: 'Adresse email' }); - await expect(emailField).toHaveAttribute('type', 'email'); - await emailField.fill('john@doe.com'); - - const passwordField = page.getByRole('textbox', { name: 'Mot de passe' }); - await expect(passwordField).toHaveAttribute('type', 'password'); - await passwordField.fill('john'); + const emailField = page.getByRole('textbox', { name: 'Adresse email' }); + await expect(emailField).toHaveAttribute('type', 'email'); + await emailField.fill('john@doe.com'); - await page.getByRole('button', { name: 'Se connecter' }).click(); + const passwordField = page.getByRole('textbox', { name: 'Mot de passe' }); + await expect(passwordField).toHaveAttribute('type', 'password'); + await passwordField.fill('john'); - await page.waitForURL('/'); -}) + await page.getByRole('button', { name: 'Se connecter' }).click(); + await page + .getByRole('heading', { level: 1, name: 'Bonjour, John Doe !' }) + .waitFor(); +}); diff --git a/server/package.json b/server/package.json index dccd9bf4..69c85ecb 100644 --- a/server/package.json +++ b/server/package.json @@ -9,11 +9,11 @@ "build": "nest build", "assets:build": "esbuild src/assets/main.js --bundle --minify --outfile=dist/public/app.js", "assets:watch": "npm run assets:build -- --watch", - "format": "prettier --write \"src/**/*.ts\" \"src/assets/**/*\" \"test/**/*.ts\"", + "format": "prettier --write \"src/**/*.ts\" \"src/assets/**/*\" \"e2e/**/*.js\"", "start": "nest start", "start:dev": "nest start --preserveWatchOutput --watch --debug", "start:prod": "node dist/src/main", - "lint": "prettier --check \"src/**/*.ts\" \"src/assets/**/*\" \"test/**/*.ts\" && eslint src/**/*.ts", + "lint": "prettier --check \"src/**/*.ts\" \"src/assets/**/*\" \"e2e/**/*.js\" && eslint src/**/*.ts", "lint:fix": "eslint src/**/*.ts --fix", "test": "jest", "test:watch": "jest --watchAll", diff --git a/server/playwright.config.ts b/server/playwright.config.ts index 5ec41ba4..ed004a01 100644 --- a/server/playwright.config.ts +++ b/server/playwright.config.ts @@ -1,9 +1,9 @@ -import type { PlaywrightTestConfig } from "@playwright/test"; +import { type PlaywrightTestConfig, devices } from "@playwright/test"; const config: PlaywrightTestConfig = { testDir: "./e2e", retries: 0, - timeout: 5 * 1000, + timeout: 10 * 1000, use: { baseURL: "http://localhost:3000", browserName: "firefox", @@ -11,6 +11,22 @@ const config: PlaywrightTestConfig = { screenshot: "only-on-failure", video: "on-first-retry", }, + projects: [ + { name: 'setup', testMatch: /.*\.setup\.js/ }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + dependencies: ['setup'], + }, + ], + webServer: { + command: 'cd .. && make start-dist', + reuseExistingServer: !process.env.CI, + url: 'http://localhost:3000', + env: { + DATABASE_NAME: 'permacoop_test', + } + }, }; export default config; diff --git a/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts b/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts index 18d7c1f4..c51f00a3 100644 --- a/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts +++ b/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts @@ -31,7 +31,7 @@ const _readBundle = (path: string, locale: string) => { const resource = new fluent.FluentResource(content); - const bundle = new fluent.FluentBundle(locale); + const bundle = new fluent.FluentBundle(locale, { useIsolating: false }); const errors = bundle.addResource(resource); if (errors.length > 0) { diff --git a/server/src/Infrastructure/Customer/DTO/AddressDTO.spec.ts b/server/src/Infrastructure/Customer/DTO/AddressDTO.spec.ts deleted file mode 100644 index e6c8daf3..00000000 --- a/server/src/Infrastructure/Customer/DTO/AddressDTO.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { validate } from 'class-validator'; -import { AddressDTO } from './AddressDTO'; - -describe('AddressDTO', () => { - it('testValidDTO', async () => { - const dto = new AddressDTO(); - dto.street = '2 rue Dieu'; - dto.city = 'Paris'; - dto.zipCode = '75010'; - dto.country = 'FR'; - - const validation = await validate(dto); - expect(validation).toHaveLength(0); - }); - - it('testInvalidDTO', async () => { - const dto = new AddressDTO(); - dto.street = ''; - dto.city = ''; - dto.zipCode = ''; - dto.country = 'France'; - - const validation = await validate(dto); - expect(validation).toHaveLength(4); - expect(validation[0].constraints).toMatchObject({ - isNotEmpty: 'street should not be empty' - }); - expect(validation[1].constraints).toMatchObject({ - isNotEmpty: 'city should not be empty' - }); - expect(validation[2].constraints).toMatchObject({ - isNotEmpty: 'zipCode should not be empty' - }); - expect(validation[3].constraints).toMatchObject({ - isISO31661Alpha2: 'country must be a valid ISO31661 Alpha2 code' - }); - }); -}); diff --git a/server/src/Infrastructure/Customer/DTO/AddressDTO.ts b/server/src/Infrastructure/Customer/DTO/AddressDTO.ts deleted file mode 100644 index c44f7b0d..00000000 --- a/server/src/Infrastructure/Customer/DTO/AddressDTO.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, MaxLength, IsISO31661Alpha2 } from 'class-validator'; - -export class AddressDTO { - @ApiProperty() - @IsNotEmpty() - public street: string; - - @ApiProperty() - @IsNotEmpty() - public city: string; - - @ApiProperty() - @IsNotEmpty() - @MaxLength(6) - public zipCode: string; - - @ApiProperty() - @IsNotEmpty() - @IsISO31661Alpha2() - public country: string; -} diff --git a/server/src/Infrastructure/Customer/DTO/CustomerDTO.spec.ts b/server/src/Infrastructure/Customer/DTO/CustomerDTO.spec.ts index fd17815e..d0b3b91a 100644 --- a/server/src/Infrastructure/Customer/DTO/CustomerDTO.spec.ts +++ b/server/src/Infrastructure/Customer/DTO/CustomerDTO.spec.ts @@ -1,18 +1,14 @@ import { CustomerDTO } from './CustomerDTO'; import { validate } from 'class-validator'; -import { AddressDTO } from './AddressDTO'; describe('CustomerDTO', () => { it('testValidDTO', async () => { - const addressDto = new AddressDTO(); - addressDto.street = '2 rue Dieu'; - addressDto.city = 'Paris'; - addressDto.zipCode = '75010'; - addressDto.country = 'FR'; - const dto = new CustomerDTO(); dto.name = 'Customer'; - dto.address = addressDto; + dto.street = '2 rue Dieu'; + dto.city = 'Paris'; + dto.zipCode = '75010'; + dto.country = 'FR'; const validation = await validate(dto); expect(validation).toHaveLength(0); @@ -21,26 +17,27 @@ describe('CustomerDTO', () => { it('testInvalidDTO', async () => { const dto = new CustomerDTO(); dto.name = ''; + dto.street = ''; + dto.city = ''; + dto.zipCode = ''; + dto.country = 'France'; const validation = await validate(dto); - expect(validation).toHaveLength(2); + expect(validation).toHaveLength(5); expect(validation[0].constraints).toMatchObject({ isNotEmpty: 'name should not be empty' }); expect(validation[1].constraints).toMatchObject({ - isNotEmpty: 'address should not be empty' + isNotEmpty: 'street should not be empty' + }); + expect(validation[2].constraints).toMatchObject({ + isNotEmpty: 'city should not be empty' + }); + expect(validation[3].constraints).toMatchObject({ + isNotEmpty: 'zipCode should not be empty' + }); + expect(validation[4].constraints).toMatchObject({ + isISO31661Alpha2: 'country must be a valid ISO31661 Alpha2 code' }); - }); - - it('testInvalidAddressDTO', async () => { - const badAddress = new AddressDTO(); - badAddress.country = 'France'; - const dto = new CustomerDTO(); - - dto.name = 'Customer'; - dto.address = badAddress; - - const validation = await validate(dto); - expect(validation).toHaveLength(1); }); }); diff --git a/server/src/Infrastructure/FairCalendar/DTO/AbstractEventDTO.ts b/server/src/Infrastructure/FairCalendar/DTO/AbstractEventDTO.ts index 349aecd7..b9ceb10d 100644 --- a/server/src/Infrastructure/FairCalendar/DTO/AbstractEventDTO.ts +++ b/server/src/Infrastructure/FairCalendar/DTO/AbstractEventDTO.ts @@ -17,7 +17,7 @@ export abstract class AbstractEventDTO { @IsNotEmpty() @IsInt() - @IsIn([...ArrayUtils.range(30, 480, 30)].map(n => n.toString())) + @IsIn([...ArrayUtils.range(30, 480, 30)]) public time: number; @IsOptional() diff --git a/server/src/Infrastructure/HumanResource/User/DTO/UserAdministrativeDTO.spec.ts b/server/src/Infrastructure/HumanResource/User/DTO/UserAdministrativeDTO.spec.ts index 3c4b3720..b516dc9d 100644 --- a/server/src/Infrastructure/HumanResource/User/DTO/UserAdministrativeDTO.spec.ts +++ b/server/src/Infrastructure/HumanResource/User/DTO/UserAdministrativeDTO.spec.ts @@ -27,7 +27,7 @@ describe('UserAdministrativeDTO', () => { const dto = new UserAdministrativeDTO(); dto.role = UserRole.COOPERATOR; dto.joiningDate = ''; - dto.leavingDate = ''; + dto.leavingDate = 'invalid'; const validation = await validate(dto); @@ -38,19 +38,19 @@ describe('UserAdministrativeDTO', () => { isPositive: 'annualEarnings must be a positive number' }); expect(validation[1].constraints).toMatchObject({ - isBooleanString: 'healthInsurance must be a boolean string', + isBoolean: 'healthInsurance must be a boolean value', isNotEmpty: 'healthInsurance should not be empty' }); expect(validation[2].constraints).toMatchObject({ - isBooleanString: 'executivePosition must be a boolean string', + isBoolean: 'executivePosition must be a boolean value', isNotEmpty: 'executivePosition should not be empty' }); expect(validation[3].constraints).toMatchObject({ - isDateString: 'joiningDate must be a ISOString', + // isDateString: 'joiningDate must be a ISOString', isNotEmpty: 'joiningDate should not be empty' }); expect(validation[4].constraints).toMatchObject({ - isDateString: 'leavingDate must be a ISOString' + isIso8601: 'leavingDate must be a valid ISO 8601 date string' }); expect(validation[5].constraints).toMatchObject({ isEnum: 'contract must be a valid enum value', diff --git a/server/src/Infrastructure/HumanResource/User/DTO/UserAdministrativeDTO.ts b/server/src/Infrastructure/HumanResource/User/DTO/UserAdministrativeDTO.ts index 6d435199..85688bba 100644 --- a/server/src/Infrastructure/HumanResource/User/DTO/UserAdministrativeDTO.ts +++ b/server/src/Infrastructure/HumanResource/User/DTO/UserAdministrativeDTO.ts @@ -7,7 +7,8 @@ import { IsNumber, IsBoolean, Min, - IsISO8601 + IsISO8601, + ValidateIf } from 'class-validator'; import { ContractType, @@ -47,7 +48,8 @@ export class UserAdministrativeDTO { @IsISO8601() public joiningDate: string; - @IsOptional() + @IsISO8601() + @ValidateIf(v => v.leavingDate !== '') public leavingDate: string; @IsNotEmpty() diff --git a/server/src/Infrastructure/HumanResource/User/DTO/UserDTO.spec.ts b/server/src/Infrastructure/HumanResource/User/DTO/UserDTO.spec.ts index 9efa29d3..2c87b394 100644 --- a/server/src/Infrastructure/HumanResource/User/DTO/UserDTO.spec.ts +++ b/server/src/Infrastructure/HumanResource/User/DTO/UserDTO.spec.ts @@ -7,18 +7,7 @@ import { } from 'src/Domain/HumanResource/User/UserAdministrative.entity'; describe('UserDTO', () => { - it('testValidWithoutAdministrativeDTO', async () => { - const dto = new UserDTO(); - dto.email = 'mathieu@fairness.coop'; - dto.firstName = 'Mathieu'; - dto.lastName = 'MARCHOIS'; - dto.password = 'password'; - - const validation = await validate(dto); - expect(validation).toHaveLength(0); - }); - - it('testValidWithAdministrativeDTO', async () => { + it('testValidDTO', async () => { const dto = new UserDTO(); dto.email = 'mathieu@fairness.coop'; dto.firstName = 'Mathieu'; @@ -46,10 +35,10 @@ describe('UserDTO', () => { dto.password = ''; dto.transportFee = 1.5; dto.joiningDate = ''; - dto.leavingDate = ''; + dto.leavingDate = 'invalid'; const validation = await validate(dto); - expect(validation).toHaveLength(5); + expect(validation).toHaveLength(12); expect(validation[0].constraints).toMatchObject({ isNotEmpty: 'firstName should not be empty' }); @@ -62,9 +51,37 @@ describe('UserDTO', () => { expect(validation[3].constraints).toMatchObject({ isNotEmpty: 'password should not be empty' }); - expect(validation[4].children[0].constraints).toMatchObject({ + expect(validation[4].constraints).toMatchObject({ isEnum: 'role must be a valid enum value', isNotEmpty: 'role should not be empty' }); + expect(validation[5].constraints).toMatchObject({ + isInt: 'annualEarnings must be an integer number', + isNotEmpty: 'annualEarnings should not be empty', + isPositive: 'annualEarnings must be a positive number' + }); + expect(validation[6].constraints).toMatchObject({ + isBoolean: 'healthInsurance must be a boolean value', + isNotEmpty: 'healthInsurance should not be empty' + }); + expect(validation[7].constraints).toMatchObject({ + isBoolean: 'executivePosition must be a boolean value', + isNotEmpty: 'executivePosition should not be empty' + }); + expect(validation[8].constraints).toMatchObject({ + isIso8601: 'joiningDate must be a valid ISO 8601 date string', + isNotEmpty: 'joiningDate should not be empty' + }); + expect(validation[9].constraints).toMatchObject({ + isIso8601: 'leavingDate must be a valid ISO 8601 date string' + }); + expect(validation[10].constraints).toMatchObject({ + isEnum: 'contract must be a valid enum value', + isNotEmpty: 'contract should not be empty' + }); + expect(validation[11].constraints).toMatchObject({ + isEnum: 'workingTime must be a valid enum value', + isNotEmpty: 'workingTime should not be empty' + }); }); }); diff --git a/server/src/Infrastructure/Project/DTO/ProjectDTO.spec.ts b/server/src/Infrastructure/Project/DTO/ProjectDTO.spec.ts index 78cfe53e..a3551896 100644 --- a/server/src/Infrastructure/Project/DTO/ProjectDTO.spec.ts +++ b/server/src/Infrastructure/Project/DTO/ProjectDTO.spec.ts @@ -1,13 +1,11 @@ import { ProjectDTO } from './ProjectDTO'; import { validate } from 'class-validator'; -import { InvoiceUnits } from 'src/Domain/Project/Project.entity'; describe('ProjectDTO', () => { it('testValidDTO', async () => { const dto = new ProjectDTO(); dto.name = 'Project'; dto.customerId = '2218609f-293b-4438-b3a0-cce8961e8acc'; - dto.invoiceUnit = InvoiceUnits.DAY; const validation = await validate(dto); expect(validation).toHaveLength(0); @@ -19,15 +17,11 @@ describe('ProjectDTO', () => { dto.customerId = '12'; const validation = await validate(dto); - expect(validation).toHaveLength(3); + expect(validation).toHaveLength(2); expect(validation[0].constraints).toMatchObject({ isNotEmpty: 'name should not be empty' }); expect(validation[1].constraints).toMatchObject({ - isEnum: 'invoiceUnit must be a valid enum value', - isNotEmpty: 'invoiceUnit should not be empty' - }); - expect(validation[2].constraints).toMatchObject({ isUuid: 'customerId must be an UUID' }); }); diff --git a/server/src/assets/styles/_components/dropdown/dropdown.css b/server/src/assets/styles/_components/dropdown/dropdown.css index b110bbe0..4695ed14 100644 --- a/server/src/assets/styles/_components/dropdown/dropdown.css +++ b/server/src/assets/styles/_components/dropdown/dropdown.css @@ -3,6 +3,7 @@ details.pc-dropdown { } details.pc-dropdown > summary { + display: inline; /* Remove default 'v' */ cursor: pointer; } diff --git a/server/src/assets/styles/_components/icon/icon.css b/server/src/assets/styles/_components/icon/icon.css index bec18166..b8c3ab5f 100644 --- a/server/src/assets/styles/_components/icon/icon.css +++ b/server/src/assets/styles/_components/icon/icon.css @@ -1,3 +1,9 @@ +.pc-icon { + --size: 7; + width: calc(var(--size) * var(--v)); + height: calc(var(--size) * var(--v)); +} + .pc-icon--error { color: var(--text-error); } @@ -13,8 +19,7 @@ } .pc-icon--sm { - width: calc(6 * var(--v)); - height: calc(6 * var(--v)); + --size: 5; } .pc-icon--left { diff --git a/server/src/assets/styles/_components/input/input.css b/server/src/assets/styles/_components/input/input.css index bd0fe580..7f9f5c9b 100644 --- a/server/src/assets/styles/_components/input/input.css +++ b/server/src/assets/styles/_components/input/input.css @@ -30,7 +30,8 @@ padding: var(--w) calc(5 * var(--w)) var(--w) calc(3 * var(--v)); } -:where(.pc-input-group, .pc-select-group) > label { +.pc-input-group > label, +.pc-select-group > label { display: block; padding-bottom: var(--v); } diff --git a/server/src/assets/styles/_components/nav/nav.css b/server/src/assets/styles/_components/nav/nav.css index 22ee8ac3..f6f0e1e9 100644 --- a/server/src/assets/styles/_components/nav/nav.css +++ b/server/src/assets/styles/_components/nav/nav.css @@ -53,7 +53,8 @@ position: relative; } -.pc-nav :where(li.active, > ul > li > a[aria-current='page'])::before { +.pc-nav li.active::before, +.pc-nav > ul > li > a[aria-current='page']::before { position: absolute; content: ''; inset: 0; diff --git a/server/src/assets/styles/_components/table/table.css b/server/src/assets/styles/_components/table/table.css index c3649a3b..c8e99b5a 100644 --- a/server/src/assets/styles/_components/table/table.css +++ b/server/src/assets/styles/_components/table/table.css @@ -19,7 +19,8 @@ } } -.app-table :where(th, td) { +.app-table th, +.app-table td { padding: calc(3 * var(--v)) calc(4 * var(--v)); } diff --git a/server/src/templates/components/header.njk b/server/src/templates/components/header.njk index 823d5041..79fe2384 100644 --- a/server/src/templates/components/header.njk +++ b/server/src/templates/components/header.njk @@ -1,25 +1,25 @@ {% import 'macros/icons.njk' as icons %}
      -
      - - {{ req.user.firstName|first|upper }} - -
      + + +
      diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk index b270df93..a05abc2a 100644 --- a/server/src/templates/components/nav.njk +++ b/server/src/templates/components/nav.njk @@ -4,14 +4,14 @@
      {% else %} - + {% endfor %} diff --git a/server/src/templates/pages/home.njk b/server/src/templates/pages/home.njk index fba9fe7d..7a9c754c 100644 --- a/server/src/templates/pages/home.njk +++ b/server/src/templates/pages/home.njk @@ -3,7 +3,5 @@ {% block main_class %}pc-container{% endblock %} {% block main %} -

      - {{ 'home-title'|trans({ user: req.user|fullName }) }} -

      +

      {{ 'home-title'|trans({ user: req.user|fullName }) }}

      {% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index 36546bce..e92538c5 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -5,10 +5,12 @@ common-edit = Modifier common-actions = Actions common-yes = Oui common-no = Non +common-table-empty = Aucun élément site-title = Permacoop header-profile = Mon compte +header-dropdown = Voir plus d'actions header-logout = Se déconnecter home-title = Bonjour, {$user} ! From 9bd5f8bc2abb13d706694e17e6db694d5944aef1 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Sat, 23 Sep 2023 00:53:21 +0200 Subject: [PATCH 24/49] Drop client/kit and client/proxy --- .github/workflows/ci.yml | 4 +- .scrutinizer.yml | 1 - client/kit/.env | 2 - client/kit/.eslintignore | 13 - client/kit/.eslintrc.cjs | 20 - client/kit/.gitignore | 11 - client/kit/.npmrc | 1 - client/kit/.prettierignore | 15 - client/kit/.prettierrc | 6 - client/kit/e2e/login.spec.ts | 34 - client/kit/package-lock.json | 11136 ---------------- client/kit/package.json | 63 - client/kit/playwright.config.ts | 15 - client/kit/src/app.css | 8 - client/kit/src/app.d.ts | 9 - client/kit/src/app.html | 14 - .../kit/src/components/RequiredMarker.svelte | 1 - .../kit/src/components/ServerErrors.spec.ts | 35 - client/kit/src/components/ServerErrors.svelte | 25 - .../kit/src/components/icons/ErrorIcon.svelte | 12 - .../kit/src/components/inputs/Button.svelte | 14 - .../kit/src/components/inputs/Input.spec.ts | 16 - client/kit/src/components/inputs/Input.svelte | 46 - client/kit/src/config.js | 4 - client/kit/src/lib/axios.ts | 33 - client/kit/src/lib/errors/normalizer.ts | 18 - client/kit/src/lib/i18n/fr.json | 345 - client/kit/src/lib/i18n/index.ts | 23 - client/kit/src/lib/navigation.ts | 10 - client/kit/src/lib/shortid.ts | 3 - client/kit/src/routes/+layout.ts | 14 - client/kit/src/routes/login/+page.svelte | 72 - .../images/icons/android-icon-144x144.png | Bin 9773 -> 0 bytes .../images/icons/android-icon-192x192.png | Bin 13736 -> 0 bytes .../images/icons/android-icon-36x36.png | Bin 2108 -> 0 bytes .../images/icons/android-icon-48x48.png | Bin 2721 -> 0 bytes .../images/icons/android-icon-72x72.png | Bin 4010 -> 0 bytes .../images/icons/android-icon-96x96.png | Bin 5712 -> 0 bytes client/kit/static/images/icons/favicon.ico | Bin 1150 -> 0 bytes client/kit/static/images/login-office.jpeg | Bin 37749 -> 0 bytes client/kit/static/images/logo.png | Bin 4743 -> 0 bytes client/kit/static/manifest.json | 46 - client/kit/svelte.config.js | 20 - client/kit/tailwind.config.cjs | 132 - client/kit/tsconfig.json | 13 - client/kit/vite.config.ts | 42 - client/kit/vitest.config.ts | 30 - client/proxy/index.cjs | 30 - client/proxy/package-lock.json | 1302 -- client/proxy/package.json | 13 - docs/dev.md | 12 +- prod/README.md | 2 + 52 files changed, 5 insertions(+), 13660 deletions(-) delete mode 100644 client/kit/.env delete mode 100644 client/kit/.eslintignore delete mode 100644 client/kit/.eslintrc.cjs delete mode 100644 client/kit/.gitignore delete mode 100644 client/kit/.npmrc delete mode 100644 client/kit/.prettierignore delete mode 100644 client/kit/.prettierrc delete mode 100644 client/kit/e2e/login.spec.ts delete mode 100644 client/kit/package-lock.json delete mode 100644 client/kit/package.json delete mode 100644 client/kit/playwright.config.ts delete mode 100644 client/kit/src/app.css delete mode 100644 client/kit/src/app.d.ts delete mode 100644 client/kit/src/app.html delete mode 100644 client/kit/src/components/RequiredMarker.svelte delete mode 100644 client/kit/src/components/ServerErrors.spec.ts delete mode 100644 client/kit/src/components/ServerErrors.svelte delete mode 100644 client/kit/src/components/icons/ErrorIcon.svelte delete mode 100644 client/kit/src/components/inputs/Button.svelte delete mode 100644 client/kit/src/components/inputs/Input.spec.ts delete mode 100644 client/kit/src/components/inputs/Input.svelte delete mode 100644 client/kit/src/config.js delete mode 100644 client/kit/src/lib/axios.ts delete mode 100644 client/kit/src/lib/errors/normalizer.ts delete mode 100644 client/kit/src/lib/i18n/fr.json delete mode 100644 client/kit/src/lib/i18n/index.ts delete mode 100644 client/kit/src/lib/navigation.ts delete mode 100644 client/kit/src/lib/shortid.ts delete mode 100644 client/kit/src/routes/+layout.ts delete mode 100644 client/kit/src/routes/login/+page.svelte delete mode 100644 client/kit/static/images/icons/android-icon-144x144.png delete mode 100644 client/kit/static/images/icons/android-icon-192x192.png delete mode 100644 client/kit/static/images/icons/android-icon-36x36.png delete mode 100644 client/kit/static/images/icons/android-icon-48x48.png delete mode 100644 client/kit/static/images/icons/android-icon-72x72.png delete mode 100644 client/kit/static/images/icons/android-icon-96x96.png delete mode 100644 client/kit/static/images/icons/favicon.ico delete mode 100644 client/kit/static/images/login-office.jpeg delete mode 100644 client/kit/static/images/logo.png delete mode 100644 client/kit/static/manifest.json delete mode 100644 client/kit/svelte.config.js delete mode 100644 client/kit/tailwind.config.cjs delete mode 100644 client/kit/tsconfig.json delete mode 100644 client/kit/vite.config.ts delete mode 100644 client/kit/vitest.config.ts delete mode 100644 client/proxy/index.cjs delete mode 100644 client/proxy/package-lock.json delete mode 100644 client/proxy/package.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 227e685b..eb461ef4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,12 +11,12 @@ jobs: with: node-version: 16 cache: 'npm' - cache-dependency-path: client/kit/package-lock.json + cache-dependency-path: server/package-lock.json - uses: actions/cache@v2 with: path: ~/.cache/ms-playwright - key: ${{ runner.os }}-node-${{ hashFiles('**/client/kit/package-lock.json') }} + key: ${{ runner.os }}-node-${{ hashFiles('**/server/package-lock.json') }} - name: Tests run: make ci diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 5cc278b9..1fd7e250 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -10,4 +10,3 @@ filter: excluded_paths: - 'client/legacy/static' - 'client/legacy/src/store' - - 'client/kit/static' diff --git a/client/kit/.env b/client/kit/.env deleted file mode 100644 index ccfa2a1d..00000000 --- a/client/kit/.env +++ /dev/null @@ -1,2 +0,0 @@ -VITE_CLIENT_API_URL=http://localhost:3000/api -VITE_CLIENT_API_URL_SSR=http://localhost:3000/api diff --git a/client/kit/.eslintignore b/client/kit/.eslintignore deleted file mode 100644 index 38972655..00000000 --- a/client/kit/.eslintignore +++ /dev/null @@ -1,13 +0,0 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock diff --git a/client/kit/.eslintrc.cjs b/client/kit/.eslintrc.cjs deleted file mode 100644 index 09dcc6a9..00000000 --- a/client/kit/.eslintrc.cjs +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - root: true, - parser: "@typescript-eslint/parser", - extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], - plugins: ["svelte3", "@typescript-eslint"], - ignorePatterns: ["*.cjs"], - overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }], - settings: { - "svelte3/typescript": () => require("typescript"), - }, - parserOptions: { - sourceType: "module", - ecmaVersion: 2020, - }, - env: { - browser: true, - es2017: true, - node: true, - }, -}; diff --git a/client/kit/.gitignore b/client/kit/.gitignore deleted file mode 100644 index 93b01414..00000000 --- a/client/kit/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env.local -.env.*.local -!.env.example -test-results -coverage/ -static/css/index.css diff --git a/client/kit/.npmrc b/client/kit/.npmrc deleted file mode 100644 index b6f27f13..00000000 --- a/client/kit/.npmrc +++ /dev/null @@ -1 +0,0 @@ -engine-strict=true diff --git a/client/kit/.prettierignore b/client/kit/.prettierignore deleted file mode 100644 index 6187ce4b..00000000 --- a/client/kit/.prettierignore +++ /dev/null @@ -1,15 +0,0 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example -test-results -coverage/ - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock diff --git a/client/kit/.prettierrc b/client/kit/.prettierrc deleted file mode 100644 index 337af691..00000000 --- a/client/kit/.prettierrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "printWidth": 100, - "plugins": ["prettier-plugin-svelte"], - "pluginSearchDirs": ["."], - "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] -} diff --git a/client/kit/e2e/login.spec.ts b/client/kit/e2e/login.spec.ts deleted file mode 100644 index 32c41749..00000000 --- a/client/kit/e2e/login.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { expect, test } from "@playwright/test"; - -test("/ redirects to /kit/login", async ({ page }) => { - await page.goto("/"); - expect(page).toHaveURL("/kit/login"); -}); - -test("/login redirects to /kit/login", async ({ page }) => { - await page.goto("/login"); - expect(page).toHaveURL("/kit/login"); -}); - -test("Login page has expected h1", async ({ page }) => { - await page.goto("/kit/login"); - expect(await page.textContent("h1")).toBe("Connexion"); -}); - -test("Logs in using form", async ({ page }) => { - await page.goto("/kit/login"); - - const emailField = page.getByLabel("Adresse email"); - expect(emailField).toHaveAttribute("required", ""); - await emailField.fill("john@doe.com"); - - const passwordField = page.getByLabel("Mot de passe"); - expect(passwordField).toHaveAttribute("required", ""); - await passwordField.fill("john"); - - const loginButton = page.getByText("Se connecter"); - await loginButton.click(); - - await page.getByText("Bonjour John Doe !").waitFor(); - expect(page).toHaveURL("/"); -}); diff --git a/client/kit/package-lock.json b/client/kit/package-lock.json deleted file mode 100644 index cab3e7df..00000000 --- a/client/kit/package-lock.json +++ /dev/null @@ -1,11136 +0,0 @@ -{ - "name": "client", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "client", - "version": "1.0.0", - "dependencies": { - "axios": "^1.1.3", - "js-cookie": "^3.0.1", - "shortid": "^2.2.16", - "sveltekit-i18n": "^2.2.2" - }, - "devDependencies": { - "@fullhuman/postcss-purgecss": "^5.0.0", - "@playwright/test": "^1.25.0", - "@sveltejs/adapter-node": "^1.0.0-next.98", - "@sveltejs/kit": "next", - "@tailwindcss/forms": "^0.5.3", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/svelte": "^3.2.2", - "@typescript-eslint/eslint-plugin": "^5.27.0", - "@typescript-eslint/parser": "^5.27.0", - "@vitest/coverage-c8": "^0.24.3", - "autoprefixer": "^10.4.13", - "color": "^4.2.3", - "cssnano": "^5.1.14", - "eslint": "^8.16.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-svelte3": "^4.0.0", - "jsdom": "^20.0.1", - "postcss": "^8.4.19", - "prettier": "^2.6.2", - "prettier-plugin-svelte": "^2.7.0", - "start-server-and-test": "^1.14.0", - "svelte": "^3.44.0", - "svelte-check": "^2.7.1", - "svelte-preprocess": "^4.10.6", - "tailwindcss": "^3.2.4", - "tslib": "^2.3.1", - "typescript": "^4.7.4", - "vite": "^3.2.7", - "vitest": "^0.24.3" - }, - "engines": { - "node": "16" - } - }, - "node_modules/@adobe/css-tools": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz", - "integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==", - "dev": true - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/runtime": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz", - "integrity": "sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@esbuild/android-arm": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.11.tgz", - "integrity": "sha512-PzMcQLazLBkwDEkrNPi9AbjFt6+3I7HKbiYF2XtWQ7wItrHvEOeO3T8Am434zAozWtVP7lrTue1bEfc2nYWeCA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.11.tgz", - "integrity": "sha512-geWp637tUhNmhL3Xgy4Bj703yXB9dqiLJe05lCUfjSFDrQf9C/8pArusyPUbUbPwlC/EAUjBw32sxuIl/11dZw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@fullhuman/postcss-purgecss": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-5.0.0.tgz", - "integrity": "sha512-onDS/b/2pMRzqSoj4qOs2tYFmOpaspjTAgvACIHMPiicu1ptajiBruTrjBzTKdxWdX0ldaBb7wj8nEaTLyFkJw==", - "dev": true, - "dependencies": { - "purgecss": "^5.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.2.0.tgz", - "integrity": "sha512-nz2IDF7nb1qmj9hx8Ja3MFab2q9Ml8QbOaaeJNyX5JQJHU8QUvEDiMctmhGEkk3Kzr8w8vAqz4hPk/ogJSrUhg==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.2.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/schemas": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", - "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.24.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.2.0.tgz", - "integrity": "sha512-mfgpQz4Z2xGo37m6KD8xEpKelaVzvYVRijmLPePn9pxgaPEtX+SqIyPNzzoeCPXKYbB4L/wYSgXDL8o3Gop78Q==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@playwright/test": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.1.tgz", - "integrity": "sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A==", - "dev": true, - "dependencies": { - "@types/node": "*", - "playwright-core": "1.27.1" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "23.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.0.tgz", - "integrity": "sha512-JbrTRyDNtLQj/rhl7RFUuYXwQ2fac+33oLDAu2k++WD95zweyo28UAomLVA0JMGx4vmCa7Nw4T6k/1F6lelExg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.2.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "glob": "^8.0.3", - "is-reference": "1.2.1", - "magic-string": "^0.26.4" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@rollup/plugin-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-5.0.0.tgz", - "integrity": "sha512-LsWDA5wJs/ggzakVuKQhZo7HPRcQZgBa3jWIVxQSFxaRToUGNi8ZBh3+k/gQ+1eInVYJgn4WBRCUkmoDrmmGzw==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.2.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.0.tgz", - "integrity": "sha512-iwJbzfTzlzDDQcGmkS7EkCKwe2kSkdBrjX87Fy/KrNjr6UNnLpod0t6X66e502LRe5JJCA4FFqrEscWPnZAkig==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.2.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-builtin-module": "^3.2.0", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.24.46", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.46.tgz", - "integrity": "sha512-ng4ut1z2MCBhK/NwDVwIQp3pAUOCs/KNaW3cBxdFB2xTDrOuo1xuNmpr/9HHFhxqIvHrs1NTH3KJg6q+JSy1Kw==", - "dev": true - }, - "node_modules/@sveltejs/adapter-node": { - "version": "1.0.0-next.98", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.98.tgz", - "integrity": "sha512-eo89sswzm3ntZJgaQzz2MneqMqBfQWQj6b8VtImlHeq2AB+RSodippmKY0RyPcIJ0hJqdDc4DubU7XMDKkoTew==", - "dev": true, - "dependencies": { - "@rollup/plugin-commonjs": "^23.0.0", - "@rollup/plugin-json": "^5.0.0", - "@rollup/plugin-node-resolve": "^15.0.0", - "rollup": "^2.78.1" - } - }, - "node_modules/@sveltejs/kit": { - "version": "1.0.0-next.516", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.516.tgz", - "integrity": "sha512-n0oGcv7xpgJ81ld1oER5HVREP4TdeDUJ8S64XNDcl3Y2xfQLKk8C4SLYQw2D6V+DxUm8V3aRrj7N7/tm4CQm6A==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@sveltejs/vite-plugin-svelte": "^1.0.5", - "@types/cookie": "^0.5.1", - "cookie": "^0.5.0", - "devalue": "^4.0.0", - "kleur": "^4.1.4", - "magic-string": "^0.26.2", - "mime": "^3.0.0", - "sade": "^1.8.1", - "set-cookie-parser": "^2.4.8", - "sirv": "^2.0.2", - "tiny-glob": "^0.2.9", - "undici": "^5.11.0" - }, - "bin": { - "svelte-kit": "svelte-kit.js" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "svelte": "^3.44.0", - "vite": "^3.1.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.9.tgz", - "integrity": "sha512-+SDrAnT7TDi8sdj4OfD2SC4s9DNrpNVBrue8fT2PmKks9Ddu0JIfSeX91wXZb/1xHz4EkGb+rli8GTRI0yGOjg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.2.1", - "debug": "^4.3.4", - "deepmerge": "^4.2.2", - "kleur": "^4.1.5", - "magic-string": "^0.26.5", - "svelte-hmr": "^0.15.0" - }, - "engines": { - "node": "^14.18.0 || >= 16" - }, - "peerDependencies": { - "diff-match-patch": "^1.0.5", - "svelte": "^3.44.0", - "vite": "^3.0.0" - }, - "peerDependenciesMeta": { - "diff-match-patch": { - "optional": true - } - } - }, - "node_modules/@sveltekit-i18n/base": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@sveltekit-i18n/base/-/base-1.2.1.tgz", - "integrity": "sha512-F8gqG2+KAOeT0o2wYlUrW3TRCX7zaD7rBy/1CEVNw0irfw9TgFf/ODmhubkHHT3+6Zk+SMz8RNgeuffBfAMbJw==", - "optionalDependencies": { - "@sveltekit-i18n/parser-default": "^1.x" - }, - "peerDependencies": { - "svelte": "^3.x" - } - }, - "node_modules/@sveltekit-i18n/parser-default": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@sveltekit-i18n/parser-default/-/parser-default-1.0.3.tgz", - "integrity": "sha512-HheveklTjp3hxpYQhoHfyA6B4bQaUeSV5MQf2usIv/58UF2jY/YqhCAWj9bDBjufbuZc5pSz4BXvdX3WVT+viA==" - }, - "node_modules/@tailwindcss/forms": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz", - "integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==", - "dev": true, - "dependencies": { - "mini-svg-data-uri": "^1.2.3" - }, - "peerDependencies": { - "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" - } - }, - "node_modules/@testing-library/dom": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz", - "integrity": "sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^4.2.0", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.4.4", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", - "dev": true, - "dependencies": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=8", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/svelte": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@testing-library/svelte/-/svelte-3.2.2.tgz", - "integrity": "sha512-IKwZgqbekC3LpoRhSwhd0JswRGxKdAGkf39UiDXTywK61YyLXbCYoR831e/UUC6EeNW4hiHPY+2WuovxOgI5sw==", - "dev": true, - "dependencies": { - "@testing-library/dom": "^8.1.0" - }, - "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "svelte": "3.x" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", - "dev": true - }, - "node_modules/@types/chai": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", - "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", - "dev": true - }, - "node_modules/@types/chai-subset": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", - "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", - "dev": true, - "dependencies": { - "@types/chai": "*" - } - }, - "node_modules/@types/cookie": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.1.tgz", - "integrity": "sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==", - "dev": true - }, - "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.1.2.tgz", - "integrity": "sha512-y+nlX0h87U0R+wsGn6EBuoRWYyv3KFtwRNP3QWp9+k2tJ2/bqcGS3UxD7jgT+tiwJWWq3UsyV4Y+T6rsMT4XMg==", - "dev": true, - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@types/jest/node_modules/pretty-format": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.0.tgz", - "integrity": "sha512-QCSUFdwOi924g24czhOH5eTkXxUCqlLGZBRCySlwDYHIXRJkdGyjJc9nZaqhlFBZws8dq5Dvk0lCilsmlfsPxw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@types/jest/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.11.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz", - "integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==", - "dev": true - }, - "node_modules/@types/pug": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz", - "integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==", - "dev": true - }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true - }, - "node_modules/@types/sass": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz", - "integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/testing-library__jest-dom": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", - "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", - "dev": true, - "dependencies": { - "@types/jest": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", - "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.0.tgz", - "integrity": "sha512-FIBZgS3DVJgqPwJzvZTuH4HNsZhHMa9SjxTKAZTlMsPw/UzpEjcf9f4dfgDJEHjK+HboUJo123Eshl6niwEm/Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.40.0", - "@typescript-eslint/type-utils": "5.40.0", - "@typescript-eslint/utils": "5.40.0", - "debug": "^4.3.4", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.0.tgz", - "integrity": "sha512-Ah5gqyX2ySkiuYeOIDg7ap51/b63QgWZA7w6AHtFrag7aH0lRQPbLzUjk0c9o5/KZ6JRkTTDKShL4AUrQa6/hw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.40.0", - "@typescript-eslint/types": "5.40.0", - "@typescript-eslint/typescript-estree": "5.40.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.0.tgz", - "integrity": "sha512-d3nPmjUeZtEWRvyReMI4I1MwPGC63E8pDoHy0BnrYjnJgilBD3hv7XOiETKLY/zTwI7kCnBDf2vWTRUVpYw0Uw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.40.0", - "@typescript-eslint/visitor-keys": "5.40.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.0.tgz", - "integrity": "sha512-nfuSdKEZY2TpnPz5covjJqav+g5qeBqwSHKBvz7Vm1SAfy93SwKk/JeSTymruDGItTwNijSsno5LhOHRS1pcfw==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.40.0", - "@typescript-eslint/utils": "5.40.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.0.tgz", - "integrity": "sha512-V1KdQRTXsYpf1Y1fXCeZ+uhjW48Niiw0VGt4V8yzuaDTU8Z1Xl7yQDyQNqyAFcVhpYXIVCEuxSIWTsLDpHgTbw==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.0.tgz", - "integrity": "sha512-b0GYlDj8TLTOqwX7EGbw2gL5EXS2CPEWhF9nGJiGmEcmlpNBjyHsTwbqpyIEPVpl6br4UcBOYlcI2FJVtJkYhg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.40.0", - "@typescript-eslint/visitor-keys": "5.40.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.0.tgz", - "integrity": "sha512-MO0y3T5BQ5+tkkuYZJBjePewsY+cQnfkYeRqS6tPh28niiIwPnQ1t59CSRcs1ZwJJNOdWw7rv9pF8aP58IMihA==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.40.0", - "@typescript-eslint/types": "5.40.0", - "@typescript-eslint/typescript-estree": "5.40.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.0.tgz", - "integrity": "sha512-ijJ+6yig+x9XplEpG2K6FUdJeQGGj/15U3S56W9IqXKJqleuD7zJ2AX/miLezwxpd7ZxDAqO87zWufKg+RPZyQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.40.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@vitest/coverage-c8": { - "version": "0.24.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.24.3.tgz", - "integrity": "sha512-tAmMyHxWYnAwGeJb7QgTuEX8aLasTg4X1/6INobXa/7wYGEJ28CACFO5iLn1HzFVPoLvhsS3luQjiflGjjSMRQ==", - "dev": true, - "dependencies": { - "c8": "^7.12.0", - "vitest": "0.24.3" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "dev": true, - "dependencies": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dev": true, - "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "node_modules/acorn-node/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-node/node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/aria-query": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", - "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/autoprefixer": { - "version": "10.4.13", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", - "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001426", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/axios": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz", - "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dev": true, - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/c8": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", - "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.1.4", - "rimraf": "^3.0.2", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001434", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz", - "integrity": "sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ci-info": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", - "dev": true - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "dev": true, - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-declaration-sorter": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz", - "integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.14.tgz", - "integrity": "sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==", - "dev": true, - "dependencies": { - "cssnano-preset-default": "^5.2.13", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-default": { - "version": "5.2.13", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz", - "integrity": "sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.0", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.3", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.1", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", - "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==", - "dev": true - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defined": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", - "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/detective": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", - "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", - "dev": true, - "dependencies": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "detective": "bin/detective.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/devalue": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.0.0.tgz", - "integrity": "sha512-w25siwXyuMUqMr7jPlEjyNCp1vn0Jzj/fNg3qVt/r/Dpe8HjESh2V92L0jmh3uq4iJt0BvjH+Azk1pQzkcnDWA==", - "dev": true - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "node_modules/diff-sequences": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.2.0.tgz", - "integrity": "sha512-413SY5JpYeSBZxmenGEmCVQ8mCgtFJF0w9PROdaS6z987XC2Pd2GOKqOITLtMftmyFZqgtCOb/QA7/Z3ZXfzIw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-accessibility-api": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz", - "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", - "dev": true - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", - "dev": true - }, - "node_modules/esbuild": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.11.tgz", - "integrity": "sha512-OgHGuhlfZ//mToxjte1D5iiiQgWfJ2GByVMwEC/IuoXsBGkuyK1+KrjYu0laSpnN/L1UmLUCv0s25vObdc1bVg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.15.11", - "@esbuild/linux-loong64": "0.15.11", - "esbuild-android-64": "0.15.11", - "esbuild-android-arm64": "0.15.11", - "esbuild-darwin-64": "0.15.11", - "esbuild-darwin-arm64": "0.15.11", - "esbuild-freebsd-64": "0.15.11", - "esbuild-freebsd-arm64": "0.15.11", - "esbuild-linux-32": "0.15.11", - "esbuild-linux-64": "0.15.11", - "esbuild-linux-arm": "0.15.11", - "esbuild-linux-arm64": "0.15.11", - "esbuild-linux-mips64le": "0.15.11", - "esbuild-linux-ppc64le": "0.15.11", - "esbuild-linux-riscv64": "0.15.11", - "esbuild-linux-s390x": "0.15.11", - "esbuild-netbsd-64": "0.15.11", - "esbuild-openbsd-64": "0.15.11", - "esbuild-sunos-64": "0.15.11", - "esbuild-windows-32": "0.15.11", - "esbuild-windows-64": "0.15.11", - "esbuild-windows-arm64": "0.15.11" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.11.tgz", - "integrity": "sha512-rrwoXEiuI1kaw4k475NJpexs8GfJqQUKcD08VR8sKHmuW9RUuTR2VxcupVvHdiGh9ihxL9m3lpqB1kju92Ialw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.11.tgz", - "integrity": "sha512-/hDubOg7BHOhUUsT8KUIU7GfZm5bihqssvqK5PfO4apag7YuObZRZSzViyEKcFn2tPeHx7RKbSBXvAopSHDZJQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.11.tgz", - "integrity": "sha512-1DqHD0ms3AhiwkKnjRUzmiW7JnaJJr5FKrPiR7xuyMwnjDqvNWDdMq4rKSD9OC0piFNK6n0LghsglNMe2MwJtA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.11.tgz", - "integrity": "sha512-OMzhxSbS0lwwrW40HHjRCeVIJTURdXFA8c3GU30MlHKuPCcvWNUIKVucVBtNpJySXmbkQMDJdJNrXzNDyvoqvQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.11.tgz", - "integrity": "sha512-8dKP26r0/Qyez8nTCwpq60QbuYKOeBygdgOAWGCRalunyeqWRoSZj9TQjPDnTTI9joxd3QYw3UhVZTKxO9QdRg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.11.tgz", - "integrity": "sha512-aSGiODiukLGGnSg/O9+cGO2QxEacrdCtCawehkWYTt5VX1ni2b9KoxpHCT9h9Y6wGqNHmXFnB47RRJ8BIqZgmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.11.tgz", - "integrity": "sha512-lsrAfdyJBGx+6aHIQmgqUonEzKYeBnyfJPkT6N2dOf1RoXYYV1BkWB6G02tjsrz1d5wZzaTc3cF+TKmuTo/ZwA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.11.tgz", - "integrity": "sha512-Y2Rh+PcyVhQqXKBTacPCltINN3uIw2xC+dsvLANJ1SpK5NJUtxv8+rqWpjmBgaNWKQT1/uGpMmA9olALy9PLVA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.11.tgz", - "integrity": "sha512-TJllTVk5aSyqPFvvcHTvf6Wu1ZKhWpJ/qNmZO8LL/XeB+LXCclm7HQHNEIz6MT7IX8PmlC1BZYrOiw2sXSB95A==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.11.tgz", - "integrity": "sha512-uhcXiTwTmD4OpxJu3xC5TzAAw6Wzf9O1XGWL448EE9bqGjgV1j+oK3lIHAfsHnuIn8K4nDW8yjX0Sv5S++oRuw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.11.tgz", - "integrity": "sha512-WD61y/R1M4BLe4gxXRypoQ0Ci+Vjf714QYzcPNkiYv5I8K8WDz2ZR8Bm6cqKxd6rD+e/rZgPDbhQ9PCf7TMHmA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.11.tgz", - "integrity": "sha512-JVleZS9oPVLTlBhPTWgOwxFWU/wMUdlBwTbGA4GF8c38sLbS13cupj+C8bLq929jU7EMWry4SaL+tKGIaTlqKg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.11.tgz", - "integrity": "sha512-9aLIalZ2HFHIOZpmVU11sEAS9F8TnHw49daEjcgMpBXHFF57VuT9f9/9LKJhw781Gda0P9jDkuCWJ0tFbErvJw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.11.tgz", - "integrity": "sha512-sZHtiXXOKsLI3XGBGoYO4qKBzJlb8xNsWmvFiwFMHFzA4AXgDP1KDp7Dawe9C2pavTRBDvl+Ok4n/DHQ59oaTg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.11.tgz", - "integrity": "sha512-hUC9yN06K9sg7ju4Vgu9ChAPdsEgtcrcLfyNT5IKwKyfpLvKUwCMZSdF+gRD3WpyZelgTQfJ+pDx5XFbXTlB0A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.11.tgz", - "integrity": "sha512-0bBo9SQR4t66Wd91LGMAqmWorzO0TTzVjYiifwoFtel8luFeXuPThQnEm5ztN4g0fnvcp7AnUPPzS/Depf17wQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.11.tgz", - "integrity": "sha512-EuBdTGlsMTjEl1sQnBX2jfygy7iR6CKfvOzi+gEOfhDqbHXsmY1dcpbVtcwHAg9/2yUZSfMJHMAgf1z8M4yyyw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.11.tgz", - "integrity": "sha512-O0/Wo1Wk6dc0rZSxkvGpmTNIycEznHmkObTFz2VHBhjPsO4ZpCgfGxNkCpz4AdAIeMczpTXt/8d5vdJNKEGC+Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.11.tgz", - "integrity": "sha512-x977Q4HhNjnHx00b4XLAnTtj5vfbdEvkxaQwC1Zh5AN8g5EX+izgZ6e5QgqJgpzyRNJqh4hkgIJF1pyy1be0mQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.11.tgz", - "integrity": "sha512-VwUHFACuBahrvntdcMKZteUZ9HaYrBRODoKe4tIWxguQRvvYoYb7iu5LrcRS/FQx8KPZNaa72zuqwVtHeXsITw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", - "@humanwhocodes/module-importer": "^1.0.1", - "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.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-svelte3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-4.0.0.tgz", - "integrity": "sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==", - "dev": true, - "peerDependencies": { - "eslint": ">=8.0.0", - "svelte": "^3.2.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/expect": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.2.0.tgz", - "integrity": "sha512-03ClF3GWwUqd9Grgkr9ZSdaCJGMRA69PQ8jT7o+Bx100VlGiAFf9/8oIm9Qve7ZVJhuJxFftqFhviZJRxxNfvg==", - "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.2.0", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.2.0", - "jest-message-util": "^29.2.0", - "jest-util": "^29.2.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", - "dev": true - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-builtin-module": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz", - "integrity": "sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==", - "dev": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.2.0.tgz", - "integrity": "sha512-GsH07qQL+/D/GxlnU+sSg9GL3fBOcuTlmtr3qr2pnkiODCwubNN2/7slW4m3CvxDsEus/VEOfQKRFLyXsUlnZw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.2.0", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.2.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/pretty-format": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.0.tgz", - "integrity": "sha512-QCSUFdwOi924g24czhOH5eTkXxUCqlLGZBRCySlwDYHIXRJkdGyjJc9nZaqhlFBZws8dq5Dvk0lCilsmlfsPxw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-diff/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.2.0.tgz", - "integrity": "sha512-FcEfKZ4vm28yCdBsvC69EkrEhcfex+IYlRctNJXsRG9+WC3WxgBNORnECIgqUtj7o/h1d8o7xB/dFUiLi4bqtw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.2.0", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.2.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.0.tgz", - "integrity": "sha512-QCSUFdwOi924g24czhOH5eTkXxUCqlLGZBRCySlwDYHIXRJkdGyjJc9nZaqhlFBZws8dq5Dvk0lCilsmlfsPxw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "node_modules/jest-message-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.2.0.tgz", - "integrity": "sha512-arBfk5yMFMTnMB22GyG601xGSGthA02vWSewPaxoFo0F9wBqDOyxccPbCcYu8uibw3kduSHXdCOd1PsLSgdomg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.2.0", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.2.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.0.tgz", - "integrity": "sha512-QCSUFdwOi924g24czhOH5eTkXxUCqlLGZBRCySlwDYHIXRJkdGyjJc9nZaqhlFBZws8dq5Dvk0lCilsmlfsPxw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "node_modules/jest-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.2.0.tgz", - "integrity": "sha512-8M1dx12ujkBbnhwytrezWY0Ut79hbflwodE+qZKjxSRz5qt4xDp6dQQJaOCFvCmE0QJqp9KyEK33lpPNjnhevw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.2.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/joi": { - "version": "17.6.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.3.tgz", - "integrity": "sha512-YlQsIaS9MHYekzf1Qe11LjTkNzx9qhYluK3172z38RxYoAUf82XMX1p1DG1H4Wtk2ED/vPdSn9OggqtDu+aTow==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/js-cookie": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", - "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "acorn": "^8.8.0", - "acorn-globals": "^7.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.2", - "decimal.js": "^10.4.1", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.2", - "parse5": "^7.1.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^3.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0", - "ws": "^8.9.0", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", - "dev": true, - "engines": { - "node": "> 0.8" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", - "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/local-pkg": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.2.tgz", - "integrity": "sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lz-string": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", - "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", - "dev": true, - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/magic-string": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", - "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", - "dev": true - }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mini-svg-data-uri": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", - "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", - "dev": true, - "bin": { - "mini-svg-data-uri": "cli.js" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mrmime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", - "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/nwsapi": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", - "dev": true - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "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" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse5": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", - "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dev": true, - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/playwright-core": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.1.tgz", - "integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==", - "dev": true, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/postcss": { - "version": "8.4.19", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", - "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-colormin": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", - "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-import": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", - "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", - "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", - "dev": true, - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.3.3" - } - }, - "node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dev": true, - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-merge-rules": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz", - "integrity": "sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dev": true, - "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-nested": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", - "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dev": true, - "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", - "dev": true, - "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz", - "integrity": "sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-plugin-svelte": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-2.8.0.tgz", - "integrity": "sha512-QlXv/U3bUszks3XYDPsk1fsaQC+fo2lshwKbcbO+lrSVdJ+40mB1BfL8OCAk1W9y4pJxpqO/4gqm6NtF3zNGCw==", - "dev": true, - "peerDependencies": { - "prettier": "^1.16.4 || ^2.0.0", - "svelte": "^3.2.0" - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "dev": true, - "dependencies": { - "event-stream": "=3.3.4" - }, - "bin": { - "ps-tree": "bin/ps-tree.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/purgecss": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-5.0.0.tgz", - "integrity": "sha512-RAnuxrGuVyLLTr8uMbKaxDRGWMgK5CCYDfRyUNNcaz5P3kGgD2b7ymQGYEyo2ST7Tl/ScwFgf5l3slKMxHSbrw==", - "dev": true, - "dependencies": { - "commander": "^9.0.0", - "glob": "^8.0.3", - "postcss": "^8.4.4", - "postcss-selector-parser": "^6.0.7" - }, - "bin": { - "purgecss": "bin/purgecss.js" - } - }, - "node_modules/purgecss/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/purgecss/node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/purgecss/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.10", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz", - "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==", - "dev": true - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sander": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", - "integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==", - "dev": true, - "dependencies": { - "es6-promise": "^3.1.2", - "graceful-fs": "^4.1.3", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.2" - } - }, - "node_modules/sander/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, - "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz", - "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shortid": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", - "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", - "dependencies": { - "nanoid": "^2.1.0" - } - }, - "node_modules/shortid/node_modules/nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/sirv": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.2.tgz", - "integrity": "sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sorcery": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", - "integrity": "sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==", - "dev": true, - "dependencies": { - "buffer-crc32": "^0.2.5", - "minimist": "^1.2.0", - "sander": "^0.5.0", - "sourcemap-codec": "^1.3.0" - }, - "bin": { - "sorcery": "bin/index.js" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/start-server-and-test": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.14.0.tgz", - "integrity": "sha512-on5ELuxO2K0t8EmNj9MtVlFqwBMxfWOhu4U7uZD1xccVpFlOQKR93CSe0u98iQzfNxRyaNTb/CdadbNllplTsw==", - "dev": true, - "dependencies": { - "bluebird": "3.7.2", - "check-more-types": "2.24.0", - "debug": "4.3.2", - "execa": "5.1.1", - "lazy-ass": "1.6.0", - "ps-tree": "1.2.0", - "wait-on": "6.0.0" - }, - "bin": { - "server-test": "src/bin/start.js", - "start-server-and-test": "src/bin/start.js", - "start-test": "src/bin/start.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/start-server-and-test/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-literal": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-0.4.2.tgz", - "integrity": "sha512-pv48ybn4iE1O9RLgCAN0iU4Xv7RlBTiit6DKmMiErbs9x1wH6vXBs45tWc0H5wUIF6TLTrKweqkmYF/iraQKNw==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svelte": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.52.0.tgz", - "integrity": "sha512-FxcnEUOAVfr10vDU5dVgJN19IvqeHQCS1zfe8vayTfis9A2t5Fhx+JDe5uv/C3j//bB1umpLJ6quhgs9xyUbCQ==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/svelte-check": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.9.2.tgz", - "integrity": "sha512-DRi8HhnCiqiGR2YF9ervPGvtoYrheE09cXieCTEqeTPOTJzfoa54Py8rovIBv4bH4n5HgZYIyTQ3DDLHQLl2uQ==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.9", - "chokidar": "^3.4.1", - "fast-glob": "^3.2.7", - "import-fresh": "^3.2.1", - "picocolors": "^1.0.0", - "sade": "^1.7.4", - "svelte-preprocess": "^4.0.0", - "typescript": "*" - }, - "bin": { - "svelte-check": "bin/svelte-check" - }, - "peerDependencies": { - "svelte": "^3.24.0" - } - }, - "node_modules/svelte-hmr": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.0.tgz", - "integrity": "sha512-Aw21SsyoohyVn4yiKXWPNCSW2DQNH/76kvUnE9kpt4h9hcg9tfyQc6xshx9hzgMfGF0kVx0EGD8oBMWSnATeOg==", - "dev": true, - "engines": { - "node": "^12.20 || ^14.13.1 || >= 16" - }, - "peerDependencies": { - "svelte": ">=3.19.0" - } - }, - "node_modules/svelte-preprocess": { - "version": "4.10.7", - "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz", - "integrity": "sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@types/pug": "^2.0.4", - "@types/sass": "^1.16.0", - "detect-indent": "^6.0.0", - "magic-string": "^0.25.7", - "sorcery": "^0.10.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">= 9.11.2" - }, - "peerDependencies": { - "@babel/core": "^7.10.2", - "coffeescript": "^2.5.1", - "less": "^3.11.3 || ^4.0.0", - "postcss": "^7 || ^8", - "postcss-load-config": "^2.1.0 || ^3.0.0 || ^4.0.0", - "pug": "^3.0.0", - "sass": "^1.26.8", - "stylus": "^0.55.0", - "sugarss": "^2.0.0", - "svelte": "^3.23.0", - "typescript": "^3.9.5 || ^4.0.0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "coffeescript": { - "optional": true - }, - "less": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "postcss": { - "optional": true - }, - "postcss-load-config": { - "optional": true - }, - "pug": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/svelte-preprocess/node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/sveltekit-i18n": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/sveltekit-i18n/-/sveltekit-i18n-2.2.2.tgz", - "integrity": "sha512-6eygICleGCSL7elY7A3trF8XUhV+mlW56ZSoD0UUKXlw+Y6u0MTTHDq48u1LyY73SfnlbPHXgTarhTjZ0BvUKA==", - "dependencies": { - "@sveltekit-i18n/base": "1.2.1", - "@sveltekit-i18n/parser-default": "1.0.3" - }, - "peerDependencies": { - "svelte": "^3.x" - } - }, - "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "node_modules/tailwindcss": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", - "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", - "dev": true, - "dependencies": { - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.1", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "lilconfig": "^2.0.6", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.18", - "postcss-import": "^14.1.0", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "6.0.0", - "postcss-selector-parser": "^6.0.10", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.1" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/tiny-glob": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", - "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", - "dev": true, - "dependencies": { - "globalyzer": "0.1.0", - "globrex": "^0.1.2" - } - }, - "node_modules/tinybench": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.0.tgz", - "integrity": "sha512-zs1gMVBwyyG2QbVchYIbnabRhMOCGvrwZz/q+SV+LIMa9q5YDQZi2kkI6ZRqV2Bz7ba1uvrc7ieUoE4KWnGeKg==", - "dev": true - }, - "node_modules/tinypool": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.0.tgz", - "integrity": "sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-1.0.2.tgz", - "integrity": "sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/totalist": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz", - "integrity": "sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "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==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/undici": { - "version": "5.21.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.21.0.tgz", - "integrity": "sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA==", - "dev": true, - "dependencies": { - "busboy": "^1.6.0" - }, - "engines": { - "node": ">=12.18" - } - }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/vite": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.7.tgz", - "integrity": "sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==", - "dev": true, - "dependencies": { - "esbuild": "^0.15.9", - "postcss": "^8.4.18", - "resolve": "^1.22.1", - "rollup": "^2.79.1" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vitest": { - "version": "0.24.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.3.tgz", - "integrity": "sha512-aM0auuPPgMSstWvr851hB74g/LKaKBzSxcG3da7ejfZbx08Y21JpZmbmDYrMTCGhVZKqTGwzcnLMwyfz2WzkhQ==", - "dev": true, - "dependencies": { - "@types/chai": "^4.3.3", - "@types/chai-subset": "^1.3.3", - "@types/node": "*", - "chai": "^4.3.6", - "debug": "^4.3.4", - "local-pkg": "^0.4.2", - "strip-literal": "^0.4.2", - "tinybench": "^2.3.0", - "tinypool": "^0.3.0", - "tinyspy": "^1.0.2", - "vite": "^3.0.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": ">=v14.16.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@vitest/browser": "*", - "@vitest/ui": "*", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/w3c-xmlserializer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", - "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", - "dev": true, - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/wait-on": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.0.tgz", - "integrity": "sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw==", - "dev": true, - "dependencies": { - "axios": "^0.21.1", - "joi": "^17.4.0", - "lodash": "^4.17.21", - "minimist": "^1.2.5", - "rxjs": "^7.1.0" - }, - "bin": { - "wait-on": "bin/wait-on" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/wait-on/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", - "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@adobe/css-tools": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz", - "integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==", - "dev": true - }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/runtime": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz", - "integrity": "sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@esbuild/android-arm": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.11.tgz", - "integrity": "sha512-PzMcQLazLBkwDEkrNPi9AbjFt6+3I7HKbiYF2XtWQ7wItrHvEOeO3T8Am434zAozWtVP7lrTue1bEfc2nYWeCA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.11.tgz", - "integrity": "sha512-geWp637tUhNmhL3Xgy4Bj703yXB9dqiLJe05lCUfjSFDrQf9C/8pArusyPUbUbPwlC/EAUjBw32sxuIl/11dZw==", - "dev": true, - "optional": true - }, - "@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@fullhuman/postcss-purgecss": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-5.0.0.tgz", - "integrity": "sha512-onDS/b/2pMRzqSoj4qOs2tYFmOpaspjTAgvACIHMPiicu1ptajiBruTrjBzTKdxWdX0ldaBb7wj8nEaTLyFkJw==", - "dev": true, - "requires": { - "purgecss": "^5.0.0" - } - }, - "@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true - }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/expect-utils": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.2.0.tgz", - "integrity": "sha512-nz2IDF7nb1qmj9hx8Ja3MFab2q9Ml8QbOaaeJNyX5JQJHU8QUvEDiMctmhGEkk3Kzr8w8vAqz4hPk/ogJSrUhg==", - "dev": true, - "requires": { - "jest-get-type": "^29.2.0" - } - }, - "@jest/schemas": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", - "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.24.1" - } - }, - "@jest/types": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.2.0.tgz", - "integrity": "sha512-mfgpQz4Z2xGo37m6KD8xEpKelaVzvYVRijmLPePn9pxgaPEtX+SqIyPNzzoeCPXKYbB4L/wYSgXDL8o3Gop78Q==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@playwright/test": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.1.tgz", - "integrity": "sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A==", - "dev": true, - "requires": { - "@types/node": "*", - "playwright-core": "1.27.1" - } - }, - "@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "@rollup/plugin-commonjs": { - "version": "23.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.0.tgz", - "integrity": "sha512-JbrTRyDNtLQj/rhl7RFUuYXwQ2fac+33oLDAu2k++WD95zweyo28UAomLVA0JMGx4vmCa7Nw4T6k/1F6lelExg==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^4.2.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "glob": "^8.0.3", - "is-reference": "1.2.1", - "magic-string": "^0.26.4" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@rollup/plugin-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-5.0.0.tgz", - "integrity": "sha512-LsWDA5wJs/ggzakVuKQhZo7HPRcQZgBa3jWIVxQSFxaRToUGNi8ZBh3+k/gQ+1eInVYJgn4WBRCUkmoDrmmGzw==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^4.2.1" - } - }, - "@rollup/plugin-node-resolve": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.0.tgz", - "integrity": "sha512-iwJbzfTzlzDDQcGmkS7EkCKwe2kSkdBrjX87Fy/KrNjr6UNnLpod0t6X66e502LRe5JJCA4FFqrEscWPnZAkig==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^4.2.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-builtin-module": "^3.2.0", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - } - }, - "@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "requires": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - } - }, - "@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "@sinclair/typebox": { - "version": "0.24.46", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.46.tgz", - "integrity": "sha512-ng4ut1z2MCBhK/NwDVwIQp3pAUOCs/KNaW3cBxdFB2xTDrOuo1xuNmpr/9HHFhxqIvHrs1NTH3KJg6q+JSy1Kw==", - "dev": true - }, - "@sveltejs/adapter-node": { - "version": "1.0.0-next.98", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.98.tgz", - "integrity": "sha512-eo89sswzm3ntZJgaQzz2MneqMqBfQWQj6b8VtImlHeq2AB+RSodippmKY0RyPcIJ0hJqdDc4DubU7XMDKkoTew==", - "dev": true, - "requires": { - "@rollup/plugin-commonjs": "^23.0.0", - "@rollup/plugin-json": "^5.0.0", - "@rollup/plugin-node-resolve": "^15.0.0", - "rollup": "^2.78.1" - } - }, - "@sveltejs/kit": { - "version": "1.0.0-next.516", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.516.tgz", - "integrity": "sha512-n0oGcv7xpgJ81ld1oER5HVREP4TdeDUJ8S64XNDcl3Y2xfQLKk8C4SLYQw2D6V+DxUm8V3aRrj7N7/tm4CQm6A==", - "dev": true, - "requires": { - "@sveltejs/vite-plugin-svelte": "^1.0.5", - "@types/cookie": "^0.5.1", - "cookie": "^0.5.0", - "devalue": "^4.0.0", - "kleur": "^4.1.4", - "magic-string": "^0.26.2", - "mime": "^3.0.0", - "sade": "^1.8.1", - "set-cookie-parser": "^2.4.8", - "sirv": "^2.0.2", - "tiny-glob": "^0.2.9", - "undici": "^5.11.0" - } - }, - "@sveltejs/vite-plugin-svelte": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.9.tgz", - "integrity": "sha512-+SDrAnT7TDi8sdj4OfD2SC4s9DNrpNVBrue8fT2PmKks9Ddu0JIfSeX91wXZb/1xHz4EkGb+rli8GTRI0yGOjg==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^4.2.1", - "debug": "^4.3.4", - "deepmerge": "^4.2.2", - "kleur": "^4.1.5", - "magic-string": "^0.26.5", - "svelte-hmr": "^0.15.0" - } - }, - "@sveltekit-i18n/base": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@sveltekit-i18n/base/-/base-1.2.1.tgz", - "integrity": "sha512-F8gqG2+KAOeT0o2wYlUrW3TRCX7zaD7rBy/1CEVNw0irfw9TgFf/ODmhubkHHT3+6Zk+SMz8RNgeuffBfAMbJw==", - "requires": { - "@sveltekit-i18n/parser-default": "^1.x" - } - }, - "@sveltekit-i18n/parser-default": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@sveltekit-i18n/parser-default/-/parser-default-1.0.3.tgz", - "integrity": "sha512-HheveklTjp3hxpYQhoHfyA6B4bQaUeSV5MQf2usIv/58UF2jY/YqhCAWj9bDBjufbuZc5pSz4BXvdX3WVT+viA==" - }, - "@tailwindcss/forms": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz", - "integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==", - "dev": true, - "requires": { - "mini-svg-data-uri": "^1.2.3" - } - }, - "@testing-library/dom": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz", - "integrity": "sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^4.2.0", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.4.4", - "pretty-format": "^27.0.2" - } - }, - "@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", - "dev": true, - "requires": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", - "redent": "^3.0.0" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } - } - }, - "@testing-library/svelte": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@testing-library/svelte/-/svelte-3.2.2.tgz", - "integrity": "sha512-IKwZgqbekC3LpoRhSwhd0JswRGxKdAGkf39UiDXTywK61YyLXbCYoR831e/UUC6EeNW4hiHPY+2WuovxOgI5sw==", - "dev": true, - "requires": { - "@testing-library/dom": "^8.1.0" - } - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true - }, - "@types/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", - "dev": true - }, - "@types/chai": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", - "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", - "dev": true - }, - "@types/chai-subset": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", - "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", - "dev": true, - "requires": { - "@types/chai": "*" - } - }, - "@types/cookie": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.1.tgz", - "integrity": "sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==", - "dev": true - }, - "@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.1.2.tgz", - "integrity": "sha512-y+nlX0h87U0R+wsGn6EBuoRWYyv3KFtwRNP3QWp9+k2tJ2/bqcGS3UxD7jgT+tiwJWWq3UsyV4Y+T6rsMT4XMg==", - "dev": true, - "requires": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.0.tgz", - "integrity": "sha512-QCSUFdwOi924g24czhOH5eTkXxUCqlLGZBRCySlwDYHIXRJkdGyjJc9nZaqhlFBZws8dq5Dvk0lCilsmlfsPxw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/node": { - "version": "18.11.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz", - "integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==", - "dev": true - }, - "@types/pug": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz", - "integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==", - "dev": true - }, - "@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true - }, - "@types/sass": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz", - "integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/testing-library__jest-dom": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", - "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", - "dev": true, - "requires": { - "@types/jest": "*" - } - }, - "@types/yargs": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", - "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.0.tgz", - "integrity": "sha512-FIBZgS3DVJgqPwJzvZTuH4HNsZhHMa9SjxTKAZTlMsPw/UzpEjcf9f4dfgDJEHjK+HboUJo123Eshl6niwEm/Q==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.40.0", - "@typescript-eslint/type-utils": "5.40.0", - "@typescript-eslint/utils": "5.40.0", - "debug": "^4.3.4", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.0.tgz", - "integrity": "sha512-Ah5gqyX2ySkiuYeOIDg7ap51/b63QgWZA7w6AHtFrag7aH0lRQPbLzUjk0c9o5/KZ6JRkTTDKShL4AUrQa6/hw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.40.0", - "@typescript-eslint/types": "5.40.0", - "@typescript-eslint/typescript-estree": "5.40.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.0.tgz", - "integrity": "sha512-d3nPmjUeZtEWRvyReMI4I1MwPGC63E8pDoHy0BnrYjnJgilBD3hv7XOiETKLY/zTwI7kCnBDf2vWTRUVpYw0Uw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.0", - "@typescript-eslint/visitor-keys": "5.40.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.0.tgz", - "integrity": "sha512-nfuSdKEZY2TpnPz5covjJqav+g5qeBqwSHKBvz7Vm1SAfy93SwKk/JeSTymruDGItTwNijSsno5LhOHRS1pcfw==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.40.0", - "@typescript-eslint/utils": "5.40.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.0.tgz", - "integrity": "sha512-V1KdQRTXsYpf1Y1fXCeZ+uhjW48Niiw0VGt4V8yzuaDTU8Z1Xl7yQDyQNqyAFcVhpYXIVCEuxSIWTsLDpHgTbw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.0.tgz", - "integrity": "sha512-b0GYlDj8TLTOqwX7EGbw2gL5EXS2CPEWhF9nGJiGmEcmlpNBjyHsTwbqpyIEPVpl6br4UcBOYlcI2FJVtJkYhg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.0", - "@typescript-eslint/visitor-keys": "5.40.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.0.tgz", - "integrity": "sha512-MO0y3T5BQ5+tkkuYZJBjePewsY+cQnfkYeRqS6tPh28niiIwPnQ1t59CSRcs1ZwJJNOdWw7rv9pF8aP58IMihA==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.40.0", - "@typescript-eslint/types": "5.40.0", - "@typescript-eslint/typescript-estree": "5.40.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.0.tgz", - "integrity": "sha512-ijJ+6yig+x9XplEpG2K6FUdJeQGGj/15U3S56W9IqXKJqleuD7zJ2AX/miLezwxpd7ZxDAqO87zWufKg+RPZyQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@vitest/coverage-c8": { - "version": "0.24.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.24.3.tgz", - "integrity": "sha512-tAmMyHxWYnAwGeJb7QgTuEX8aLasTg4X1/6INobXa/7wYGEJ28CACFO5iLn1HzFVPoLvhsS3luQjiflGjjSMRQ==", - "dev": true, - "requires": { - "c8": "^7.12.0", - "vitest": "0.24.3" - } - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true - }, - "acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "dev": true, - "requires": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" - } - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dev": true, - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - } - } - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "aria-query": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", - "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "autoprefixer": { - "version": "10.4.13", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", - "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001426", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "axios": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz", - "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==", - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true - }, - "builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true - }, - "busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dev": true, - "requires": { - "streamsearch": "^1.1.0" - } - }, - "c8": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", - "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.1.4", - "rimraf": "^3.0.2", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true - }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30001434", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz", - "integrity": "sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA==", - "dev": true - }, - "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", - "dev": true - }, - "check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "ci-info": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "dev": true, - "requires": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "dev": true, - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "css-declaration-sorter": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz", - "integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==", - "dev": true, - "requires": {} - }, - "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true - }, - "css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "cssnano": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.14.tgz", - "integrity": "sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==", - "dev": true, - "requires": { - "cssnano-preset-default": "^5.2.13", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - } - }, - "cssnano-preset-default": { - "version": "5.2.13", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz", - "integrity": "sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==", - "dev": true, - "requires": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.0", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.3", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.1", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - } - }, - "cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true, - "requires": {} - }, - "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "requires": { - "css-tree": "^1.1.2" - } - }, - "cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decimal.js": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", - "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "defined": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", - "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", - "dev": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true - }, - "detective": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", - "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", - "dev": true, - "requires": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - } - }, - "devalue": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.0.0.tgz", - "integrity": "sha512-w25siwXyuMUqMr7jPlEjyNCp1vn0Jzj/fNg3qVt/r/Dpe8HjESh2V92L0jmh3uq4iJt0BvjH+Azk1pQzkcnDWA==", - "dev": true - }, - "didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "diff-sequences": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.2.0.tgz", - "integrity": "sha512-413SY5JpYeSBZxmenGEmCVQ8mCgtFJF0w9PROdaS6z987XC2Pd2GOKqOITLtMftmyFZqgtCOb/QA7/Z3ZXfzIw==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-accessibility-api": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz", - "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", - "dev": true - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "dependencies": { - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - } - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "requires": { - "webidl-conversions": "^7.0.0" - } - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true - }, - "es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", - "dev": true - }, - "esbuild": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.11.tgz", - "integrity": "sha512-OgHGuhlfZ//mToxjte1D5iiiQgWfJ2GByVMwEC/IuoXsBGkuyK1+KrjYu0laSpnN/L1UmLUCv0s25vObdc1bVg==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.15.11", - "@esbuild/linux-loong64": "0.15.11", - "esbuild-android-64": "0.15.11", - "esbuild-android-arm64": "0.15.11", - "esbuild-darwin-64": "0.15.11", - "esbuild-darwin-arm64": "0.15.11", - "esbuild-freebsd-64": "0.15.11", - "esbuild-freebsd-arm64": "0.15.11", - "esbuild-linux-32": "0.15.11", - "esbuild-linux-64": "0.15.11", - "esbuild-linux-arm": "0.15.11", - "esbuild-linux-arm64": "0.15.11", - "esbuild-linux-mips64le": "0.15.11", - "esbuild-linux-ppc64le": "0.15.11", - "esbuild-linux-riscv64": "0.15.11", - "esbuild-linux-s390x": "0.15.11", - "esbuild-netbsd-64": "0.15.11", - "esbuild-openbsd-64": "0.15.11", - "esbuild-sunos-64": "0.15.11", - "esbuild-windows-32": "0.15.11", - "esbuild-windows-64": "0.15.11", - "esbuild-windows-arm64": "0.15.11" - } - }, - "esbuild-android-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.11.tgz", - "integrity": "sha512-rrwoXEiuI1kaw4k475NJpexs8GfJqQUKcD08VR8sKHmuW9RUuTR2VxcupVvHdiGh9ihxL9m3lpqB1kju92Ialw==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.11.tgz", - "integrity": "sha512-/hDubOg7BHOhUUsT8KUIU7GfZm5bihqssvqK5PfO4apag7YuObZRZSzViyEKcFn2tPeHx7RKbSBXvAopSHDZJQ==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.11.tgz", - "integrity": "sha512-1DqHD0ms3AhiwkKnjRUzmiW7JnaJJr5FKrPiR7xuyMwnjDqvNWDdMq4rKSD9OC0piFNK6n0LghsglNMe2MwJtA==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.11.tgz", - "integrity": "sha512-OMzhxSbS0lwwrW40HHjRCeVIJTURdXFA8c3GU30MlHKuPCcvWNUIKVucVBtNpJySXmbkQMDJdJNrXzNDyvoqvQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.11.tgz", - "integrity": "sha512-8dKP26r0/Qyez8nTCwpq60QbuYKOeBygdgOAWGCRalunyeqWRoSZj9TQjPDnTTI9joxd3QYw3UhVZTKxO9QdRg==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.11.tgz", - "integrity": "sha512-aSGiODiukLGGnSg/O9+cGO2QxEacrdCtCawehkWYTt5VX1ni2b9KoxpHCT9h9Y6wGqNHmXFnB47RRJ8BIqZgmQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.11.tgz", - "integrity": "sha512-lsrAfdyJBGx+6aHIQmgqUonEzKYeBnyfJPkT6N2dOf1RoXYYV1BkWB6G02tjsrz1d5wZzaTc3cF+TKmuTo/ZwA==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.11.tgz", - "integrity": "sha512-Y2Rh+PcyVhQqXKBTacPCltINN3uIw2xC+dsvLANJ1SpK5NJUtxv8+rqWpjmBgaNWKQT1/uGpMmA9olALy9PLVA==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.11.tgz", - "integrity": "sha512-TJllTVk5aSyqPFvvcHTvf6Wu1ZKhWpJ/qNmZO8LL/XeB+LXCclm7HQHNEIz6MT7IX8PmlC1BZYrOiw2sXSB95A==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.11.tgz", - "integrity": "sha512-uhcXiTwTmD4OpxJu3xC5TzAAw6Wzf9O1XGWL448EE9bqGjgV1j+oK3lIHAfsHnuIn8K4nDW8yjX0Sv5S++oRuw==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.11.tgz", - "integrity": "sha512-WD61y/R1M4BLe4gxXRypoQ0Ci+Vjf714QYzcPNkiYv5I8K8WDz2ZR8Bm6cqKxd6rD+e/rZgPDbhQ9PCf7TMHmA==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.11.tgz", - "integrity": "sha512-JVleZS9oPVLTlBhPTWgOwxFWU/wMUdlBwTbGA4GF8c38sLbS13cupj+C8bLq929jU7EMWry4SaL+tKGIaTlqKg==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.11.tgz", - "integrity": "sha512-9aLIalZ2HFHIOZpmVU11sEAS9F8TnHw49daEjcgMpBXHFF57VuT9f9/9LKJhw781Gda0P9jDkuCWJ0tFbErvJw==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.11.tgz", - "integrity": "sha512-sZHtiXXOKsLI3XGBGoYO4qKBzJlb8xNsWmvFiwFMHFzA4AXgDP1KDp7Dawe9C2pavTRBDvl+Ok4n/DHQ59oaTg==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.11.tgz", - "integrity": "sha512-hUC9yN06K9sg7ju4Vgu9ChAPdsEgtcrcLfyNT5IKwKyfpLvKUwCMZSdF+gRD3WpyZelgTQfJ+pDx5XFbXTlB0A==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.11.tgz", - "integrity": "sha512-0bBo9SQR4t66Wd91LGMAqmWorzO0TTzVjYiifwoFtel8luFeXuPThQnEm5ztN4g0fnvcp7AnUPPzS/Depf17wQ==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.11.tgz", - "integrity": "sha512-EuBdTGlsMTjEl1sQnBX2jfygy7iR6CKfvOzi+gEOfhDqbHXsmY1dcpbVtcwHAg9/2yUZSfMJHMAgf1z8M4yyyw==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.11.tgz", - "integrity": "sha512-O0/Wo1Wk6dc0rZSxkvGpmTNIycEznHmkObTFz2VHBhjPsO4ZpCgfGxNkCpz4AdAIeMczpTXt/8d5vdJNKEGC+Q==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.11.tgz", - "integrity": "sha512-x977Q4HhNjnHx00b4XLAnTtj5vfbdEvkxaQwC1Zh5AN8g5EX+izgZ6e5QgqJgpzyRNJqh4hkgIJF1pyy1be0mQ==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.11.tgz", - "integrity": "sha512-VwUHFACuBahrvntdcMKZteUZ9HaYrBRODoKe4tIWxguQRvvYoYb7iu5LrcRS/FQx8KPZNaa72zuqwVtHeXsITw==", - "dev": true, - "optional": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", - "@humanwhocodes/module-importer": "^1.0.1", - "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.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "dependencies": { - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} - }, - "eslint-plugin-svelte3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-4.0.0.tgz", - "integrity": "sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==", - "dev": true, - "requires": {} - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", - "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "expect": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.2.0.tgz", - "integrity": "sha512-03ClF3GWwUqd9Grgkr9ZSdaCJGMRA69PQ8jT7o+Bx100VlGiAFf9/8oIm9Qve7ZVJhuJxFftqFhviZJRxxNfvg==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.2.0", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.2.0", - "jest-message-util": "^29.2.0", - "jest-util": "^29.2.0" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" - }, - "foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globalyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", - "dev": true - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "requires": { - "whatwg-encoding": "^2.0.0" - } - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-builtin-module": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz", - "integrity": "sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==", - "dev": true, - "requires": { - "builtin-modules": "^3.3.0" - } - }, - "is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "requires": { - "@types/estree": "*" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest-diff": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.2.0.tgz", - "integrity": "sha512-GsH07qQL+/D/GxlnU+sSg9GL3fBOcuTlmtr3qr2pnkiODCwubNN2/7slW4m3CvxDsEus/VEOfQKRFLyXsUlnZw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.2.0", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.0.tgz", - "integrity": "sha512-QCSUFdwOi924g24czhOH5eTkXxUCqlLGZBRCySlwDYHIXRJkdGyjJc9nZaqhlFBZws8dq5Dvk0lCilsmlfsPxw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true - }, - "jest-matcher-utils": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.2.0.tgz", - "integrity": "sha512-FcEfKZ4vm28yCdBsvC69EkrEhcfex+IYlRctNJXsRG9+WC3WxgBNORnECIgqUtj7o/h1d8o7xB/dFUiLi4bqtw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.2.0", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.0.tgz", - "integrity": "sha512-QCSUFdwOi924g24czhOH5eTkXxUCqlLGZBRCySlwDYHIXRJkdGyjJc9nZaqhlFBZws8dq5Dvk0lCilsmlfsPxw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-message-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.2.0.tgz", - "integrity": "sha512-arBfk5yMFMTnMB22GyG601xGSGthA02vWSewPaxoFo0F9wBqDOyxccPbCcYu8uibw3kduSHXdCOd1PsLSgdomg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.2.0", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.2.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.0.tgz", - "integrity": "sha512-QCSUFdwOi924g24czhOH5eTkXxUCqlLGZBRCySlwDYHIXRJkdGyjJc9nZaqhlFBZws8dq5Dvk0lCilsmlfsPxw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.2.0.tgz", - "integrity": "sha512-8M1dx12ujkBbnhwytrezWY0Ut79hbflwodE+qZKjxSRz5qt4xDp6dQQJaOCFvCmE0QJqp9KyEK33lpPNjnhevw==", - "dev": true, - "requires": { - "@jest/types": "^29.2.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "joi": { - "version": "17.6.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.3.tgz", - "integrity": "sha512-YlQsIaS9MHYekzf1Qe11LjTkNzx9qhYluK3172z38RxYoAUf82XMX1p1DG1H4Wtk2ED/vPdSn9OggqtDu+aTow==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", - "@sideway/pinpoint": "^2.0.0" - } - }, - "js-cookie": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", - "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==" - }, - "js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "acorn": "^8.8.0", - "acorn-globals": "^7.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.2", - "decimal.js": "^10.4.1", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.2", - "parse5": "^7.1.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^3.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0", - "ws": "^8.9.0", - "xml-name-validator": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true - }, - "lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lilconfig": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", - "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", - "dev": true - }, - "local-pkg": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.2.tgz", - "integrity": "sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", - "dev": true, - "requires": { - "get-func-name": "^2.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "lz-string": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", - "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", - "dev": true - }, - "magic-string": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", - "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", - "dev": true - }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "mini-svg-data-uri": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", - "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true - }, - "mrmime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", - "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "nwsapi": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", - "dev": true - }, - "object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "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": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse5": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", - "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", - "dev": true, - "requires": { - "entities": "^4.4.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dev": true, - "requires": { - "through": "~2.3" - } - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true - }, - "playwright-core": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.1.tgz", - "integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==", - "dev": true - }, - "postcss": { - "version": "8.4.19", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", - "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==", - "dev": true, - "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-colormin": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", - "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", - "dev": true, - "requires": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "dev": true, - "requires": {} - }, - "postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true, - "requires": {} - }, - "postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true, - "requires": {} - }, - "postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true, - "requires": {} - }, - "postcss-import": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", - "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", - "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", - "dev": true, - "requires": { - "camelcase-css": "^2.0.1" - } - }, - "postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dev": true, - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - } - }, - "postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" - } - }, - "postcss-merge-rules": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz", - "integrity": "sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dev": true, - "requires": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-nested": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", - "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true, - "requires": {} - }, - "postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dev": true, - "requires": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", - "dev": true, - "requires": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-reduce-initial": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz", - "integrity": "sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - } - }, - "postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - } - }, - "postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true - }, - "prettier-plugin-svelte": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-2.8.0.tgz", - "integrity": "sha512-QlXv/U3bUszks3XYDPsk1fsaQC+fo2lshwKbcbO+lrSVdJ+40mB1BfL8OCAk1W9y4pJxpqO/4gqm6NtF3zNGCw==", - "dev": true, - "requires": {} - }, - "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "dev": true, - "requires": { - "event-stream": "=3.3.4" - } - }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "purgecss": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-5.0.0.tgz", - "integrity": "sha512-RAnuxrGuVyLLTr8uMbKaxDRGWMgK5CCYDfRyUNNcaz5P3kGgD2b7ymQGYEyo2ST7Tl/ScwFgf5l3slKMxHSbrw==", - "dev": true, - "requires": { - "commander": "^9.0.0", - "glob": "^8.0.3", - "postcss": "^8.4.4", - "postcss-selector-parser": "^6.0.7" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "requires": { - "pify": "^2.3.0" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - } - }, - "regenerator-runtime": { - "version": "0.13.10", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz", - "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==", - "dev": true - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, - "requires": { - "mri": "^1.1.0" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "sander": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", - "integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==", - "dev": true, - "requires": { - "es6-promise": "^3.1.2", - "graceful-fs": "^4.1.3", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.2" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "set-cookie-parser": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz", - "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "shortid": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", - "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", - "requires": { - "nanoid": "^2.1.0" - }, - "dependencies": { - "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" - } - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "dev": true, - "requires": { - "is-arrayish": "^0.3.1" - } - }, - "sirv": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.2.tgz", - "integrity": "sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==", - "dev": true, - "requires": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^3.0.0" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "sorcery": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", - "integrity": "sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==", - "dev": true, - "requires": { - "buffer-crc32": "^0.2.5", - "minimist": "^1.2.0", - "sander": "^0.5.0", - "sourcemap-codec": "^1.3.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "dev": true, - "requires": { - "through": "2" - } - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "start-server-and-test": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.14.0.tgz", - "integrity": "sha512-on5ELuxO2K0t8EmNj9MtVlFqwBMxfWOhu4U7uZD1xccVpFlOQKR93CSe0u98iQzfNxRyaNTb/CdadbNllplTsw==", - "dev": true, - "requires": { - "bluebird": "3.7.2", - "check-more-types": "2.24.0", - "debug": "4.3.2", - "execa": "5.1.1", - "lazy-ass": "1.6.0", - "ps-tree": "1.2.0", - "wait-on": "6.0.0" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - } - } - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } - }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "strip-literal": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-0.4.2.tgz", - "integrity": "sha512-pv48ybn4iE1O9RLgCAN0iU4Xv7RlBTiit6DKmMiErbs9x1wH6vXBs45tWc0H5wUIF6TLTrKweqkmYF/iraQKNw==", - "dev": true, - "requires": { - "acorn": "^8.8.0" - } - }, - "stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "svelte": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.52.0.tgz", - "integrity": "sha512-FxcnEUOAVfr10vDU5dVgJN19IvqeHQCS1zfe8vayTfis9A2t5Fhx+JDe5uv/C3j//bB1umpLJ6quhgs9xyUbCQ==" - }, - "svelte-check": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.9.2.tgz", - "integrity": "sha512-DRi8HhnCiqiGR2YF9ervPGvtoYrheE09cXieCTEqeTPOTJzfoa54Py8rovIBv4bH4n5HgZYIyTQ3DDLHQLl2uQ==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.9", - "chokidar": "^3.4.1", - "fast-glob": "^3.2.7", - "import-fresh": "^3.2.1", - "picocolors": "^1.0.0", - "sade": "^1.7.4", - "svelte-preprocess": "^4.0.0", - "typescript": "*" - } - }, - "svelte-hmr": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.0.tgz", - "integrity": "sha512-Aw21SsyoohyVn4yiKXWPNCSW2DQNH/76kvUnE9kpt4h9hcg9tfyQc6xshx9hzgMfGF0kVx0EGD8oBMWSnATeOg==", - "dev": true, - "requires": {} - }, - "svelte-preprocess": { - "version": "4.10.7", - "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz", - "integrity": "sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==", - "dev": true, - "requires": { - "@types/pug": "^2.0.4", - "@types/sass": "^1.16.0", - "detect-indent": "^6.0.0", - "magic-string": "^0.25.7", - "sorcery": "^0.10.0", - "strip-indent": "^3.0.0" - }, - "dependencies": { - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - } - } - }, - "sveltekit-i18n": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/sveltekit-i18n/-/sveltekit-i18n-2.2.2.tgz", - "integrity": "sha512-6eygICleGCSL7elY7A3trF8XUhV+mlW56ZSoD0UUKXlw+Y6u0MTTHDq48u1LyY73SfnlbPHXgTarhTjZ0BvUKA==", - "requires": { - "@sveltekit-i18n/base": "1.2.1", - "@sveltekit-i18n/parser-default": "1.0.3" - } - }, - "svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - } - } - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "tailwindcss": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", - "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", - "dev": true, - "requires": { - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.1", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "lilconfig": "^2.0.6", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.18", - "postcss-import": "^14.1.0", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "6.0.0", - "postcss-selector-parser": "^6.0.10", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.1" - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "tiny-glob": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", - "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", - "dev": true, - "requires": { - "globalyzer": "0.1.0", - "globrex": "^0.1.2" - } - }, - "tinybench": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.0.tgz", - "integrity": "sha512-zs1gMVBwyyG2QbVchYIbnabRhMOCGvrwZz/q+SV+LIMa9q5YDQZi2kkI6ZRqV2Bz7ba1uvrc7ieUoE4KWnGeKg==", - "dev": true - }, - "tinypool": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.0.tgz", - "integrity": "sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ==", - "dev": true - }, - "tinyspy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-1.0.2.tgz", - "integrity": "sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "totalist": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz", - "integrity": "sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==", - "dev": true - }, - "tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - } - }, - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "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==", - "dev": true - }, - "typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true - }, - "undici": { - "version": "5.21.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.21.0.tgz", - "integrity": "sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA==", - "dev": true, - "requires": { - "busboy": "^1.6.0" - } - }, - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - } - }, - "vite": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.7.tgz", - "integrity": "sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==", - "dev": true, - "requires": { - "esbuild": "^0.15.9", - "fsevents": "~2.3.2", - "postcss": "^8.4.18", - "resolve": "^1.22.1", - "rollup": "^2.79.1" - } - }, - "vitest": { - "version": "0.24.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.3.tgz", - "integrity": "sha512-aM0auuPPgMSstWvr851hB74g/LKaKBzSxcG3da7ejfZbx08Y21JpZmbmDYrMTCGhVZKqTGwzcnLMwyfz2WzkhQ==", - "dev": true, - "requires": { - "@types/chai": "^4.3.3", - "@types/chai-subset": "^1.3.3", - "@types/node": "*", - "chai": "^4.3.6", - "debug": "^4.3.4", - "local-pkg": "^0.4.2", - "strip-literal": "^0.4.2", - "tinybench": "^2.3.0", - "tinypool": "^0.3.0", - "tinyspy": "^1.0.2", - "vite": "^3.0.0" - } - }, - "w3c-xmlserializer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", - "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", - "dev": true, - "requires": { - "xml-name-validator": "^4.0.0" - } - }, - "wait-on": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.0.tgz", - "integrity": "sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw==", - "dev": true, - "requires": { - "axios": "^0.21.1", - "joi": "^17.4.0", - "lodash": "^4.17.21", - "minimist": "^1.2.5", - "rxjs": "^7.1.0" - }, - "dependencies": { - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "requires": { - "follow-redirects": "^1.14.0" - } - } - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "requires": { - "iconv-lite": "0.6.3" - } - }, - "whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true - }, - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "ws": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", - "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/client/kit/package.json b/client/kit/package.json deleted file mode 100644 index 826b6f2f..00000000 --- a/client/kit/package.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "name": "client", - "version": "1.0.0", - "author": "Fairness", - "private": true, - "scripts": { - "dev": "vite dev --clearScreen=false", - "build": "vite build", - "preview": "vite preview", - "start": "node ./build", - "test": "vitest run", - "test:coverage": "npm run test -- --coverage", - "test:watch": "vitest watch", - "test-e2e": "playwright test", - "test-e2e:ci": "start-server-and-test e2e-start '3000/api|3001/login' test-e2e", - "e2e-start": "DATABASE_NAME=permacoop_test cd ../../ && make start", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "prettier --plugin-search-dir . --check . && eslint .", - "format": "prettier --plugin-search-dir . --write ." - }, - "dependencies": { - "axios": "^1.1.3", - "js-cookie": "^3.0.1", - "shortid": "^2.2.16", - "sveltekit-i18n": "^2.2.2" - }, - "devDependencies": { - "@fullhuman/postcss-purgecss": "^5.0.0", - "@playwright/test": "^1.25.0", - "@sveltejs/adapter-node": "^1.0.0-next.98", - "@sveltejs/kit": "next", - "@tailwindcss/forms": "^0.5.3", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/svelte": "^3.2.2", - "@typescript-eslint/eslint-plugin": "^5.27.0", - "@typescript-eslint/parser": "^5.27.0", - "@vitest/coverage-c8": "^0.24.3", - "autoprefixer": "^10.4.13", - "color": "^4.2.3", - "cssnano": "^5.1.14", - "eslint": "^8.16.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-svelte3": "^4.0.0", - "jsdom": "^20.0.1", - "postcss": "^8.4.19", - "prettier": "^2.6.2", - "prettier-plugin-svelte": "^2.7.0", - "start-server-and-test": "^1.14.0", - "svelte": "^3.44.0", - "svelte-check": "^2.7.1", - "svelte-preprocess": "^4.10.6", - "tailwindcss": "^3.2.4", - "tslib": "^2.3.1", - "typescript": "^4.7.4", - "vite": "^3.2.7", - "vitest": "^0.24.3" - }, - "type": "module", - "engines": { - "node": "16" - } -} diff --git a/client/kit/playwright.config.ts b/client/kit/playwright.config.ts deleted file mode 100644 index bf5e8caf..00000000 --- a/client/kit/playwright.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { PlaywrightTestConfig } from "@playwright/test"; - -const config: PlaywrightTestConfig = { - testDir: "./e2e", - retries: 1, - use: { - baseURL: "http://localhost:3001", - browserName: "firefox", - headless: true, - screenshot: "only-on-failure", - video: "on-first-retry", - }, -}; - -export default config; diff --git a/client/kit/src/app.css b/client/kit/src/app.css deleted file mode 100644 index 9cffd335..00000000 --- a/client/kit/src/app.css +++ /dev/null @@ -1,8 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* - Write here your custom css - See here : https://tailwindcss.com/docs/functions-and-directives -*/ diff --git a/client/kit/src/app.d.ts b/client/kit/src/app.d.ts deleted file mode 100644 index 3e4ed205..00000000 --- a/client/kit/src/app.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -// See https://kit.svelte.dev/docs/types#app -// for information about these interfaces -// and what to do when importing types -declare namespace App { - // interface Locals {} - // interface PageData {} - // interface Error {} - // interface Platform {} -} diff --git a/client/kit/src/app.html b/client/kit/src/app.html deleted file mode 100644 index 13c92e77..00000000 --- a/client/kit/src/app.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - %sveltekit.head% - - -
      %sveltekit.body%
      - - diff --git a/client/kit/src/components/RequiredMarker.svelte b/client/kit/src/components/RequiredMarker.svelte deleted file mode 100644 index c52f8cac..00000000 --- a/client/kit/src/components/RequiredMarker.svelte +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/client/kit/src/components/ServerErrors.spec.ts b/client/kit/src/components/ServerErrors.spec.ts deleted file mode 100644 index dadbd614..00000000 --- a/client/kit/src/components/ServerErrors.spec.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @jest-environment jsdom - */ -import "@testing-library/jest-dom"; -import { render } from "@testing-library/svelte"; -import { addTranslations, loadTranslations } from "src/lib/i18n"; -import ServerErrors from "./ServerErrors.svelte"; - -it("renders nothing with no error.", () => { - const { queryByText } = render(ServerErrors, { errors: [] }); - - expect(queryByText("Erreur")).not.toBeInTheDocument(); -}); - -it("renders the given errors", async () => { - await loadTranslations("fr"); - - addTranslations({ - fr: { - "": { - first_error: "Fichier non trouvé", - second_error: "Saisie invalide", - }, - }, - }); - - const errors = ["first_error", "second_error"]; - const { getAllByRole, getByText } = render(ServerErrors, { errors }); - - const listItems = getAllByRole("listitem"); - const listItemErrors = listItems.map((item) => item.textContent); - expect(listItems).toHaveLength(2); - expect(listItemErrors).toStrictEqual(["Fichier non trouvé", "Saisie invalide"]); - expect(getByText(/Erreur/i)).toBeInTheDocument(); -}); diff --git a/client/kit/src/components/ServerErrors.svelte b/client/kit/src/components/ServerErrors.svelte deleted file mode 100644 index 5090545f..00000000 --- a/client/kit/src/components/ServerErrors.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - -{#if errors.length > 0} -
      -
      - -
      -
      -
      - {$_("error")} -
        - {#each errors as error} -
      • {$_(error)}
      • - {/each} -
      -
      -
      -
      -{/if} diff --git a/client/kit/src/components/icons/ErrorIcon.svelte b/client/kit/src/components/icons/ErrorIcon.svelte deleted file mode 100644 index d491cf0c..00000000 --- a/client/kit/src/components/icons/ErrorIcon.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - - - diff --git a/client/kit/src/components/inputs/Button.svelte b/client/kit/src/components/inputs/Button.svelte deleted file mode 100644 index 3e1fcf68..00000000 --- a/client/kit/src/components/inputs/Button.svelte +++ /dev/null @@ -1,14 +0,0 @@ - - - diff --git a/client/kit/src/components/inputs/Input.spec.ts b/client/kit/src/components/inputs/Input.spec.ts deleted file mode 100644 index 21951af0..00000000 --- a/client/kit/src/components/inputs/Input.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @jest-environment jsdom - */ -import "@testing-library/jest-dom"; -import { render } from "@testing-library/svelte"; -import Input from "./Input.svelte"; - -it("renders an email input.", () => { - const value = "abc"; - const label = "my email input"; - const type = "email"; - - const { getByRole } = render(Input, { value, label, type }); - - expect(getByRole("textbox", { name: /my email input/i })).toBeInTheDocument(); -}); diff --git a/client/kit/src/components/inputs/Input.svelte b/client/kit/src/components/inputs/Input.svelte deleted file mode 100644 index 79c1e23f..00000000 --- a/client/kit/src/components/inputs/Input.svelte +++ /dev/null @@ -1,46 +0,0 @@ - - -
      - {#if label} - - {/if} - {#if type === "email"} - - {:else if type === "password"} - - {:else if type === "money"} - - {:else if type === "date"} - - {:else} - - {/if} -
      diff --git a/client/kit/src/config.js b/client/kit/src/config.js deleted file mode 100644 index d5d53ae3..00000000 --- a/client/kit/src/config.js +++ /dev/null @@ -1,4 +0,0 @@ -export default { - API_URL_SSR: import.meta.env.VITE_CLIENT_API_URL_SSR, - API_URL: import.meta.env.VITE_CLIENT_API_URL, -}; diff --git a/client/kit/src/lib/axios.ts b/client/kit/src/lib/axios.ts deleted file mode 100644 index e430c16c..00000000 --- a/client/kit/src/lib/axios.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { browser } from "$app/environment"; -import axios from "axios"; -import Cookies from "js-cookie"; -import config from "src/config"; -export { AxiosError } from "axios"; - -const client = axios.create({ - baseURL: browser ? config.API_URL : config.API_URL_SSR, -}); - -const authorizationBearerHeader = (token = "") => { - const bearer = token || Cookies.get("permacoop_token"); - const headers = bearer ? { Authorization: `Bearer ${bearer}` } : {}; - return { - headers, - }; -}; - -export const post = (url: string, payload: any) => { - return client.post(url, payload, authorizationBearerHeader()); -}; - -export const put = (url: string, payload: any) => { - return client.put(url, payload, authorizationBearerHeader()); -}; - -export const del = (url: string) => { - return client.delete(url, authorizationBearerHeader()); -}; - -export const get = (url: string, payload: any, token: string) => { - return client.get(url, { ...payload, ...authorizationBearerHeader(token) }); -}; diff --git a/client/kit/src/lib/errors/normalizer.ts b/client/kit/src/lib/errors/normalizer.ts deleted file mode 100644 index 7739afd2..00000000 --- a/client/kit/src/lib/errors/normalizer.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { _ } from "src/lib/i18n"; -import type { AxiosError } from "$lib/axios"; - -export const errorNormalizer = (e: AxiosError): string[] => { - if (!e.response) { - // eslint-disable-next-line no-console - console.error("Non standard error", e); - return [_.get("error_generic")]; - } - - const message = e.response.data.message || ""; - - if (Array.isArray(message)) { - return message; - } - - return [message]; -}; diff --git a/client/kit/src/lib/i18n/fr.json b/client/kit/src/lib/i18n/fr.json deleted file mode 100644 index bdbdb883..00000000 --- a/client/kit/src/lib/i18n/fr.json +++ /dev/null @@ -1,345 +0,0 @@ -{ - "app": "Permacoop", - "error": "Erreur", - "error_generic": "Une erreur est survenue", - "pagination": "Affichage {start}-{from} sur {totalItems}", - "common": { - "actions": "Actions", - "form": { - "save": "Enregistrer", - "edit": "Modifier", - "add": "Ajouter", - "remove": "Supprimer", - "see": "Voir" - }, - "roles": { - "cooperator": "Coopérateur", - "accountant": "Comptable", - "employee": "Employé" - }, - "errors": { - "file_not_found": "Le fichier demandé n'existe pas" - }, - "days_duration": "{n, plural, =0 {0} one {# jour} other {# jours}}", - "yes": "Oui", - "no": "Non" - }, - "login": { - "title": "Se connecter", - "sub_title": "Connexion", - "password_lost": "Mot de passe oublié ?", - "form": { - "button": "Se connecter", - "email": "Adresse email", - "password": "Mot de passe" - } - }, - "accounting": { - "breadcrumb": "FairGestion", - "invoices": { - "title": "Factures", - "date": "Date", - "project": "Nom du projet", - "invoice_id": "Numéro de facture", - "expiry_date": "Date d'échéance", - "amount": "Montant TTC", - "status": { - "title": "Statut", - "payed": "Payé", - "sent": "Envoyé", - "draft": "Brouillon", - "canceled": "Annulé" - }, - "add": { - "title": "Générer une facture" - }, - "form": { - "submit": "Générer", - "expire_in_days": "Echéance (en jours)" - } - }, - "tasks": { - "title": "Missions", - "name": "Nom de la mission", - "form": { - "name": "Nom de la mission", - "task": "Mission", - "task_placeholder": "-- Choisir une mission --" - }, - "add": { - "title": "Ajouter une mission" - }, - "edit": { - "title": "Edition de la mission \"{name}\"" - }, - "errors": { - "not_found": "La mission n'existe pas.", - "already_exist": "Cette mission existe déjà." - } - } - }, - "crm": { - "breadcrumb": "FairCRM", - "projects": { - "title": "Projets", - "name": "Nom du projet", - "customer": "Nom du client", - "form": { - "project_placeholder": "-- Choisir un projet --", - "project": "Nom du projet" - }, - "invoice_unit": { - "title": "Facturation", - "day": "À la journée", - "hour": "À l'heure" - }, - "add": { - "title": "Ajouter un projet" - }, - "edit": { - "title": "Edition du projet \"{name}\"" - }, - "errors": { - "not_found": "Le projet n'existe pas.", - "already_exist": "Ce projet existe déjà." - } - }, - "customers": { - "title": "Clients", - "name": "Nom du client", - "addresse": "Adresse", - "errors": { - "already_exist": "Ce client existe déjà.", - "not_found": "Le client n'existe pas." - }, - "form": { - "customer_placeholder": "-- Choisir un client --", - "customer": "Nom du client", - "address": "Adresse", - "zip_code": "Code postal", - "city": "Ville", - "country": "Pays" - }, - "add": { - "title": "Ajouter un client" - }, - "edit": { - "title": "Edition du client \"{name}\"" - } - } - }, - "faircalendar": { - "legend": "Légende:", - "breadcrumb": "FairCalendar", - "title": "Faircalendar {month}", - "summary": "Récapitulatif", - "no_meal_ticket_for_this_day": "Pas de ticket restaurant pour cette journée", - "errors": { - "event_doesnt_belong_to_user": "Cet évènement ne vous appartient pas, vous ne pouvez ni le modifier, ni le supprimer.", - "event_not_found": "Cet évènement n'existe pas.", - "events_or_leaves_already_exist_for_this_period": "Vous avez déjà complété un congé ou un CRA sur la période demandée.", - "event_maximum_reached": "Vous ne pouvez pas déclarer plus de 12h sur une journée.", - "no_date_during_this_period": "Vous devez sélectionner une période valide.", - "project_or_task_missing": "Vous devez saisir un projet et une mission." - }, - "type": { - "mission": "Missions", - "support": "Supports", - "dojo": "Dojos", - "formationConference": "Formations / Confs", - "leave": "Congés", - "leave_medical": "Congé maladie", - "leave_paid": "Congé payé", - "leave_unpaid": "Congé sans solde", - "leave_special": "Congé exceptionnel", - "leave_illimited": "Congé illimité", - "holiday": "Jour férié", - "other": "Autres" - }, - "filter": { - "title": "Filtres", - "month": "Filtrer par mois", - "user": "Filtrer par coopérateur - salarié" - }, - "from_date": "CRA du {date}", - "to_date": "au {date}", - "form": { - "type": "Type de CRA", - "time": "Temps passé", - "summary": "Commentaire", - "can_have_meal_ticket": "Je reçois un ticket restaurant pour cet évenement", - "cant_have_meal_ticket_comment": "Pour quelle raison ne voulez-vous pas en reçevoir ?" - } - }, - "human_resources": { - "breadcrumb": "FairRH", - "meal_tickets": { - "breadcrumb": "Tickets restaurant", - "title": "Tickets restaurant - {month}", - "user": "Coopérateur - salarié", - "nb_meal_tickets": "Nb. ticket(s) restaurant", - "nb_meal_tickets_removals": "Nb. exception(s)", - "do_not_want_to_receive_meal_ticket_this_day": "Je ne souhaite pas recevoir de ticket restaurant pour la date du", - "add": { - "title": "Ajouter une exception" - }, - "errors": { - "already_exist": "Vous avez déjà créé une exception pour ce jour", - "not_a_working_date": "Ce jour n'est pas travaillé" - } - }, - "payslips": { - "breadcrumb": "Éléments de paie", - "title": "Éléments pour les fiches de paie", - "user": "Salairé / stagiaire", - "contract": "Type de contrat", - "executive_position": "Cadre", - "joining_date": "Date d'entrée", - "annual_earnings": "Salaire brut annuel", - "monthly_earnings": "Salaire brut mensuel", - "working_time": "TC/TP", - "transport_fee": "Transport", - "meal_tickets": "Tickets resto", - "full_time": "Temps complet", - "partial_time": "Temps partiel", - "health_insurance": "Mutuelle", - "paid_leaves": "Congés payés", - "unpaid_leaves": "Congés sans solde", - "sick_leaves": "Congés maladie", - "exceptional_leaves": "Congés exceptionnels", - "download": "Télécharger" - }, - "leaves": { - "title": "Congés", - "confirm_cancel": "Etes-vous sûr de vouloir annuler ces congés ?", - "requests": { - "title": "Demandes de congé", - "view": "Demande de {user}", - "user": "Coopérateur - salarié", - "all_day": "Toute la journée", - "periods": "Périodes", - "period": "Du {from} au {to}", - "status": "Etat", - "duration": "Durée", - "comment": "Commentaire", - "moderate_by": "Modéré par", - "end_date": "Date de fin", - "start_date": "Date de début", - "confirm": "Etes-vous sûr de vouloir supprimer cette demande de congé ?", - "add": { - "title": "Faire une demande de congé" - }, - "states": { - "pending": "En attente", - "accepted": "Acceptée", - "refused": "Refusée" - }, - "leave_type": { - "title": "Type de congé", - "medical": "Congé maladie", - "paid": "Congé payé", - "illimited": "Congé illimité", - "unpaid": "Congé sans solde", - "special": "Congé exceptionnel" - }, - "errors": { - "already_exist_for_this_period": "Vous avez déjà une demande de congé sur cette période.", - "cant_be_moderated": "Vous ne pouvez pas modérer cette demande de congé.", - "not_found": "La demande de congé n'existe pas." - }, - "form": { - "from_date": "Du", - "to_date": "Au", - "all_day": "Toute la journée", - "comment": "Commentaire" - }, - "actions": { - "accept": "Accepter", - "refuse": "Refuser" - } - } - }, - "users": { - "title": "Coopérateurs - salariés", - "first_name": "Prénom", - "last_name": "Nom", - "email": "Adresse email", - "role": "Rôle", - "add": { - "title": "Ajouter un coopérateur - salarié" - }, - "edit": { - "title": "Mise à jour des informations administratives de {name}" - }, - "form": { - "user_placeholder": "-- Choisir un coopérateur - salarié --", - "user": "Coopérateur - salarié", - "contract": { - "title": "Contrat de travail", - "cdi": "CDI", - "cdd": "CDD", - "ctt": "CTT", - "professionalization": "Contrat de professionalisation", - "apprenticeship": "Contrat d'apprentisage" - }, - "working_time": { - "title": "Temps de travail", - "full_time": "Temps complet", - "part_time": "Temps partiel" - }, - "executive_position": "Statut cadre", - "health_insurance": "Mutuelle", - "annual_earnings": "Salaire annuel brut", - "transport_fee": "Frais de transport", - "joining_date": "Date d'entrée", - "leaving_date": "Date de sortie", - "first_name": "Prénom", - "last_name": "Nom", - "email": "Adresse email", - "password": "Mot de passe", - "role": "Rôle" - }, - "errors": { - "password_not_match": "Adresse email ou mot de passe incorrect.", - "email_already_exist": "Cette adresse email est déjà utilisée.", - "user_administrative_missing": "Veuillez saisir les informations administratives.", - "not_found": "Adresse email ou mot de passe incorrect." - } - }, - "savings_records": { - "title": "Épargne salariale", - "add": { - "title": "Ajouter une prime de participation" - }, - "form": { - "amount": "Montant" - }, - "errors": { - "interest_rate_not_found": "Aucun taux d'intérêt n'est applicable." - } - } - }, - "profile": { - "title": "Mon compte", - "logout": "Se déconnecter", - "form": { - "first_name": "Prénom", - "last_name": "Nom", - "email": "Adresse email", - "password": "Mot de passe" - } - }, - "search": { - "title": "Chercher un client, un projet ...", - "aria_label": "Rechercher" - }, - "dashboard": { - "title": "Tableau de bord", - "welcome": "Bonjour {firstName} {lastName} !" - }, - "settings": { - "errors": { - "cooperative_not_found": "Les paramètres de la coopérative n'ont pas été trouvés." - } - } -} diff --git a/client/kit/src/lib/i18n/index.ts b/client/kit/src/lib/i18n/index.ts deleted file mode 100644 index 291fbd67..00000000 --- a/client/kit/src/lib/i18n/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import i18n from "sveltekit-i18n"; -import type { Config } from "sveltekit-i18n"; - -const config: Config = { - loaders: [ - { - locale: "fr", - key: "", - loader: async () => { - return (await import("./fr.json")).default; - }, - }, - ], -}; - -export const { - t: _, - locale, - locales, - loading, - addTranslations, - loadTranslations, -} = new i18n(config); diff --git a/client/kit/src/lib/navigation.ts b/client/kit/src/lib/navigation.ts deleted file mode 100644 index 8493c7c9..00000000 --- a/client/kit/src/lib/navigation.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { goto } from "$app/navigation"; - -// This helper exists to mark places where we intend to redirect -// to a page that we know is still managed by Sapper. -// We will see a 404 error in the web console, because SvelteKit will try -// to match a route, fail, and then let the browser take over, which will -// let Sapper respond. -export const gotoSapper = async (path: string): Promise => { - await goto(path); -}; diff --git a/client/kit/src/lib/shortid.ts b/client/kit/src/lib/shortid.ts deleted file mode 100644 index 3ad1bc58..00000000 --- a/client/kit/src/lib/shortid.ts +++ /dev/null @@ -1,3 +0,0 @@ -import shortid from "shortid"; - -export default shortid; diff --git a/client/kit/src/routes/+layout.ts b/client/kit/src/routes/+layout.ts deleted file mode 100644 index eb93ae06..00000000 --- a/client/kit/src/routes/+layout.ts +++ /dev/null @@ -1,14 +0,0 @@ -import "../app.css"; - -import type { LayoutLoad } from "./$types"; -import { locale, loadTranslations } from "src/lib/i18n"; - -export const load: LayoutLoad = async ({ url }) => { - const { pathname } = url; - - const defaultLocale = "fr"; - const initLocale = locale.get() || defaultLocale; - await loadTranslations(initLocale, pathname); - - return {}; -}; diff --git a/client/kit/src/routes/login/+page.svelte b/client/kit/src/routes/login/+page.svelte deleted file mode 100644 index b3bdd40a..00000000 --- a/client/kit/src/routes/login/+page.svelte +++ /dev/null @@ -1,72 +0,0 @@ - - - - {$_("login.title")} - {$_("app")} - - -
      -
      -
      -
      - -
      -
      -
      -

      - {$_("login.sub_title")} -

      - - - -
      - -
      -
      -
      diff --git a/client/kit/static/images/icons/android-icon-144x144.png b/client/kit/static/images/icons/android-icon-144x144.png deleted file mode 100644 index 2cf1be22811ffd3819be1b017386869e700d7ae6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9773 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 diff --git a/client/kit/static/images/icons/android-icon-36x36.png b/client/kit/static/images/icons/android-icon-36x36.png deleted file mode 100644 index f6afdb92cfa8c7bcbd705ea2184c0ad7c9e06bb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2108 zcmZ{m3pAAL8ppqKiFP)}B{IaMlrR@&%oq$akzt~7r!Wn3%`nUiBH7p`mpXLhRxUMZ z*w)lk+95(*O{U0Dzez0DuDp^kd7Ld>p}sY6RKc6Q@goR3!_Mtrrg0Hn^?S&=yPoP^Ab;W~R&UDn zuPrG#@Kr@Ec9U(JVzsrc^NEb&Y0;{5G>_c-yZVfwEz~*HD@9*m&<;a|bscv=<1GfW z4RFPU%jkQ8VQjvuyFqb@fj?AbrJ4JAzbt#wGaO$r#ouv&?74a#E{_r4_f5$xVfr3W zJ+Ve5iUP|ToY&t)S`el~I#^~wFiQ)9I?Ofu8x=(K&pGgxpV2 z0raQgweLnH5BV)(Q1p&_(Vj-?#@dsh$7Qe(}7OyrU0qDH#vPau#8-*eDL69l48@r-m3CYS;Mgg z3iQSG;M}YvJj85l4!*b@de~ETjTdXy*3m&PklOkkP*!UHcw$GWWV!C;+n0xOsx1{A z-1CyHaDlK*<>kz6WL*-ke1exgJ6Y?YlKFw##?Q@W{lW*%adr;5zPK0G-NSA@xU z#fqNsotkbLcf%vOw_$U7pIdOwogMV?^zaee!!4`Pd7WqDHa4}ovww+nkH0VfAhMcB zuWC2$Q-*u*4yiqy5`5*04!`Jr(a-178ni-u3qF5X;m2fLkHgwW*DlZU)9W2?SE-p! zU=YT`kPnPP*nDU&(IT@z*dVPp&P{+waLq$?wo@v(sn48JV~@@ zSW2b`^*g<1i(zVddGHF(xHZ`%266O-S--+ZFxTI0M+@` zqEKD=*yNLKtBp;MM?aUTiJyjCP1n-BYIm*NzQ<4J98K?KH#GnB-e^eJ-KczgZq-1z zzP3~R$df;-xUZD@hTzqe)p)O@Kz2V$(Lb{pKwi)cQ`;MTs_sw4xjYS0{ve&2{xRs> zyo}OmHZ1?BnOLk~OI>hUL@2wlK%z*>ucn(QTJdkuDx&EpbC;ggH{u*R{f0S4lDgkv&;$n~l=AZROi!!4o+9K9Lrf?e)oGj_tpW3{aPpXG> z$KMW<+H751dU!f7%P@b}I|cjOPs*`S{3)sfo`Bw+~CZmb<$3+2q?8+z+R-fkRvSD6NO@~pvkf0taX)MQg z1S3{lc0icFLOw{Z3>>w3sO{+B)P4*hET!nn3f>y3tj4cxP3`HNT--QJDHwz4e7hc6 zaxlTJF?9~sKeosDf_*oazIf(&BvsdXc*5>d2_5RaaoKqDg9UE$)29L>~sp^l1RF-4OuT2&& zPrFc^jVAdu#qZ?LY<#Gtv(VG_5ru* zyD-nugFQQt)Xc2?HSET%)FMo5(VG-hH_?jh0$Jfgaw+=H>$_?ksDkF!9P=&3+N==I z-Z4l9Nqz8iU3nFlZz~!_tZgBAP$w_;HdM0D?#? zyoCP1^9XZOb(X;em*=pM#$x{;7nQqCz2N75mP?dvk diff --git a/client/kit/static/images/icons/android-icon-48x48.png b/client/kit/static/images/icons/android-icon-48x48.png deleted file mode 100644 index 2b402dad7f06b811a5dc0110060551cb29cfa6cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2721 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 diff --git a/client/kit/static/images/icons/favicon.ico b/client/kit/static/images/icons/favicon.ico deleted file mode 100644 index 5b6cfe2152ba828d00eb9dc8661ea71298053d42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmbVMOK;Oa5H=DwE)@sP9QkSdA8tGam5_*30YVh1s#*aRrGf(wHI4FY{77OuYsc{; zj@S0btasP65+}x5&w6IQZyvjeVcei+XUCxTUE}^u!?G7R$Fz9m=l zO)n^^As_Ks)*R#TH@f~Qy6z`f;V;y6)kI2NE0k0Msl`o9oDN%_9Qj4n{sWn-4SlAD(sOy)-zO!ts&7A=q1ToQkueMerVEpFs~M$dka zEN9ZD@}(OW{m~1!?nz@`lYc;1A-blb%rN!7z@xsGRFC#u?R_%d1uxc!s1`H$*~W+s zC%i*5SQ0*r`pPH!s8w$Z`z?xXfGC^8Twc%5c?xrO2u5cxzU&~P8gy-1d-iK^flnP+ zG&dpIS5+LYe}*)*;8Pv_-UDoDzA{G6mN|qk0<0;IdN-Az`O2 zMg_@pQ?o0J6#{1u%z8!rF%+4D<#ZRT#Xc(f4K&ik>N+)xK7VP?lM&&bgPAW;Z03J) NDvw6#|AGJ2e*k~x)Oi2^ diff --git a/client/kit/static/images/login-office.jpeg b/client/kit/static/images/login-office.jpeg deleted file mode 100644 index 6414d4902b5708ae9619d91b9728bdbe207ce9f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37749 zcmb@tc|4Tg`!IeJWvdwbQW!I`3>qm*F_y86ku7^7hU{d^z9h-c3dat+{x(yz{%OeO;=Ts$H>@(=iE<#3}6S&0D^$D z1@V|B2-@w$M8xT1y>wlZ4ENB@0|3ZOL73LdC+UbN{CK2d?{@Mo(7>O!EnZ6orkqI*nR-O7y-a3P5&wVzqI-hV$jGNG`;Q|dKSM!z_8b-U$q#_)AM`QaL_|4DyTAYvkBCAfA&3YD z3PMWC3@ns7nogLq_5FLxFl6L}E0TczIN8p}a&1{CNim9+MVsOcJVg6399;p`3r8Zc z5GGZGYFfwV=z6^*s)%CmUX>hMq;Iz$ZvL54wcEiDN! z!UQ~p?+jD>)DE-IU?gQE3k#fwf{a2wG>MlQL7+gR@oXur;RHs`Xnv}cZ)`cVNMu}X zmVL;_ZWaU(4AnJKpx~v)Sydp7MQ^BK7-CX#!=rU#T2o+k?Fi~<9E02_7AsI-`7}`; zi!j2dRZt{RTcYc}W1yWCXf-?x!wbRCVV+vH!7LpxqO{vJ-TF+*#+G=?Tq8tCD^ZUp zyn>h7H55yy!!``FR6#h_buloq5gv}L>458Xk^BoU&nt`U^*0fB{Nk;Q~6(zjwP z8JS=>=qF1)PGnsUn+7Hl18eVMdp7{rS7$ORP^5*^Lt85Z;RFJeB9@mv)H1#es>Fnj zV2BygRl~tlqzIU}5fkm~SLl~ykZ^jqWkoAB6)zlzfWq4+3C0mHBpMm2aaNM4eXs0gzPSA*SeoV>e0@UoRLr! zs1kEKlwXnw1JO_;@QWWMVf6|?rN$HbMxF4HLL--ffq@F+idIu=4ddfz#fdT^=yZ*v zajr-rF4i1pE2xeT0;qU+g&0_<6d;q~N(>ATg_t%(w4)M3bREcW8oI~|CECDuUy4L1 zm9ezs6zZXRP(5^kFkN{$PXt0ml93^TKBe?JEEU6+l9KXDyo(yjZEkBKV2rNiAR0Yw z#Zp@uNQ9^2te^(sQx@T^(O_#rBa8+ZplG5cKDzAzIF9C}RU!hE08fY!ks9$Pp5C&8 z0W$UAI&UNz8xxOb(Th)Jv&2MPC9;u_6_{-y5kVbwb*v~agB68h>tjf(F$04u#^{w) zAALAXIl>Yf-fsHfhK3GQ<@(di``IPTB1r-iL|DZnRTN}ONc09<#m5#-R<_WTDV7#a zDzJv=a#)3_6;2e1tjk7{xZH-euPgCdBeL$J%fTjvuobcmBjD{_7Lk1H(c+;BbdJTk zcq@z*0f~pA->%=+Dl60%pwT-k5sqdcV-SL+TEfa*AsC1nwGdAfwJ@iUA}j)#G7M#8 zWNJ3cE__M}C&JP3p$tM;wtilUB%bz3Py=M=R*)kUtaxyAx*C>>XiH3By|R9iaw0hu zo*u2NAub<5!OF(=6B*v#`sz9@gQZ@vV?~#1d^;P?3gpB zDb=IkXqbi$k{_mF7peMzpEutH#V;M|mg^z$RSfyetp=vlH+@iG0A+E3$=lbfpygDI)BLa#}<|Ho``j4XX}c_vTLk+ziV52 zXSlN3!FAui*9Mij?RNW;d9eR@)@D%c#B`9z38202{hpiz!Nc(|6=7I-8!SS6|E;w; zOJtT4DQ*Mx;hk5|v;8ah-Puj<<)FO1j3+EopI}igtP^*S6V{u*Hi@+cx$Mi8-JyHP z`eM(0i#z0KcJ37_J>c1T=E$+%{`hiW(7O2os&Wd-LPO-o#HifB(CN5Fu(k7X#(f*X z+G=;|Tf2SU2*mErrtX=Ir_LR}JTT8c82>CMeDTh5U{5U4hUC{Qc-UMt=NEKiVE;;c zkfPss4lYDANcu2+d@%@pq=_PNTWmZJ5T@594OQnkmq6h zBY1aQIzV|E0<=Fag$M;;4NF!Y3Ju**qwWVHL%Fa3yH6`BSgU{?2M#_96G|qaa)m^9f-1 z@ThitB2*p`oh#oW7+p&)Pe9{C(V6CYR@wc1hOjj`$zLe)!zsDrxR={Ur5EMM=j2$IffwlY3*m zx%=Gddzm-UEt}^3CxH6Vl}&8u#tFc3NLs&q@tWDCqg!U8hkG*3TE|b19DY_hyruFGjyfi#V~E&aSopfy zVE=ib!?b^<Ib!VuIJ5Trt(@5V4e`w*Ev?MvxxkjC zccgswk-eSi@pBV%>v9d<6NepIDD&#x?GvE%xM|t9Vp;(Kqe4H9B!P1ni&SoVZ>fG& zRaIUdYeR)akwLnQr^8T@L5bVVfX0U%4Sl_re7D>;=K69pV>ldanu$_7`{^RS^?SFL z%qVJTMEBwjtnjTO%~=Vdcv~x*Dx@vx~$gITM)a$@|Dt2787H5_bXm*c7dT+0O3m4#&fY=rlj){Pz zeB-5NQHX+ATAcf4Qe@{8g|*XoUKOp|AI^>**;I zd6!=sCgrp#^XR9Z+kjE|4V}29L-mLvKLjkTuIGEp3gTo*4DvtT{m#V z6TsojgP!Q}B-k4)BALUIPT&J*j3O?U)DTN_`%84L*=Z~72V=cN z5+J^#qXrhILnDSl-FV$SQ9@j5xHjTmDb$_JP7s2!s0~>eLo5S)OY}u_`v=cw@}?cL;^l!UGen^z<-lre2WxO;oV5>n z8Xh@z|19ZbF*a&rvHS-4q^q{Sm6xY4l2^#?TWJ=<^>g3T9^`zweVNsE%jKo9j`ODb z(jeW!jAuP9uC~m{n!P{{r^vX^CM2{(dnpy z@&i)xcDmnc2m3Sgg8r8CGCq5obF+i)Bc6*X_FI8*d9fT-?(Xh$v!`M~WSf%c@u`>} zuMO-uxYm0s6-Gm3xr&Dsu(cjhg~-c?@*#36^Uupj*HqzUt9gw5zrR$~YC8nZ>u7a{%p6Wc>*VotJJUVQX6k@C!CP{}5 z#lw#1@+bu;3vZ`$Y=Z21+Ts$Et#`>~Tvi>I0(>+)ZD(f(@^#97%y-avE@UKUrF9sh zB*i2p#csr!eVR_03X6W&zBJryqcZx!{qr!d zHm&F+U|_A$MqQ=2uxnfo*m(D;^$PRyikyl|NC;2c-!tHNWhNxN(8~PdX;b^?XryLm zHkPA)ufD#1uWG7e&gpJO&%5!0G*EWTbdtf(nr zW+H@lut&&6sORbaxN9)tYyc|87s<(S&pvNR`OKDYHjQ$+e;$(_EH479ONi>-xK#vF z%0}~Ot?>hf+$+kW7pfB?a3k%>#KKQgzPZ{NGFk=5hUr_$>=2K>6eSMQc zlaBKy9`hfFpO&bxu^CP>9=3z|W&r_5H^ohhgu`Uk`g&Ss_r`2qwDc?mT*(=1xT%LQ z3f332C671a))gpZ%8sN#Q@mCr$3Uqlq9gdFEFyWLt-`|zFiQo1>M>M4dEvEo9upuC zOa)LprlQh?p~GPz;JOD&A0J_b2Fa-?mn5H^B%lnC17s|%6l4N~4^&VHH3b8d96=4i z@C%^*JhJ2kbp+)@jQ|F5Dtds2UKa*|(yP^wU<8b_Rmv2Sz$5FH$V3A$L*BzFjM;f0 z%mDd$BO9V5lnPnZJ*}4V3E4vTaHvf6#=A0{v(!|qxM@ks)Z$ZZCINLafC#2G0*gJI zU8z|}7TgVDT|Q#gt|_ij3+>=?9RjtH`?~Aus#}1~x2Z684`&iM(b)|yKhaH@JMT3YU|MisM#eJ z2A+Kh`Jyi%Kp!6r4dxXx0wRq!4pGKMOeEB7V43PhZ^=e z(ASfnkQvoGF+F+2w{*l_cHZ}N_A&1lv`)DE55{Zk^$WN^JJt6YJSIoE**!+kUBc%0(-~9noO!4Kx#J1We{KDey{sv7{2)J zli`y7A&Y2WKXtG&b_9<0o8W8=D=Y-TQoh@3IP#S+QYqW~_&9kzDD?n!X)&;JX=ih3 zIK%G-hUIEoEI3sdlyFG6+5MiK8R+;ONZPCiCr*PBU)L5*l+isSpYi8D?}9QveCQSR z8F3>C6SWA3aZ}PL`Qsl)!Ve4z3lw0HRrHDZ`1NrI;#onr;Yw7@5@_Uok`+r{I`SG@ znIEl{O~twr%5h;btAjUz7rnPbvsDmZ(aHTiB?lxd?cU1g`K{(xsH}jPR1={BfQih^d={1Mb-yl$xqG%Uh;{Y^ zAb9#`<{h9K=2k{4Z>_(7ifH>o2<2%m2i{~ZF`9{ zJltrw#r&`L6U~+07!+-ch;QKm+1y3i58jyHkWx}yt&xTL9(sQ?W zHn2D3h<4lDp*jD7pLj$hvV-pGV9}+&THI%EYjLP&Wa~LAoc0*@RtT~fi}+m>QGVd5pLlII7B7hAVt~ihMtXlGj=3- z-59%=dHis_L8jL6Gby|sf&+~Z58K(T=D_`<1ChciDr*s`6M*^X%pW9<4d-m27hN%2 z8}#JZF|ecMpkwUdQo}Z+{B(A5IF(Qd(8&HhJ==20|G0Va(jCw&wr?>g_5i)+w?)o= zHR~=La_)Pz&noksTdAW}q$a{jd_Cs+l9y419!uRLSd4m++!=7mHXez2igC+Is&^d8 zoJ2`ZgItyo_Jfg~|C$*`)kMB#j0rdi?o}p4}V$>BK>hH}L^``wuB7@R!J z+>k4c8MdmMlsU>&`nGelf*aWs&&JILI_zIQtmqyTnl6hzEZVt8sEK>HM#!0`me|>%+C*eh=8JpHO*^x53t6*2y>;}p-I=Jg}e^w0F_YD3zG~c+v zx#Jr+TfO8bH&nUgye{js-?-wKHf9(z=|9`$U-s>|WyQm>mmlj?FLBJbaQs@M7_Cm` ztXzwzFw%)_GD-ngDWJufX_hYILa4IJ`Zd1#A#_PCtE8u1&N!W=byxROCkTmBo;5aDh zG@PL?s+*WsZ>OkB=kWvQ6mIY{MfkrB* zGZtG`C=Co{8y*faa@t6yPJ0JRKArS2Q*GTfHLvvza$hq?HVb$B_OJbVoW37dJ=6?N zJ8t#%$Hs>@cgA1uqg;l^V}~C(&T+4Zrt)m%cr-mC#1J6qGyLX#E9iyhC1G6?8TwCa_wp{YIA1Kl+ zC^A5K&>DbjI~L&I%(Vw|btzl&J#KDT_Pg9s{%3Qd?EEd$TcBGU9Uq_f4R8*0mg7c| z)*4+H%jV@8mIJWUyLE1B8xxDi;uP&-x&%44DuKJJab*jstA z8tC=g|DtearP-g2E!mZq`(j|#vb`?DOLo&U6B~zRe1=*swVSeOmzsuV4^4xNHyTAX zz{!oXXL^u-bVS5y`=}|?(?CeKTR&TyCm5DRQPGyDjwoX~?K03AP{%~sUk>%V-Z%f$&Z&$ay z{pKw4$F$1CJb8L5W6KW+qY7hmjnK>NZpGVyhL1PQ#WuJlH&9nL%$%btoktHEntHQ# znpWJ0_FdjIX9Qk55}VyUyc~2c^SAdqu@^;NUIi-wV&9GsL$#Z4BZUyzZExOCTV@Hh zg#w{jt_AUlXLSXI?uuT!pv5?StU7h9G!tmvF)@2LW94qn61cC^w{5Q9FuFfpxG$Ew zyq!QT;RCmLlNkxwOXYNxbw+$wvq zml?Ciov`PUIllhms@KCMl3Yec^WAy5%0;>4@qID#9MyA46MNi!Ux^8VIu?ook?L3` z`2zB6UBnxH9qaZ*rgmhdVPtoZ#LM--pRvsmb9=sb1&f6Tp4pUFE{N zxVfgd0ZPh5<=l$AU}Fn`Hx*OXQPA#Wj;HDsw2@dL9g1>Sm}QN|H>(cAnBNcmPk<-j zww2_s!||BkYisLvAFca_hmNzbB1VFgq7q3K7C24=fH)-{VfoS68cw8*X%oGn&A@_% z;o!O@QEcTy5^Fw}S$q9wKlzuDb_2c6q4p~=_Tr&}c98DKH!RfFp*0k=F+@E?xuB>d z6GD_%m(E#S4g25@!v3QXQRC{&hQC(ET2PjKH?5^9A(zCi{Inu3l-&4%4xGXWp2Q4? zhvN~s8d*?SGCQoh7^{YSQ=@VjpU9+thm%6*e)dabIg>_i#V}QYBRZD`4~45IF(NQ< zi>ry<%v7ejELNLXp(tx|1_5nAIkcjUhiJqoNDH1v7$J)hrgsFb!z(^scMz%Q(t&hB ztrrA@lHe6a3I;~%M$`|Cz6(Z@sI4E1gi;w(QzdHTnmQU);Bvc3yfH}-Qw^I+b%Amr zilhhHRDwdx5W;))5M!c5s1ZC0YU)^F9TWb>vbfx#gVU11wXT$30zC3$KRxUO-M{CZ z;P>y5=ilSb)AM@ZJ@``afF5{I1v>B$7$DO-g(yyAXu8#RDmxU)hYBhlYHG5yJb%H{ zl>bGNk^cutCIG;DyFJxk{ukP+jOW{#2@3vwvq^U^{&r2YCEMVUHu6RY3jT3=Wl z1AqSy3PV1qkzHjBWBMnk@kG8`q(E0e9z0N&2lP56=$`%?BD2Pvk?%A~g0Z|jjr<#o zH%WqW6w}6rv#*r-#05<^g8N6aeB1;z;c}OrY2v8D~c?vk{St>ay1s5>@{%?tc$ebBK=D;wcPlsavlk0#J5V;Qul{-#JJle zx>+7(r)vIdubkefohL6Z8cK>twGVzUde6b2@)|_vk;W{$orTpCc{Y=m000pg{8sYy z)2E13c!|D|Mljedu%@1x#k-@apE)rldY^qxQA8th%BVBKzW45yTub|XdJlsF2nGO{ z{ymSe#+P6)7z_dAY73yB^p~M1&IbdKmw)+{{tPH7Z2vz&`70@Z1?9{svrcM*9_Zw$ zcqIM>Dd_(NdB}MrUjB^-=*j5+1*yoWuFL;}B?r|01t|dNzaTjfa^s(PaMR++f06?7 z>i;iDMK1B5cp${+cJO~-9;$yh0PGSF^KU#n_%=YM4HyCJU?e;^1~_x8cIcTa`S%`b ziFdNT^$WoOJ$W$s+M4m)N~x@ja)!UlrG2`+hV2cX{e4$3k30>)-fkv(95~vzx4k2F z#Tb4q6P2HFbJi~yyg4BOaC{aMHQM$Zhu@wvyj8!*-cgD`SkQC0*o-FK|@+#QD+^`&Pt_Sw0+if{_>a`WJJF zd~ z@-M~6=mh{u^;3|FUYl1QAnyhMLdqaOhtGrE79eK=lUd(>@Tu(!8oGGR4b~q4Q%ipY z2q-7<PdBu^mdFYM08IimsQD5g^AfB?Q)JL0Y zFjX)7M^~Gj@&kw0FV9+&IhDEv^A|qI=Cihm{6d}ns7QcOg3Qpk`{mha9q0|=Tk0%> zHIa1PfIvkywR3I{l+U6d*0*Mmh4Yh;jRJYM5E*5S<@fNIrxnwc1~VQJc<=815qUJv z+lssV9*Sz;P11Hslwkl>gd4yNE%}z(T})K#j}!tsO8G=U;8oN$cb4}8FToJld5C-q^2goSM&QO3CY`{x4VC-M{VW0#cj7&UN<>{I4Yd<_29RL15H*Lts z$xnbuYTf3xG%xw%;Q0bnmutW}SE#w0(6M=-aAupx^SzSKFNViq8ghN8@2Zoil(f2HR=Q(JW%6j@5gr9DdkNVV?Z%+E+^Mx`&BZzYVceXQm$>{%n}Mt?!iP^Vg&spImFOmieZ0!QR6A?L!z2VL=hpnq_Upo#ITh~tcQ5A8axUD7 zW{`SBv8_8P%=DYud~GdszYTXmY#|JRQ;}Q@OtWN+LSIeXcJkv|W-wBUooD)BP3x)7 zTrTow!Y)iZBw-J|Z+9tpzeTC0X3h2C>YD4HVSUWu>rJso)4oZo8GSEZzHld9_ATtc z`7CyMMK7c8chkYnTws>m+W?uuFNbv-hTQ?Ki*cm1qG+(Zg3)U7QRpIBS=iqZ(kvZ_U&dZ#WLu6jogfCSY_)AG}H$Za9wAI_U?h z)U2&NTyy;!(API8a^YrWWxaS#tADcz#qy)D^he3PVI3V9{==77RB>&UPJg@WZ@6M# z`2Tf9$G^w_l%4<){*Qn8>zk*#S^CY?wI&wrK2yE>0zXpId?PPiV(1|rW>1^hCWE4D zUOhK!>Vw$%ZPrGuq@%|@GyZn@Xdq|!Qr}*`52wS23guPgca0);#^6BIX&iEO1{3PydqwWtoNFd}ws^GEU*GKQSMO4#1UHdFQO*e&TYN#l>XX;o`RkJBj zt1+^#s$woqq^rnpQKd5W%Xof{(EjP-#PgAK=J08^Ju2PTPgQN;hlAReV~(nBSs^DF zgQ&o!?G>!u!(_H>!q+QbX4g!;Zr9FFFaF$ z6M%ZJ1ihJ@?@{qN!ba`Oc3G2h*pWU(2#r<8_G8QYatE>N<=g`@9yedncye7)+SU0Y z8?2Yauf)296uID6VIxWVO&hs}KR|769(--KPOi1Wnwx-eMkRR^XWmHwFD(<|dscd|`cL1YQ`&-D@-#>6A>R5Sn z-!W&L$KT19r-PrzrPaWSJ?OsM6`lvl#q%a6X+ELpth!U0<^+weRRiYCHAR!lM^V$W z3(|XHE*H<8J9qJNz3*cl;hKYC)m17=lhXc5o*wBl1ZhUeR897<`^lGx10Rsp9eT>D z+IJT^S)VJp#*as*vTIjO58xTm@xPZw%38d^Wck}EzOo;^-)$I*wed$|~?5$dk%Jlmx)1I^ZHtuItq@_Y95~4M(j{PWHefw;! z(81e1;URCIg!NfH>$4hG?egjuoX49zcSe^-yGXr*o&hf3x#ETcGKY`ye*}O}*+@X` z2;J+hhzP?j#T;9)U)vRN>P_U5%p&}fDtwysFQ%Y)aJ}VVa({ZY=`hirz%7hUO^Y*=uqgOL9X?VTMa` ztr|0>qM5mK?;58xC8jjaFvw_3TWPO+d_Mf6Uo~L#z+OFF{L|J9Yoh0-!z;GdiGgRD z$g3?kZ!8s-O|T478|7IrhZvkU^2F(Ly?Q6o`Z7gNk2iaF@-6 zI?KLzv{ZPESIib>dzcUQ=%X;?HO>83iJlF~De9UE(t0!Prq(KIT979VrFHx6bnm66 zV&)MTMn;}kk$Zv_^y#b@YS)oiDxjr#TiPO--6DaV3?ch&n?=Uy`IsCHN8c60<{$yT%-0LjwM?rXjWW~1zvgy> zRF$8Q89lu}7-GP1TE^1eJ54iJ__YKAyAF|ECrL$KM6;{wI#E4wIMQ{NeM^sP&bP19OL(+FLo=}37i8_v-T@;)R%R$5}_?Con$Cj4Gk zSPESnI{sZlObcz~c%$ATe0fAH-^rlNbD?k#9r{UASsFcaRzZBP`Mqt&JRLLc0qn zN%+_1JA(pkzBP)xqvUU;IoT(`>qoT4Z7b^~1`RQ47Yw3$^vuTVIb46JI~X4ctqQ4z zzSg@8zY;<1?8_yz2)*`)6cny*Xcw)s#2GLW(ir{i<1R;E19#v~q5aqEg{+@V^!WVX zwk40qqjmR95TUhp}h7Tq*Q>J9CRB{7)7cm^=T)*wnOWXx>I!bA!Duv(tj#D+X>^a0# zif(Xv2rTle(B3~HB(z2fb|?zcyqfv>@gVhF_;b-hN!gItf$~RDGk*LzZd`d)c~p?X zm6rM#H9{UQ76(`H%D&E*ulvKSR7Fgs{hl%_Ym=TIW>L0nTtmT9$5ffM^-jibQ&OL6 zmEUktU4kE`ot4=-{ChhoLU-6z-8&lBdaPrvq`9bPC#X5RIv4-^+A_z(xNK| zzVFC#-}jSA!}+k5eVywDg>ZwskNLFkl3d(H-i%gNi_BzA>Uoz(zb=PI(BMVAo^PSE zm09P}2G3qqSrIqQnuhN?j$~;jwf%qxesqI9a%seH-d4NEq^IQ|`1O13!60w7aA&PY zc$Z^e#a8xGbdvN~Ekh9}X@R50;Vr9K)bykH*Whk=i2fCyqVo^zw=FUKhDRcrcl&I- z=^JoYF6Su!sk8kS;oe-|^ixsioknE`d7_u<7=}jcetSmxTTxCimXrd|8-BHT;`bF{ z<5^eD>;?W9Ro~I3qpaJoZMjen!TGl)H_RMw zn#~AF$PkKd4pSAa@ol!6Z5q$KqpFaD^nT4l7;B~CXKlvrwToKb`jr1dptzed{b3@J z!i}|A#cwj|reIUQ)tgj(%gABq5ZDtk9QLjA~)a#jtC7bYytVc0O>Z98uUtd+HERU=-be#Kg+pIA?`{)GF zd0jND+dOiS#C!W5^U6oxZYjIrq8UlYAnn(G?wTpNm;|P`{(6}(-gp9lcVtB*wG`K* zCcFl^7z-*m>%&{>mlU{X_zqs2OC6~P*H(gqk!!u9=xfUG)=25Z{iwubLES^zoxMbh zgK70wKQfQ74P{OzK&OE0$I$CKmCApXPy*l5_q^*K=$fkKe9~PI)iupCd+Kaib`75C z`udI^+w&%rSmIa-N*6iOG&|-eG&E^W+w=TJPEF4{ts$7eY+Y4tR0j45H}-B+RadOm zax~Q~cYM^m%OLGy1y#07yf^=|O*qF8yq!=qQ*he>yBd{IHCEMl@ibEfn5kHIHTD{D zG)^<$9+iIr+~W9>i=fU{;=H0RQ!&DTG0RL)Omj)7E3rEeJT|6reJlLI(f6k6mi564 z|6~)dnTh9KC2W^_#+tRBMZFIuMktJh_c(5@E3+0*mfZ@QDKlQgB3Pe%cj@~fmT=Vb z4qHUgF!R&#x}5FON1YxgU2!wW5s@VItz47wx0$4fYo?AMK5twao@{;d%Z1R!>5@V z3+dLM0GGu*#(EX6v-E1Qvb`FqXI>IB2 z=QT5xqbn({H{-q*E4nG@NbH!j(^*7BZYP)B8|8wk2+b8GM^-p2zP3#|cou&cWgsWM zge;;>6>_WJwY$Y`yej@>^)N{~zC80+&JK&`doemfQ<5-tczEbATz3guee2Mk)FtM% zyI9p;?E9-r(NJz%>#Tu4T~S{U-)zJMw>aI9Uuc%O(%;CtMtR1?w=M|@J0C_Vmn`b} zR;{81I}C(oHktd@;Rdn~t+JQ>j=Gxqti9fMA5r6AO6=m#%>QPms%JgUmbO)Dez5XL zIx!g{@LP%h7Su3+CSj~c2L%wC5(-4rX?9ZCWPRgI0*#)gRI-M?Gs9?>3=ut_Yzc@` zC_7^t!mKY_hVbIQyw>+lx{OHaZ~CJceLby)X$qrx6z8fbfzw^ws%1!*>Ry_Q6!YS3 zZGM-hT3jLgqcjO)-$J37<{YXS0!4JBiazJo*{xC%Kd0!!tUjvVq#oL31*#cFp<-hr zqQGO;`kf)w?wnMNE0ky@F2gLtY|bDF))s}%;7fDyF;o6L3D?3M$?hc0SVg-mO`2Q9 zNXizB>6`!;IW+ys5%1dW_~C87>I|9`oq-m2G5V1jS`%EztCGGv!QQ&vRAQOY_U9GB zIPn_cmrq@)1Xo+?0p0u(*G*<$X? zWyu7mFX6wHT{GQbYnEYadS1-z)IDwL+f`6XWpm5#=2{kVPkL9CSnlL=;%_^f2sP4b zys@q@692lBgv8SsD=;Nf5ie~wNvmFWbr^EdCl!hy$MO%e9em@~pLWf42l;MVNgr8? zdIwGDI49>usZVAeCw<%V%{EquN?5-$gIALFW#Vq*Iflt%*X8_G=0Fo6|GWiM(jF@*Fi+H& z#U^SKQ5Hk*m)jK3SqaVcjo4vT?OGAzkq?@*If&KQA@5bpAtX44S$SxYH+&!#JggXk zR*v)HpdpCG(A+xhiZuqme#H8?y4=&4!<)^PJx>V7Y7_e4&H19xNs`IWat+NJ-AlV9(=v|%07yaAu(;dXFX@^9{3c$mi>9{ zvGN2YSxC?g8Yid<#dB?{WuWnPVe_3;9ljd*ZLAQ+BXKPaV}XMqQk^1ev^Ph?fWQXy z8B(q5Le2^cVKkoA@X#upHyVj}8Zi*j^ge`R8 zB^E3uLm#cJ-=)QkYeW#(;i>wroh6_34zwy@(kM80UFAlid8?woS~G&7W=4Ri zk_9)XCyXE|wkzkklEA)1K)=^DQ|1d)cn=&Vu0`W*{LS*Don5UiQ}WAuvqT02xk(j8 zZSr4l{#kE}MMuVoD}H*0R87hHq&+L>o~n^yo1v;GcR8)Ljm2hl(m2or0Zw2{$uulx z?yMmKvYV5}+%3w<{LKU+BmR~UOEjFtWbclMZ~(vF-3h*(zQ9F1)G7?~K;P6&*gZ*Z zKnj}4C*X-VoVoHgo5ev@ksX>05-~yxNmq91vvR4__(68XIJwlTNSE*@AE=$ZAOnw< zSUWN2mst>Dw-Y|XHLRIbIodMWyNFtKPR$rSKAgxOtnwhYEv>KwQ@?;mc3ezeu%uu#& z*FV6xWphPmeXZPJGUwp?RE3E2ValL*n4qlOsyB1ZZ2FE*^a1{|hwfe`p(k^?;wVq7 zDo#tsV~bTwSC&c+5;bA=H2s$nH6{qI|F%d(I4Pk$Re8mb30@x)n934svjr8DV=~Tc zQO2((UVETVvx^b`_C}*hEUc?!)n+BJ(5yrwnmLrnQDog4V}4ePth4q*iEl=lymqs4=9IAl%`Rde5bvFumW$G){w934Pgl zzw3TCiM--{0shZKg9GRIvQvL-ZbWndrj%c==OWXcHm1vP$yU$Pg2-R64wZLiU9W-P zg7w{@&hD?fBSJgT>H4~QN;v#LwIHD7a&n%nRTmwhE#dc-FQ4Jis7c%lp zfonI>)3w`~GiS)p{{8#w-?bY9FH(V?N5{hT@m0M1{jBm2ecBVNYY*Q9|GPnt;ynR= zIiL=&WS#&qSu)^m{pu@93)EF&7U|AzX^3UvSWS6Jq_YaV{PCMni;)>U?WXc}Hc0rm z(%q0bpJJrF6&pG_^MfQO%L`Zu7bgxmFkd9}3jMn^@g6Py!B<%UauJs&V>j&jLL#R{ zQp|LPS8~Ax$FIf_{wV3B&yuT3xG;9KYPmH6q@0Rv~V~bmuHFTK@JEamykI zW?`lrlWDrf@Wia}L(w*k%L#WPV@tm%JP~*s`XJrI2}8xNtEco;yhEAhUe>j0OY`t(4xEj zp2%tNfvyC z-u=1jUkXQFd)v6B=_e(I{{s_-9QzOUcw5+$fd7f^`PuWzz_Bo})frL3gcugfm1cAJsPq?n3@no^IK zSKPpx<431za1hTc^sb5`XEsEz)Ag}}uY)LPF_{bJsHLmkLq9i-ou@C;&6n)iO>1UA z=NBYYGtYUYKjhWIBMcu7hwF>Bg0e*D8GN5|w0kIrTs!w+o163d2@oIDDRU=_8}Nt9 z@Q8KS#;X)Nrf&+qp_{d5v?72xtr9Aze0g4Wdxc&x_`4>Q> zXR}kW9|Lm)9geM4jsD(xQv+MO>>HJE0d>TWO^x(uT;C!Ey~@6&pV8@3^n3LcOh0B% zrN`*YmoMMi)kcJrzTllV6~L2o3FO@O&AgZS8h;caJO%guu3Tf#XTh8JgN*B`U`+(X z&!^R=OWN@7)dX~_Nb#w)SmNyfUiHU|WA0 zrPG9QMhr3-7=a%HJACn|9htS{Ce5d)xJhfoV{2;*_HJG+44%6PBT~~V=;nawW6!n- zBv``I!TK3tgg^~LmSP-tZWGPVc9en2%bIeqAzxb6E_#5qgN4eJP3BJ(4@Ud_3JJ|> zBLCSgdpTYup(%6+?DOT0ISedF^a^ETf0#o8m zj&f()49p4rOOa=DamFw_1tTL&BQrdxqr|9PcD+h1n~EodibwH#J92I_24)QYO`k_T z9FKf@+KqN(Oq`ZH)w!xOCL99>xoTlbyz$4>;KB_YXB^uWo*bqY&!ehn`HhN$gRQ;2 zwOT#`LUH|yBAVfpPBB@px9GqQEnr{?b6-LgdFjK^R18r0#}HTm_g(@_jaV&?7H@6^ zJH+<=`zE^sTvoi((!!p;1_`p6qoXfdPLa4tgsiXwCtF8W%-lzCQwECOiiijurvZLJ z{-G2`E)mK=^_ZOdgIbHu>%C{4a(4)BnlGIz8EvQQ_!=Og+4tyG>c~Akv%d1&xN)`R zOBNmxZOTS6@tCBNkIj7#vLO!VN2cC&{}Q6Q255K|`C>Uxmu*br`=ld}n!gGWGDX=JB`X*x-L8X2A|6%Go;Mt72 zxD_Qz%vy;RVzf0%iPkK!Viv7YMTuRzN^8~%L6A_h_O88G?O0tBtFelr)izaCd-Y4- z_x--#$76HvbFXvHJ@^0rpYzaZIEAOn-51%&3=)i8EGhR#C_}@KIi>tH!4iL|p65~i z4MPm$hT4~V14~IS(MC?#rto_KPLL~NN7MqWpJpe`#+z@Twk;-IJnuzNk5Eb&w8)Zc zjtzp*k8Rv)7>AjFK#&?KrBSgNi_q~3AW)7z%XASy12GV;(U4Grky(7w5Z7n@I zo1yNYsVPppJIPH(*)R~`k-lvWE zdPFBfjAZTrY6JwFr-4+bIWH_$(Xv&p0w3dU70UrtP7P15xw8QB{j{H0{PgQXFuLAX zDp$ROn)EBitHHmIa=B?9B28qb+Mo1O||s`{5$`+1KNY)-=w^jUDlNT&f-ta?V7)~ z10?TupXaY=%M?Bh^S z{Y{NTZk}!bgj9(7sv{dit4eW0lidr&6){u`ln5h{*=$vgpIo)ne<6x9*CEaGd`eQa zzJ_7!$aQZEX1*k#|L3*G%El$P53eFjI~56rnuo9y{eVO{kl3#$sK;Vj1q0KSgKs48Sv2fZ)cod^@=oLR+IuyBsi++tBLI{g;7aPOUjABKiMqggr7>jv zQSb0P|2#Rw!#G{SoSnBuO}A9Iy`#Q?#MczxC`ZTem&b-kkuMu>*s$e!Sp_4bRW%)3QbtJ5 zMFeeX#{46*GQ?yo>~3YLHhm-{b@AmS;gAzOeMf@3$ae3l9?7W@1si4Z`k4=C{k3S| z1-nzEdFh3C`4LgL*xzWG`a%V%OKWT0P(u!}^lw{3C{cF25kpY+0B)r2{-$QQC=eSs z`a;>WNCVov9GZTmsq9ISW{wma{oMzTY0==ogr_`%x*e^Wlb1R;3e(ubDHADir%0mw z1sJI@V4A?J%j89N)d?H)&htQsxD^u3dZUPyoTkGO9pC%rk$sq*7RnBTd-DIeP=O@J zYLLf!R$2emc=7E`hhEXsZOO(kc?#fgDZa_3dfcoFp_!xe;;N zRCPmtd{3>tY6QhGIdx8k9B!HUI z(bf{nWNdmU027RrU444Pe1B}tPmB?p{(g9w6z+<~8alb@8eA5xrS%J6Q7VA|5YS@; z$fxLZTi)(XMHCP>A=7C(-5Y1b2i$r>(V2H_-&&hXd%MLgPRKNQ+>n1>%Bo3me2c_D zRE_RTI9--s(;JhNB5C;3G^THln<7q{0>iK??n88 zXjgbR{w73NRHb!&)~&vWoPC1D9H1RJO zyka3c)YoVwloqlV4`pusrP4TgR>nQBBD+KW(5B@1L%w-hI(n?)B8#X#?of1Kp&ZIw zq>@aDXl|n_PR#p5SsdCZ&I??(Fg_cC=1G^1n);FF#USVEEW2so032veVB$KRHtao~ z)Iq62L#~oEZ63x@+y)yUN-0?%lP;8EFLcbKks~*dB{NTFDLoc1s>Tz^ccAw$K9VX& z{tWxJe#lk#I6HiqWbh=6s8098E#uZ4m(KomdFrl0x0$YYNatDuf2ms9V1A3UK{;{B z3|GFSHssK;+{X{SJLwgT{o7qvo6V8eeJ*MyzCTW)Ef0Xa%-jv? zMWcsuHhy~ZPph7NR>+y^}mj@h+_d|E3|1_ZP;`U>m9uud(nN-eJH227Q zMgc_hgxoOKN-nwu4^Yj)_@t8m~{!J8j8mZ4?14Ih2)R7iaISE z64S94-OQC~5ph~_6H2)+-@&}ub0>2PBygJg_zz3tL3)mK#h|oD;_CPjj5V{{h;dc$Df_6{${!2r_U5!3UH?Tj$t$%~!C7OZLfI5AVeZ4Fm1M#5Ag@Z$lv)ot`J zMUn3C+I|U@YqG@Px+7pYml!ual6&U4Vefa|H*J)`V=#wq*E1SeJU8de?TO6_0WR10 z&@FE%uA|<<9%if-J-EblLx=W{__U}l3AwL#PGb07P8E1htKt~MvzyFn;8|x}tTgsr z_~kcRuNV#c`v~Z3p0xfKGmGYIjJH68_e2_qangemJgJ_u9UuIyqNeMqH@Oxlk!k?z z)mK}Ii9BZHd9_3T@CTZf{L@^<#7w~p&T4ekrCag-@S$V$pYZi(u1AqFfOdKE+n}y% zCs5akesXj34Z(hwZ=rho6lJc!k)sdJ;`TzsL$40l_6}@bNAe3O%PU4Q?yOpXW+O{r z)Bg3#iY~x%KUe!o#8YODIr^p4pi2+wDEz@LFuUSH;>0d%`s2!Qhr-zxe2t9FoH267 z8t=|4gfWUho{&7j&Z&?@?pdg%lQ&wTPR)7X= z1V1ge>r?5qfjDL6g(jY{!R3If)DdpGL9TWH@3eu%JDMn7m9b9scMMkAofR%tZ0qpM z04D=H^C{P@2paflDD&^Fl=p18%Hwjp8cplV&*yn~8v5Nh<@?Et#2-3>v&k%_5jh24id|I4#*WznMDTSVScYi+ z2&)g#*isTlr3L-@ z_`o7!ac4VBj3%Zbt4-6=uY?J&i?s?t>77i!mSIg zxM{nvrrR!uAo^6wg*Tml8t!k!ZV9-CqrXV|iJFluq=?D-$ajvemc`fj?C9R8prxAq zqEFzm;&UmB@I^+sBy0Ucq}OyOgcwJ|PD>5Zz+5v4RD4dUjPoZ^==oCA&cwyNP>#!w z3`MTXEkH`@NxG0L&)#&vyD0k{4`2C{l6l<=;=)#G0aEEZ_f-bxlAQcM-(+yJe;mn- zhb;wMEW+Gp@a;v64!W)hJtrnD>BQtDO?YSW&q}!2ggN>b zgt!e#$HM+%=O#agI@(U;KJuK zNh>`Pzr9}-++qsOIz${btF@`R{`nHd{arQD^Yrp*YA=WSfbNI*i6M0hz+nmnCcgGR zn3$IOA58oYC8oN-#!A77O&x^(!Nf(4w+HSJw^x5Z{C^lR>tCvk0-JA7kkuvM!&sG+ zlzKBK@oKeh$H?D;>qX}@r@wtHlvE3nk3aw_7S?UB%`ld7bpdtW#6JbaXD%{`W9gKlV>U~oKqC9O=sA2(@M~8i%QW&wm{fqe21S7N zYg=$dUE{bexh|!4Z=$r1A>1>iE?BT$)f2mWwX5%Kz>_exsmmXW{!(oxC)XDp|HPTt zRDXMtU}RN!Mo$>E)Sdkvr*|rPI#|sqSV|hbw<%+Kyp@A7o!OJ4*NU?`o!L|$3X_=( zleEhfOWEc&s0p4ZBF2YDQ*0$F0@tHUICB>-W3oq63!3lod_TKcLlIR6^jYtkRH-Ev zm;AtAhuP54~0wH1b&XkO{sy+4z@gSS{9K zWV|Nj_nqSc^Y3~AVJua+B{u_aIOEK zLISwE(@snY(A%q5L_MpsX`35W(z1lnECjoBCN1XV8e5j4$!h{7yZ5-)Nl^g4&+nMO z@WxdZ6&3#vJ^tI(FBw!b(WXX9hP<|j;pXZJ$ZG@Upu~7&d~aj zX?X}>H;?<(=5gw=EoJPRDer^aC0(XPUsGwpPlFfnZ$ z&orGL_V&b(awz$a|LgY(tpz|x$MDWfycScFJdX^vh(|KUoJWQR4!;|AT~9->L5ueh zP3OQ<@sUImDC=#)S?N}j79`QH0L_hfxoNt)IZd7N3sWK&H=rlDarRCjQ4%kW z);&{peK)sIoK2wkD>hXA+C6ro`SuJ6g-o~>&^kWob0fRjZ=~u{3}Rq7h(^F@u-oXn zYFB0mh6M=47KpLm&zQ?>p!lcqVM|KcHHJMklu2P9rx{&(jw958Y)r;+HqE3xkc2iJ zi4y_Y%B;L)l8yM5obZ8*d;tVk7TB}?{@M5oUdsK6etrEl7nbz&bG@o*b2^ALccbXs z=LyM*9T_VlUh=A?by;99DXX(=gSVo_G2Kq8az2WnYG|Q{LIs%-Y}NpmQ{wNu4g!^w zGB8Rn-XBD(yuLldhqpJiLw1)78M!AGGcqAwLz39d7^knBxY+0s<3xo;YY5$p78YS6 zT$*}qysp#^8SnQT6Ch9p0%f<~`{xcllhq==SH^vq@O!r487muP*xT;+Q}_!M|5N(*So+xfkZ9?b&*az#IK2h} zVFpypM(u{}lDm9F4&jgA5tm<@J7KqbTU5;m<0R!D8H8W7eHb{2hi<)X-BPmMs6jgw zX}Pu3_g5PDD^iE*bCPh@vMIB6iKnnGTU$%b)A)wNL(_oio+g;5;uRc26WQQHzK-Sl z&S*=VYf8vi3A#I3?P5cg&5Z}T-R$h+!qB3|sW^u;x!ce!&Omk@26=r3c^Sj06>D+f zCacj(uWM|CwL!N4z@FA0T{;P2Wu_1}bw9iz9(_tPA?dFlpmk3<`6b=-66BIlk*HJm z)>Vm(040AL4O>0p@}IhY95( z-JZptzi@~wwz7A+dbP%62t==23{x9q@y)eyb$k01iw42scIU;`N(AeUvlX1~oy(P; zBQ-(TM>}KK_NJl1k;i`N7d$n2Ug91#`@bcdWaO_+)ipqd9$Z>bPR8MzG9WA~KGT^U zsaWSCmK^1lnpl+X2J``Lj=_w*-C+I>_BrboQ8EjCLP+%f3JJM%R|zSc6|0Ce=qO8M zUsq|F$2q}Q+}r{JG~E+St!q)YIi06IHe@}j%=$u@19n_I!M@Rwc*>Q(RB`Q+(%sya z2XhI!xeRRz(x|WCkqLDuBnVA$yolC0m$|mI~tW7#!JJ)IpbgGTveB}c-+3l=U z>?^5QXknG(%hMS7qEot)Q;cYHhq-MSssEWbB=$sv6(xI-eQ=P;ah%ItmZswoH@mDZ zrg1||g50}GKBQAAJt!OhVMk+ap}vpz@7>gJe4T?o;`}Y}Io+U1d}%xWik_C0d;;W}|bIzUy{!VU3kh8PRX+KLdETQ7##nNp!%b?R6H8J($ zV#K2kKdX>fkAuOA-rFxildR2Ue>ikW$5}|XZuVwceGdp@N>E=R5B#Gckq*&742A-# zmjd)+tdOOeSju;qGoR~>IX8jH3V>S;eynJMmA=yb!YtBcFmO}g%?Wd*Zy;YpjcUdr z%lRFT^Fm^Zr`u>l#3)GcVIqUf<>LEV7&Llj=9qE&D}l0cQxxI-E<=W%9!xM8Og1SL zb%0UA(8|N_HYUAHVAwA!oP0F|OmfGd%#`0g0o}#W$tHh^0st{d*Vib;IqtfpCiG() zW#v4MmsgdF_SD*su1!8QRpRktt-S3EgWVAA7%2(EN0|!S7t^j1jp*+nScQwyLBYHV z9RA>H_81Cr$1|oS?bObH+X4p%lo-O{S|~Dof~NyNYZfJAVtDp=-SPXqFrP#D)uJ-f zl)`@u*GNpEo+e=#F#^RlHlo0VvP1~P8>Y7eT1yhsqm*v8d^jypt{R=B-@-Lu%`U8k zABVzgj^o2jC^4*QN)?7U8=<6dJyRFZ|t%d*4wG=^1KwLX12^UDeM9U$O^sM1yj^YpQ0E53e+^2 z{t#P;7WRa}5b{D%mtIjCQ!szEE5FOhZ(q3igO*5v?x8p%*P`GieScaLD8ah-w7X}mWgmV$9GQAgr#~)jk@q1Ga z2VK3%N_}i#;{nwQHr1FDj)iK1(Czep{D7*_L(&+4LeEl2SC?C$03i(wg{@AK0Kqll zZbt!$b4+Qp^Nm+?DO7$30UfXBb_;rg7o)|j0fEQ>Je`sPC<21;Y@#+Tt09(SN{tdQ z8@!?%IVj*SEli{l@5@KeHhll{W-*1L7P0MtvQs$YhC<{wI?AHpXB{aG&~5N#ar?|x zL(fsdGg7(f775UEPYwh*$tK0$#8YhK`V1G2E*fE)gvDgBE8Ytj;G||iqtV20npYmj z(ELvE-w!F6Uh%~a!gmDlDlXTW%;G2f_>&NH6=oK>xn6EIGw9 z1RBW%!V`}l>g&f@e)>J8I`9kJ{4(V0m2nfQjHr2-@H`ixO}j;^$`T#{BXs?qUlH;p+`rt;Cd>;KG9hcw40Z`14qgBS@bY3oEP zMyrgLUMxfzfVmmmL<`d#E(=9k3NQXvwBnHGi#PrpbXmgcMOC`}T!;EG{4Z4tEW&s0>nG8-uhG0lS*5a9V;W+*pO9nhqQzd*Wm<#W zRA&oe@qFW34n)u!O~cpr{zvlj8bI1a4Zl+{nozynnE#&7YW__KMbdEC^q-Ia{p#O) zla&FAY0$En0fdqxFaI+W8aC2rI7yfKCR@L*Bb1_E&^;_T7ouMQ2vJUdY>asg^HT zS^3Y;g`%!e`l9?H<#+#gB?u*?{=0$yU2K1;=Gyg~+REet8fnek&>+UAjkIi&qcfMI z)Q`$1d5mxz45GL#sE4^Bn%eYQ9WN7BIH0VoU$eyNKLVk~#>Q7x}uT`CzhG~M*B5+X!31o?Z$Q^thG=|{m1*D6j zs2YU(Vl3sawJBknqi)VIyviA|S!ztmw5Oqghz5?|x+`9_nctG7_jvCtl9r7~8(^X} z`G{-+O*&AWpuxoPVGh9Sp2&WGmM;EZh^#gC%%%{A@-k&Ps12nyBZM-reQ+q#5^(3n zlE9~$V9KP0L;q3%I=lXD_96O>k362C4oE7}sf)a%lk zjMr-}wXIa%_bpHgq%Wb3hMN zEEe+DeV>Az_QkQiI!A(#hJ~n~bOr&+H6vc)4{yLB%YOTOetMFfB7yI9@NGZ8L{l~u zK}h-9qd@s3Tsv4G%vviAZc)->)c^S6U#hNnfHQX*wQ|u(q*xo-B@C%ix3r?1xYQ<5 zigdarhG;BG2uK;R+^ZnWR-^OE)|3Hl;G((kciQYYePWC<8k%kbZPe>#*tT-M_L#QO zZL~#)fi+75Y&};ikTL+u`IEm!#$u%7LNH_9i5=aI&)8QCA_Wi|X#*?yqrS_~1M%nq zJ^}hU;C3Le7Ig$9-(<3=^l}?z%I9MPHiI%6X0MrKRIF&~>9bOzBwyG*Jd|#k#wT)Y znYOm8j6(~jFC_0=RB?4*+m{>!e%s`kad@HrY#yF(s^Zz)BTAk2qU>S4HMpJ zWlYLiwD1pp3#}VbV@gJtn3+mY;+SnH7G1oTsY$m$DcHpBv`W!Jkv&KU22js@ zM1XB9n4uVq;}lO%@1fq3WBT9)wqk27ib)TPahI)0q~VWQ$sg10uZRrd_LKhnz$^r~ z6OuNh!o8BOGy4^{n6ch2@(5cv4>$lDVeqgPUuCveyqkEBLf1v7B^2KizDDRq{Mw~o zLDiQj3MsEGxkWFEvH6Wd8hmhy0o^9NVk|*S2y_PS0b^)7Bnfh&<4TC!MGs`#lDu{n zw!UR0d_Ob4JC88nW7pwnA)tVbndRDT<+Ig$i$jglb05|f(Btg?+#3$@EgyXf3>I$u zTyb%(>3&j1v)<1?L|?H)O~maXG2Hmdi)K-8d@j1310ZIOP*@dq*ZJCy$&90U?2u|( zawzyTV=2Cq8zoNtfI;ozqG_kMo()_7`pz?{aYo0R()N*KUn4)P`9!w&FWglVr15VC z`zu{+Caks$;h52x_q+qzJ6SZ zO`53f&xmsUjt3QXKN9Zh1Fpu-Ubv`H+YpDETyzlrjCl%SQPZw5JD`z-o1lz3V$prN z+oGH^zsIsw%@L)u5uz<|ZW$?leOfR3S_c9syF~xutR8E-O6FqcO50!*ICatHfMLb+ zW%8VIYu7RF5N%16%`1IH$7HRHLGl%u&h>Wjs1t6LjKvq-Qq5o+W|&mNr-{gh`Kk3= zi=i~NcNQFya%Gc9`AP8iDCs-ni{3*_8)4u0nsw-cf*a{Z2q!EJVIvec8CrX;`*z*$ zFICYydgW7KEBnHiDuBEjZZXldGIHMh&GI>JKF}i1;$6sBx%U&hR;mCf^fs1SixsLt z&05YIM|rZ&0Ra36^YR89Tv{WWgDBK%eRY<9llx9M=nMx@w+Ooe&3SKc@Yyx&sezfx zvkhmzCboM&GY)(#DBdk|C9`4qV%wn*v|R*i{5k)kGGjyMfp+!yqpa6vi_`$(S zf`OCtfOtm~hJ>5TXCyz<+OffLjYgdcTvoHEc!#mj)a480&=mjhp|Cz06PY4*>7>ClM*8NRY(6KLb2d+}{P z!UnS?3M3zb7q(&IL1QP4JBQ#%mv3iT*FFz<9|&98x5x#VkUS`*>)e;rB|OehxPH>$ z9mFHCpDWY)W(%zgr5_CaC`Rn_{A&PwDFnD>Hxx>D2qYgt-!j{T@lOPg#o)(;XVRvG zKkJGkz1ltpwqo5i*;Xs6B5L;Yw}Mp+4fD~Z|5>CW&ZzIA;-(&EH{JZ_`y02& z!`;fV4C22lYI#xhmQD8?%Qffmd-lXG6@K*CTy!AUxqHlz@ z@(#d;3hT&#Y+&$Wn`%6ci|z=#;BPPmw2}Xd<;B#)?EiWyd5XJ&>5)iFT9T#K&S%w;%=1Id z?D*r%)nQX;WoO#zZk=qo_Dws&v7L6zeRh3z11+pbiMx|mt4QV+d?_{ORDhOzB-$(< zM>d{_#v|O$wK|aMfa_-4U8&jYI()SA57{QIgw4gS>V8K;l&bp$~e2UeU&)s zz*J>ZzxfFLm&%d1i%+>Cj3{G@NhaWId^3Kcr*{_G++lGf|C=)yv`r|mwxD5t?&P1% zeby;x+(B+^q4vesw*rb}Y1bdYK?#~~B(uW{Xp`pOtF-+{hpn4vtGB+|T&1O`un@(; z8g$?y)QDPSSVd6ZU}(lw?eo}=!dazaM&g8z#H2}yoV6zm0Hyplb6#@~vTgxGJ|LYG zLnhr8M1St6G36D|$7jkc#&tt}Z9nB`48iS-qXI+O@DI+lD36s8mRjz}l-v>w=f|h_ zysyubaKk#vON*KqCP(?k;UY?RYE7}_gb z_iL#oH1VcDjctqn)^O*cCOhuvksxXky zb30=DPTS))p$z0hZkEWlP~gp+^l1f}d0^Kn2)?4xy|mPXiZm`=a(>pnQSfhy2wFtrMWai$(Xk9wJ@yqH!CW_|>Ht zx!Nwa2LjOSXASQYJS3%c#49^h~xDDGEe0T)efs3+ftb2??vy#? zH-j2FzP~-Say|RJzkoz^-gx%uoXAFI(IVFIJ8*vdxpy7_Mj8>`F4Kke#LZ>>oFH!7 zffDEKJ&%C)#p(kh8IVF8LUfSeINEv{KmN@Yyes0DgAUxmL)$(5g7Ch$CB-;NL|*3u ztyu5*d|JT(0B0=v~r8$HWVAkNLu2y z2(hpE`8iz@343+18rY*A`8jaQ>n3EPH^${&wqiOACa22n+MD9Rz?81o|24`cIf&w5 zK73X`Wx@ShogUd8XXCJKHIpXA&|nI%fPtc}M6S5ACsl87y{-$AoTED^n3`cZU;6md zJ5M{H=cAq(|H^oZyyH|Jl^sj=@|?G+4_|9iO^%l6v6iHOCSWr5MV3a7bB`V#_OW9l3$JlCd3e zQ5$3Hv7LZ?MvQDlCyW0rC;w69#)^)qMW5#j4#Es>%cMOSk|)T&o9X2l#AIYawGy943armLX6(5#$ zBp-p><)FM=P94?4iz~@~n6c5EdNJUm8L{g-!W+n2Mr-vud~_tbiHm!6--UCjU^?lv z@O%Y+8o796seUIc(Z2Eb>&mP)tXPS~YJHh+^rcV+CDnL~P{6Qw<@Qf`+#Mnh#}Z40 zw4vZrK?T;tv9QrygR+#<2M2#jU)WA%lZ7+^j#tn)BU3050x)gMfQY`mKF1oKPzXR?W8^HZ*LOztOFt-;~CcBvD`?9AD%4~_>zQW_ZBC5tGX-&xgAMAckW)y zQ0Y!vZOUHvY*Va#eGBB->!g}Cq)Fg^85|xEJsmb`ucZ`PX``DCv;3s4xe)%Y7k}J` zD%jO^+Ctl4@9Ju?!X3dBY?Xv)1Y&_PG4Z85kxK))zdMh)hR6{}`;(6A;H8vH{E265 z8ZUg-p9xqX>OWX@Wa*7fLJ#fEmdIQ&RrfJsEF)Fwn$ zR!+1DBaY2WZ$4bl8BC_jc~go*RZE&&IdGI|aX6vl^1889>aPAw@babbiCNf}U5*SiC>cg$-PYxz&hV%rOjec70M}1P2NGfmEOsH$xMGIa5#h=GTDr zCk&jiHxVc!i_%oBo;L5<%OsSJ68W<@1Z%f$ML3Bq6|{pPLCix zag#XX}06lYLG7_?qT@ zu>AC~Cv4!A2tSnVi!(WyUEn%Hhc32pE)@6FH&><^GCZiLntXU5Rq@WiZ;dSKRs(4~ zfB5w#^*rB&pUjVOG3xJG7dH6gVN+j7Bi!@$E+K;=U!Pa`2l236^Sm>t!oZ^&6G%t5 zqQ3IuSpRU_Yv#A@Lju{gl3ZUS@_3`c3oLWVcWtrd zFA7k~t8=MF6!r&O(;B*|6$85k3c=8^^>2e#)Gm;Lx4_;UXk}Vp+q*}l#Wu(86c{(n z8t2|~nKehD04aU0$=%W1!U!wa$=r0#>}I%}OA|PIFvuqQbec?f%k<2V)i^t@2Ds5I z?=&gq*Ld%Wc(>kSQ+kmN@gi^}$2i*f{D)7BLgvarWUs=8y_v9ald%}Pl|keKUJwFy zU+e(6=E&T9!fhDDa_bS)uFtTWXtYj5$lk?BBs9M759(l z9qPmO)at8;AWDhJZ8w&=zf>h`Bt^1`_;487A#Wvo<=(O2f&GrBo&7QUXxcIT`H%0p zqOL<{nmQDJ8liE%IoUflvNl>zQcC`QjzWtasyA^=APc5Itxj9~nL2F8$hwCVJ*rEN zYHm-~C%&KINl9*6(@Om8oix`><8QCKW9V{$bTLw>Tp*0C;iJw-{+dCv==UrF@(NJi zOK>I8G~kt!CS{-C>(w0FuNgI7Z5^nEZSk&LEi0q;#RJlPbKP(vzi8EqEH(H{Q)~0d z_Hj|cVCU&@gi381-;cw{`Z3%$nu6nZqLduQqSy67`yMHS>~n%r=*xaF{HbXU(u1Z# zsRj+Wc#5koeMp%Gvukdj)(#kKWW@18=lHId?<}WTxNZ!^97)+`tBpNJhl))=g>&aP z>`C8kYMnv{I-i>^k9{k1err#V#C@vy*sRsVBa!)O2l9O5g@_U7@U&{}rC;xffs)?C zd(eAvt?TOXuC>QblG1;vnsm5bm&0S!bOa4um()J%IEsfI&@V!dZ?KUjh%}0EC$x66 zQBO9OkLg|?zC0Um|8!$FWnVBxt(K*HqF1tEsnbQd@S*yj0W|l?zr*6SH;{4B(2Hk9 z1yK>xq5UGqE)hN4M0dN(VI^CvtIAHxhBNgt#A9L0%?19x#uI#Yf*sxUXF9KWuI!77 zQryVPC4DfJlvw@;z0w|kRs5xAU1yqAYhP5OQ0B)#vAVPe;Ah*RaL3W+CG6Y6Xq9VC z@|CvI3TKCks{B?DS?yl_@m$NuGs?(zC) z6|j6*g8#mo#m9I(!`t4`L8r-sGFmCc>odxKslEm3;%Tw&?Vkyar`zGxrmL{7pwzw#M-V(aY)W^FT3xG|HLU@utVv8ABz>}Xv45+s`|eMDxl+f*+n+28 z&6=TdLqRSvM@HC$UUch;EVz9MV5L9g<|OB~D?YdGnDJ+#lK}(RCUT4i$A=WZ!L``W z)z#&4#Y8SBf z_r%_Zl1T3RNVs8~;hqtvlUBmZv@3$DS4V1h_+u391|s1716t&$M$d6}Lpm>b!s!Tg2cUEPKP^SVtyRlaJm^@@c zCN%w}y8aMBaiU1+Ukk^OLKB}899<^Hs#PiFa^(W%6Nq^l$zhNwJ`UR})g_WzAbAYunWU z6_UYVpV)<-;pc;P;ily>TwEtNikVdp$cMMf#di#Q>M`kg&6JMJt)E#*nUmh>V;3yEh(#R4C=%(r~Smg%Xeb_jU2 z1|gSSbPU=M`&V3Fa}zQb1RLqACdeXZ2A5$MO3cJ)OuJPGGUK~p<&pK?8vLZ7i>V#v zBDMln<3#-mF1!{&;fRb(N@&K=lw5A& z<1}-)xkidSG2UMI8R7n>ien<#{)BL(upK0tlao{Mtu#yb*ofQTLG25#+UIvu5lu$4 z|6V8o+YS_T;(0)$q32fI=@QSw_Ovi zb|J~kn2=VkcOASU%>J-*<8dVF)V_ zLdd=g*R=o0vo(+n3+zl$171H+Ym~d*bSq0>EQUTSg?M6Pk7V1xssT#VKjBUoB&P;% z&be_`v^HG_xQCCVw|vgLyml?(2ENi*_jt&mum2=+B(q)R{9 zTqN=$yVYIFXL4T(wwG~e3TLve|;9DOsqiqRV-j$51{Sq6{i8UK?edk`tAY3;T_{ zbpp83O!6^PN$ZzNPTVZk;a=3H09D$&YhqHjKpt9f2l+#U@-G@7jDqEe=ZkhYCCX%y~G#x`H1tIr)64nLSTi6^4=mA!&@FKzEIKmIO;(C?lW13 zvnd|oY3~Kluq>CC0H&RpgL{>{F37Q*|l##%XZ*l^n(5rvv zX#m0uZ@Dta)6rzt^lN`J$zH5HesMmhzUXyME(X)RzDS7I$~BV;-t_QVrfacU*Ge*0 zPTCR=H=_00m-7=#zmLYur#aX?g$@P-*RZeIjk`Jg9di8d>)8!qD%YKI4H`Dax8f{H ziCU_J+O~bf#j@(j+k;dYd1u3~=$+N!7cU0Bzqz8rNxuHUvSFs0v;t9N-*cQn;MRw> zFj3gEs9~nolVVD^5}!=c9z_eYt=HTTSdlUP4Y>TMJ2GOfG)t%aPPzNDiaC%u;7MEA zL`kFg9L`whe)4VrVfN}dV_ucS-A^fE<_dQMwbwu8Oo@&8K#@Hb<>@Y_^_$jblirdy zH0r4biq50qu=0@>LlfwhUHCh2iw(^)F>Xf)*vIHS<;f8rnEFRn$9@MG;`FobV^(tI zJd=8X9bDy=Pvw2x^4M0DeWzBkwn%VnK$00mMn@M6v6%-y{Vwc z%fo?<>a5S&U0tsEzvWBy-QKh0DQRtDt6)CmF>UlgikZ^aZGLgfh;>u!tc&GFN#%5Y ztbl6}{f)l87yH5lVly=DTG}3ewOj%iSh#Tq{{{6JeV<;JSrX*$OAGn;B#K`ZH6)4Lv*X5 z6zfoI#eDsXiQMD$ewa__iKxfr_(cGBvCp87BM4$m)+aa^LvLbt4R0t%BYn;ZsiIN(ee97c>=S#C9vn*KM~1 z2Gv28ezi#v_h|L^R=v_=-t1;=jB{J*pD~vpEm}mcG&v3#uMt+H4Eo8!>WyEcF>#T~ zT$vvvOu+0am`{jl>kZ(hIGrG!q;Yu+VOPrE$&aVeksF@K4(&3;ylAH}D4;XC>}d=c z^GE*FHB1<6eXN@X9gF*|moot`FIjy5?hDp%_MCZCv<^XsLcK`jOThN1CE-jue$l;2 zvPjcc;VCaxs7rduLRY@?$gs@_bLYJgeNk`p_@_j=ZS}?#(sZJ1cad`mrBz(r;JnYN&bm&IT_z{Z(?{C$P8m1Xtsa)1^R|v>_aQAmf4Zd9P;3_N6bPl zb@Yij2h!SeWr-k=5~!n93l3@>%?9;s);jd)kj4Fj_zRn?VK+;}jS$nCeqx!TEsB+S zoA_~#;50z)gqgywbzxP_} zW6%0BA*R7#Fk{P-J(X-B&y%vG$e1$L(O?WCWJ{xrlqr*Bk3pr9on)&l^&UOf`zw;K=f3Xi{P8{Ky6?~T`^yx3Uoa4negvdtA~+f6AE$dXm3Q(s$@09+VU>zB*ianG z64S*ol$4W3r6U79El7-ta`t*u;lY3jVo*jXM#obqJ=!Y_aC+l#o`c@03pH4!6ASJY zr79akar)L}eg0DGWlvXQrI`#>mGq&fB?NKla>>MM6XO<_!;Z# z#XYVs=*r6)GNTigWx7P+agvLPll6i@`E!^hNEv1!E^d<(V11pf^eNY{OjmExuPnpH z#oY^3Y7-B0R%t5eAiI|`{G#G?Ri4kq(f#;r852VRxB$QDJfg_iZzoL(AV-CTMXO*M znFmM~0oKV+3fvs;BagX0YUoTMW2`m48&r$stMYK7RdP&(xyU?Bv^C!i?M0JAwoQti zURkp#qGp0jssXsz6{Lz07JM*HoFtNbWeU1gy zSP=_fB2X&B$?@V%HF z9k2Yu)e2nzQ&R}g?|z`HQLVv}Oka4`s#b;4S}2>sz+G1mqgO}P7FSp zz0nobbE=UB6~GTFv9!89jK>rUj$_bPvHscxUbClM$~~PG>Cnp0=qV%pV|lWkujV42 zG<{U;xoe)PC^8_1w#3Ke_u0ZlHOL(ovkv7?v+X?POz|eF8RB92ngI+?q5C)4pSDIz zJ~)ijeESR7GEHa!A_&ZK+>xWii_HUhBcN{wa!Y?Z{`1F%d_lfLCCB%7acB9$i* zYei?zB%AR#aU_Cq=y*8tFz_;aMEh#k`tc#}6q#vr<@+-!#T7Sp zrFQPTrj*0GuzW6htLwJ5bW+znLPML?tjK!iPL~Yue{NnT1ABSIP3Zp5y8q^WPV%CZ zPP^4nt?S+dH`YeRug>fKLyOr+;4G`BjR+TZIt%+a(Mh4T^B0=Ip~6={>%x-JZybE) z|J*mgEZsHEyR(5blDZpyb0fmLI!4=sX799$sy>EC{JpV`l>c!&yb+(*cF?XBGCx6n ztZ)sUuA|U}E_=&g>feu{y4k)r2ZM0IIvT$ckI6=|dexiJ;1nLQP?krUDQnPPiS@+^kU5BCs$Xp>Qh z)@=xz@}#aV0%-~<_FuOE^nfp7TM7|nEVHS#Fv@i8ZArCNqDT{6*<%m2=Es+P-3D8= z!saHP*3mERXBEGe#js|dHEm`U1DjoAyyx2bY;^^r(8@kVH~LwyFNslvpdRn9o@)O9oMM<_1YySJBV-^H|N z57!@U0A?~j&!T@zD2d$In+x1123fsXJ8it#xCROu-C-a35X}!SoIxx0{JP`IU3@KL z5GeFr>TuMVx1P-&-&KYa(n8$KTM?=pvDR;=i#UD`W80!W%_O(ASOjk8!zS|RMl4dk zwT^-4ZQd26k8_FEONrf0+vH9vM2!paw;ma?Z{Ff24MvZ$o47*UHQIM`q{AB2!}0e% zCvf@NNjk%7%#_w`n&xl6B++lzGt=Rk!kmCI4V;TLwAWZU-fn^g`*z8I7W&*i#SohcI$UFvu zRa%oJKW8;=dQ06P@KBEwt`rVY@oCyk9vB7QRBL)dL)b){_q1}L&h)L&7;ueoJppm? zFUBs37#;3q^C8oKK#yVf z`d9v_FyM{dQ{n5oxRVK2aO#&SZHnWL+d28xgOU{g%z+9+nyulBbvKtK$#h&#STxQW zl*df)1TTgp32jD@g1nKOLg@t8d<^Cs^a&qow21wSTs-?~N$BgYzsO+0W%PjrOj?^L1|r-Z7kZ%~@1! zugBQl?KdP!m1fNFhrc@>0#_mXV)c4`&rG>I{E|UKF6Gu7IIU)*H|5ew^yZ8XIAR}! ze7>nhg*r8Xh3`&oh!M_*Q@P}4I@t|5>OK}WTe#w)8Ej8`U7K2eOIrB8Fa>n< ztnQ?HA+drR9<$kL2^Cas6_ur}!15l*(AKQrnq3=e+t_*RCiI-d?|l;S8!;)nV3%=n z+u@`BY}Ayx?_@8=OKBN3_G&7v`@QIiQ>Q6LZPW{z#IJb01P_rdgI24YpWA+%qL#J* zR?=t-3-T0TJr+tD|If-^sQH?*qKQ8oKa;&hAG!Yse=u3#&&~dWqwKXsT-8)tRYi3E#Y>t24Ur@SP#bCQqp}k!0Lu{AoKq?S*p*lg z&|}tND(gq#ub&g^DhZ`PcH9=PD(Q&Xs@`+|Vyl!%hNE+7vrpPPfMM!gDN$bxUXEW~ z2VIgxtA{i5mNQo@c)-;ZMF#O1Tc~^sKL}lgKrc;fK?{jzUY+T?8&-pp@C_zeh-{sXa_n9+W)4N^KEjW-l)Ru07|umAjEYL~d9Gvu9g z7#rN{T4H{n%Aw@i5FLv{FYm4Ef6BVr5F$<-7)u9hf)cZv&58vH5Qw&Slw=JE8w$6n zC~xeB$2X`C%ljmU_C0>CN$2R!zc!m$CH$K9@Bvo3I>5Uxw<&^kC%t^eSm=^5Pu5$E z{7+HT@=X{ic#BLl{Tk^}|L(Yp-Ec&zb$CPkV%#~a%6iGmXPZN>5K6=PA*P@m$N)yQ zf3i6S);$?~ZT}a>PnBY9YW3uE+=|V@WXm(y^PlGJBzbYh1Xf|L_ixu&iE9fXv^VTl<>Roo~h`#)U~9 uOCF~BX{=fiN?cRkgR0DOAd?LoO@g@XaVN;tz9tPq666MAWpqd9H}`)%_?D#r diff --git a/client/kit/static/images/logo.png b/client/kit/static/images/logo.png deleted file mode 100644 index 2e8695210bfc486c5af441ce28a6b8eb4414085b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4743 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 Iv_tfN04Z+8)c^nh diff --git a/client/kit/static/manifest.json b/client/kit/static/manifest.json deleted file mode 100644 index f794400c..00000000 --- a/client/kit/static/manifest.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "background_color": "#ffffff", - "theme_color": "#343a40", - "name": "Permacoop", - "short_name": "Permacoop", - "display": "standalone", - "start_url": "/", - "icons": [ - { - "src": "/images/icons/android-icon-36x36.png", - "sizes": "36x36", - "type": "image/png", - "density": "0.75" - }, - { - "src": "/images/icons/android-icon-48x48.png", - "sizes": "48x48", - "type": "image/png", - "density": "1.0" - }, - { - "src": "/images/icons/android-icon-72x72.png", - "sizes": "72x72", - "type": "image/png", - "density": "1.5" - }, - { - "src": "/images/icons/android-icon-96x96.png", - "sizes": "96x96", - "type": "image/png", - "density": "2.0" - }, - { - "src": "/images/icons/android-icon-144x144.png", - "sizes": "144x144", - "type": "image/png", - "density": "3.0" - }, - { - "src": "/images/icons/android-icon-192x192.png", - "sizes": "192x192", - "type": "image/png", - "density": "4.0" - } - ] -} diff --git a/client/kit/svelte.config.js b/client/kit/svelte.config.js deleted file mode 100644 index 9146ebb6..00000000 --- a/client/kit/svelte.config.js +++ /dev/null @@ -1,20 +0,0 @@ -import adapter from "@sveltejs/adapter-node"; -import preprocess from "svelte-preprocess"; - -/** @type {import('@sveltejs/kit').Config} */ -const config = { - // Consult https://github.com/sveltejs/svelte-preprocess - // for more information about preprocessors - preprocess: preprocess({ - postcss: true, - }), - - kit: { - adapter: adapter(), - paths: { - base: "/kit", - }, - }, -}; - -export default config; diff --git a/client/kit/tailwind.config.cjs b/client/kit/tailwind.config.cjs deleted file mode 100644 index 93b134ea..00000000 --- a/client/kit/tailwind.config.cjs +++ /dev/null @@ -1,132 +0,0 @@ -const defaultTheme = require("tailwindcss/defaultTheme"); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ["./src/**/*.{ts,html,svelte}"], - darkMode: "class", - theme: { - colors: { - transparent: "transparent", - white: "#ffffff", - black: "#000000", - gray: { - 50: "#f9fafb", - 100: "#f4f5f7", - 200: "#e5e7eb", - 300: "#d5d6d7", - 400: "#9e9e9e", - 500: "#707275", - 600: "#4c4f52", - 700: "#24262d", - 800: "#1a1c23", - 900: "#121317", - }, - "cool-gray": { - 50: "#fbfdfe", - 100: "#f1f5f9", - 200: "#e2e8f0", - 300: "#cfd8e3", - 400: "#97a6ba", - 500: "#64748b", - 600: "#475569", - 700: "#364152", - 800: "#27303f", - 900: "#1a202e", - }, - red: { - 50: "#fdf2f2", - 100: "#fde8e8", - 200: "#fbd5d5", - 300: "#f8b4b4", - 400: "#f98080", - 500: "#f05252", - 600: "#e02424", - 700: "#c81e1e", - 800: "#9b1c1c", - 900: "#771d1d", - }, - orange: { - 50: "#fff8f1", - 100: "#feecdc", - 200: "#fcd9bd", - 300: "#fdba8c", - 400: "#ff8a4c", - 500: "#ff5a1f", - 600: "#d03801", - 700: "#b43403", - 800: "#8a2c0d", - 900: "#771d1d", - }, - blue: { - 50: "#ebf5ff", - 100: "#e1effe", - 200: "#c3ddfd", - 300: "#a4cafe", - 400: "#76a9fa", - 500: "#3f83f8", - 600: "#1c64f2", - 700: "#1a56db", - 800: "#1e429f", - 900: "#233876", - }, - yellow: { - 50: "#fdfdea", - 100: "#fdf6b2", - 200: "#fce96a", - 300: "#faca15", - 400: "#e3a008", - 500: "#c27803", - 600: "#9f580a", - 700: "#8e4b10", - 800: "#723b13", - 900: "#633112", - }, - indigo: { - 50: "#f0f5ff", - 100: "#e5edff", - 200: "#cddbfe", - 300: "#b4c6fc", - 400: "#8da2fb", - 500: "#6875f5", - 600: "#5850ec", - 700: "#5145cd", - 800: "#42389d", - 900: "#362f78", - }, - green: { - 50: "#f3faf7", - 100: "#def7ec", - 200: "#bcf0da", - 300: "#84e1bc", - 400: "#31c48d", - 500: "#0e9f6e", - 600: "#057a55", - 700: "#046c4e", - 800: "#03543f", - 900: "#014737", - }, - purple: { - 50: "#f6f5ff", - 100: "#edebfe", - 200: "#dcd7fe", - 300: "#cabffd", - 400: "#ac94fa", - 500: "#9061f9", - 600: "#7e3af2", - 700: "#6c2bd9", - 800: "#5521b5", - 900: "#4a1d96", - }, - }, - extend: { - maxHeight: { - 0: "0", - xl: "36rem", - }, - fontFamily: { - sans: ["Inter", ...defaultTheme.fontFamily.sans], - }, - }, - }, - plugins: [require("@tailwindcss/forms")], -}; diff --git a/client/kit/tsconfig.json b/client/kit/tsconfig.json deleted file mode 100644 index 5c56cee3..00000000 --- a/client/kit/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true - } -} diff --git a/client/kit/vite.config.ts b/client/kit/vite.config.ts deleted file mode 100644 index 92ec0aa7..00000000 --- a/client/kit/vite.config.ts +++ /dev/null @@ -1,42 +0,0 @@ -import path from "path"; -import { sveltekit } from "@sveltejs/kit/vite"; -import type { UserConfig } from "vite"; -import tailwindcss from "tailwindcss"; -import purgecss from "@fullhuman/postcss-purgecss"; -import cssnano from "cssnano"; - -const config: UserConfig = { - plugins: [sveltekit()], - server: { - port: 3003, - base: "/kit", - hmr: { - path: "/kit", - }, - }, - resolve: { - alias: { - src: path.resolve("./src"), - }, - }, - css: { - postcss: { - plugins: [ - tailwindcss("./tailwind.config.cjs"), - purgecss({ - content: ["./src/app.html", "./src/**/*.svelte"], - safelist: { - standard: [/^(event-)\w*/], - deep: [/^(dark)/], - }, - defaultExtractor: (content) => content.match(/[A-Za-z0-9-_:/]+/g) || [], - }), - cssnano({ - preset: "default", - }), - ], - }, - }, -}; - -export default config; diff --git a/client/kit/vitest.config.ts b/client/kit/vitest.config.ts deleted file mode 100644 index 4f0e4041..00000000 --- a/client/kit/vitest.config.ts +++ /dev/null @@ -1,30 +0,0 @@ -/// -import path from "path"; -import { defineConfig } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import config from "./vite.config"; - -export default defineConfig({ - ...config, - resolve: { - alias: { - ...config?.resolve?.alias, - $lib: path.resolve("./src/lib"), - }, - }, - plugins: [ - svelte({ - hot: !process.env.VITEST, - }), - ], - test: { - globals: true, - environment: "node", - exclude: [ - "**/e2e/**", - "**/node_modules/**", - "**/dist/**", - "**/.{idea,git,cache,output,temp}/**", - ], - }, -}); diff --git a/client/proxy/index.cjs b/client/proxy/index.cjs deleted file mode 100644 index c92731a3..00000000 --- a/client/proxy/index.cjs +++ /dev/null @@ -1,30 +0,0 @@ -const express = require('express'); -const { createProxyMiddleware } = require('http-proxy-middleware'); - -const LEGACY_PORT = process.env.LEGACY_PORT; -const KIT_PORT = process.env.KIT_PORT; -const PORT = process.env.PORT; - -const isProd = process.env.NODE_ENV === 'production'; - -const app = express(); - -app.use( - createProxyMiddleware({ - changeOrigin: true, - router: (req) => { - if (req.path.startsWith('/kit')) { - return `http://localhost:${KIT_PORT}`; - } - - if (!isProd && req.path.match(/^\/@fs|node_modules|\.svelte-kit|@vite|src/)) { - return `http://localhost:${KIT_PORT}`; - } - - return `http://localhost:${LEGACY_PORT}`; - }, - }) -); - -console.log(`client proxy listening on http://localhost:${PORT}`); -app.listen(PORT); diff --git a/client/proxy/package-lock.json b/client/proxy/package-lock.json deleted file mode 100644 index 7ffd61b8..00000000 --- a/client/proxy/package-lock.json +++ /dev/null @@ -1,1302 +0,0 @@ -{ - "name": "proxy", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "proxy", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "express": "^4.18.2", - "http-proxy-middleware": "^2.0.6" - } - }, - "node_modules/@types/http-proxy": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", - "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "18.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", - "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has": { - "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" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - } - }, - "dependencies": { - "@types/http-proxy": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", - "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", - "requires": { - "@types/node": "*" - } - }, - "@types/node": { - "version": "18.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", - "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - } - } -} diff --git a/client/proxy/package.json b/client/proxy/package.json deleted file mode 100644 index 6cf38720..00000000 --- a/client/proxy/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "proxy", - "author": "Fairness", - "version": "1.0.0", - "scripts": { - "dev": "node index.cjs" - }, - "license": "MIT", - "dependencies": { - "express": "^4.18.2", - "http-proxy-middleware": "^2.0.6" - } -} diff --git a/docs/dev.md b/docs/dev.md index 5fa080d5..562590b1 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -4,14 +4,4 @@ Icons come from https://heroicons.com/ -To add a new icon, create a corresponding `.svelte` file with the HeroIcons SVG. - -## SvelteKit migration - -During the migration from Sapper to SvelteKit (see [#214](https://github.com/fairnesscoop/permacoop/issues/214)), the `client` is run during development with the following setup: - -``` -localhost --- proxy (:3001) - ├--- legacy (:3002) - └--- kit (:3003) -``` +To add a new icon, create a corresponding macro in `icons.njk` with the HeroIcons SVG. diff --git a/prod/README.md b/prod/README.md index 80016b21..ce1e7245 100644 --- a/prod/README.md +++ b/prod/README.md @@ -17,6 +17,8 @@ _This document describes Fairness' production deployment of Permacoop. It is mea ## Architecture overview + + The deployed service architecture is as follows: ``` From af477ddab0a946275e3a542a65ee6a8ef3cff438 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Tue, 26 Sep 2023 14:04:02 +0200 Subject: [PATCH 25/49] Restructure CSS, standardize buttons and links, rework nav, header, dropdown, and more --- server/src/assets/styles/_blocks/box.css | 5 ++ server/src/assets/styles/_blocks/brand.css | 12 +++ .../breadcrumb => _blocks}/breadcrumb.css | 10 +-- .../button => _blocks}/button.css | 3 +- .../dropdown => _blocks}/dropdown.css | 12 ++- .../{_components/icon => _blocks}/icon.css | 15 ++-- server/src/assets/styles/_blocks/index.css | 12 +++ .../src/assets/styles/_blocks/input-group.css | 13 +++ server/src/assets/styles/_blocks/label.css | 9 ++ server/src/assets/styles/_blocks/link.css | 12 +++ server/src/assets/styles/_blocks/nav.css | 79 +++++++++++++++++ .../input.css => _blocks/select-group.css} | 20 ----- .../{_components/table => _blocks}/table.css | 0 .../assets/styles/_components/card/card.css | 9 -- .../_components/container/container.css | 5 -- .../src/assets/styles/_components/index.css | 10 --- .../assets/styles/_components/link/link.css | 8 -- .../src/assets/styles/_components/nav/nav.css | 71 --------------- server/src/assets/styles/_defaults.css | 25 ------ server/src/assets/styles/_layouts.css | 52 ----------- server/src/assets/styles/_reset.css | 10 +++ server/src/assets/styles/_utilities.css | 27 ------ .../assets/styles/_utilities/background.css | 7 ++ .../assets/styles/_utilities/container.css | 5 ++ server/src/assets/styles/_utilities/flex.css | 9 ++ server/src/assets/styles/_utilities/gap.css | 3 + server/src/assets/styles/_utilities/grid.css | 16 ++++ server/src/assets/styles/_utilities/index.css | 11 +++ .../src/assets/styles/_utilities/padding.css | 7 ++ server/src/assets/styles/_utilities/row.css | 12 +++ .../src/assets/styles/_utilities/shadow.css | 3 + .../src/assets/styles/_utilities/sizing.css | 3 + server/src/assets/styles/_utilities/text.css | 7 ++ .../src/assets/styles/_utilities/z-index.css | 3 + server/src/assets/styles/_variables.css | 3 +- server/src/assets/styles/main.css | 4 +- server/src/templates/components/attr.njk | 1 - server/src/templates/components/header.njk | 14 +-- server/src/templates/components/nav.njk | 34 ++++---- server/src/templates/layouts/_base.njk | 12 +-- server/src/templates/layouts/app.njk | 8 +- server/src/templates/layouts/blank.njk | 6 ++ server/src/templates/macros/attr.njk | 12 +++ server/src/templates/macros/breadcrumb.njk | 4 +- server/src/templates/macros/buttons.njk | 11 +++ server/src/templates/macros/icons.njk | 86 ++++++++++--------- server/src/templates/macros/links.njk | 8 ++ server/src/templates/macros/table.njk | 5 +- .../src/templates/pages/customers/_form.njk | 19 ++-- server/src/templates/pages/customers/add.njk | 13 ++- server/src/templates/pages/customers/edit.njk | 12 +-- server/src/templates/pages/customers/list.njk | 15 ++-- .../pages/faircalendar/events/_form.njk | 26 +++--- .../pages/faircalendar/events/add.njk | 8 +- .../pages/faircalendar/events/edit.njk | 14 +-- .../templates/pages/faircalendar/index.njk | 46 +++++----- server/src/templates/pages/home.njk | 6 +- server/src/templates/pages/login.njk | 21 +++-- server/src/templates/pages/profile/_form.njk | 19 ++-- server/src/templates/pages/profile/edit.njk | 8 +- server/src/templates/pages/projects/_form.njk | 15 ++-- server/src/templates/pages/projects/add.njk | 8 +- server/src/templates/pages/projects/edit.njk | 8 +- server/src/templates/pages/projects/list.njk | 9 +- server/src/templates/pages/tasks/_form.njk | 13 +-- server/src/templates/pages/tasks/add.njk | 8 +- server/src/templates/pages/tasks/edit.njk | 8 +- server/src/templates/pages/tasks/list.njk | 9 +- server/src/templates/pages/users/_form.njk | 46 +++++----- server/src/templates/pages/users/add.njk | 8 +- server/src/templates/pages/users/edit.njk | 8 +- server/src/templates/pages/users/list.njk | 9 +- 72 files changed, 558 insertions(+), 511 deletions(-) create mode 100644 server/src/assets/styles/_blocks/box.css create mode 100644 server/src/assets/styles/_blocks/brand.css rename server/src/assets/styles/{_components/breadcrumb => _blocks}/breadcrumb.css (52%) rename server/src/assets/styles/{_components/button => _blocks}/button.css (89%) rename server/src/assets/styles/{_components/dropdown => _blocks}/dropdown.css (57%) rename server/src/assets/styles/{_components/icon => _blocks}/icon.css (60%) create mode 100644 server/src/assets/styles/_blocks/index.css create mode 100644 server/src/assets/styles/_blocks/input-group.css create mode 100644 server/src/assets/styles/_blocks/label.css create mode 100644 server/src/assets/styles/_blocks/link.css create mode 100644 server/src/assets/styles/_blocks/nav.css rename server/src/assets/styles/{_components/input/input.css => _blocks/select-group.css} (63%) rename server/src/assets/styles/{_components/table => _blocks}/table.css (100%) delete mode 100644 server/src/assets/styles/_components/card/card.css delete mode 100644 server/src/assets/styles/_components/container/container.css delete mode 100644 server/src/assets/styles/_components/index.css delete mode 100644 server/src/assets/styles/_components/link/link.css delete mode 100644 server/src/assets/styles/_components/nav/nav.css delete mode 100644 server/src/assets/styles/_layouts.css create mode 100644 server/src/assets/styles/_utilities/background.css create mode 100644 server/src/assets/styles/_utilities/container.css create mode 100644 server/src/assets/styles/_utilities/flex.css create mode 100644 server/src/assets/styles/_utilities/gap.css create mode 100644 server/src/assets/styles/_utilities/grid.css create mode 100644 server/src/assets/styles/_utilities/index.css create mode 100644 server/src/assets/styles/_utilities/padding.css create mode 100644 server/src/assets/styles/_utilities/row.css create mode 100644 server/src/assets/styles/_utilities/shadow.css create mode 100644 server/src/assets/styles/_utilities/sizing.css create mode 100644 server/src/assets/styles/_utilities/text.css create mode 100644 server/src/assets/styles/_utilities/z-index.css delete mode 100644 server/src/templates/components/attr.njk create mode 100644 server/src/templates/macros/attr.njk create mode 100644 server/src/templates/macros/buttons.njk create mode 100644 server/src/templates/macros/links.njk diff --git a/server/src/assets/styles/_blocks/box.css b/server/src/assets/styles/_blocks/box.css new file mode 100644 index 00000000..4d3a64d2 --- /dev/null +++ b/server/src/assets/styles/_blocks/box.css @@ -0,0 +1,5 @@ +.pc-box { + background-color: var(--background-default); + box-shadow: var(--shadow-default); + padding: var(--box-padding, calc(3 * var(--w))); +} diff --git a/server/src/assets/styles/_blocks/brand.css b/server/src/assets/styles/_blocks/brand.css new file mode 100644 index 00000000..fed09464 --- /dev/null +++ b/server/src/assets/styles/_blocks/brand.css @@ -0,0 +1,12 @@ +a.pc-brand { + display: inline-flex; + align-items: center; + column-gap: calc(2 * var(--v)); + font-size: var(--font-size-lg); + font-weight: bold; +} + +a.pc-brand > img { + width: calc(8 * var(--v)); + height: calc(8 * var(--v)); +} diff --git a/server/src/assets/styles/_components/breadcrumb/breadcrumb.css b/server/src/assets/styles/_blocks/breadcrumb.css similarity index 52% rename from server/src/assets/styles/_components/breadcrumb/breadcrumb.css rename to server/src/assets/styles/_blocks/breadcrumb.css index a29fe798..5a63f9dc 100644 --- a/server/src/assets/styles/_components/breadcrumb/breadcrumb.css +++ b/server/src/assets/styles/_blocks/breadcrumb.css @@ -1,10 +1,6 @@ -nav[role='navigation'][aria-label].pc-breadcrumb { +nav.pc-breadcrumb[role='navigation'][aria-label] { color: var(--text-muted); - background-color: var(--background-default); - box-shadow: var(--shadow-default); - padding: var(--w); margin-bottom: calc(4 * var(--v)); - /* flex p-2 mt-6 mb-6 text-sm text-gray-500 bg-white rounded-lg shadow-md dark:bg-gray-800 */ } .pc-breadcrumb > ol { @@ -19,3 +15,7 @@ nav[role='navigation'][aria-label].pc-breadcrumb { content: '/'; margin-inline: var(--w); } + +.pc-breadcrumb a { + font-weight: 500; +} diff --git a/server/src/assets/styles/_components/button/button.css b/server/src/assets/styles/_blocks/button.css similarity index 89% rename from server/src/assets/styles/_components/button/button.css rename to server/src/assets/styles/_blocks/button.css index b8fa9c7f..c32da737 100644 --- a/server/src/assets/styles/_components/button/button.css +++ b/server/src/assets/styles/_blocks/button.css @@ -5,9 +5,10 @@ background-color: var(--background-action-violet); color: var(--text-on-background-action-violet); font-weight: var(--font-weight-md); + cursor: pointer; } -.pc-btn:hover { +.pc-btn:not(:disabled):hover { background-color: var(--hover-tint); } diff --git a/server/src/assets/styles/_components/dropdown/dropdown.css b/server/src/assets/styles/_blocks/dropdown.css similarity index 57% rename from server/src/assets/styles/_components/dropdown/dropdown.css rename to server/src/assets/styles/_blocks/dropdown.css index 4695ed14..0e05e46d 100644 --- a/server/src/assets/styles/_components/dropdown/dropdown.css +++ b/server/src/assets/styles/_blocks/dropdown.css @@ -3,20 +3,18 @@ details.pc-dropdown { } details.pc-dropdown > summary { - display: inline; /* Remove default 'v' */ + display: inline; /* Remove built-in chevron */ cursor: pointer; } -details.pc-dropdown .pc-dropdown__content { +details.pc-dropdown > *:not(summary) { z-index: 1; position: absolute; background-color: var(--background-default); box-shadow: var(--shadow-default); + border: 1px solid var(--border-default); + top: 100%; right: 0; width: max-content; - padding: calc(3 * var(--v)); -} - -ul.pc-dropdown__content > li { - padding-block: calc(2 * var(--v)); + margin-top: calc(3 * var(--v)); } diff --git a/server/src/assets/styles/_components/icon/icon.css b/server/src/assets/styles/_blocks/icon.css similarity index 60% rename from server/src/assets/styles/_components/icon/icon.css rename to server/src/assets/styles/_blocks/icon.css index b8c3ab5f..6995d005 100644 --- a/server/src/assets/styles/_components/icon/icon.css +++ b/server/src/assets/styles/_blocks/icon.css @@ -1,7 +1,7 @@ .pc-icon { - --size: 7; - width: calc(var(--size) * var(--v)); - height: calc(var(--size) * var(--v)); + --icon-size: 7; + width: calc(var(--icon-size) * var(--v)); + height: calc(var(--icon-size) * var(--v)); } .pc-icon--error { @@ -19,10 +19,11 @@ } .pc-icon--sm { - --size: 5; + --icon-size: 5; } -.pc-icon--left { +.pc-icon--left, +.pc-icon--right { display: flex; align-items: center; } @@ -30,3 +31,7 @@ .pc-icon--left > .pc-icon { margin-inline-end: calc(2 * var(--v)); } + +.pc-icon--right > .pc-icon { + margin-inline-start: calc(2 * var(--v)); +} diff --git a/server/src/assets/styles/_blocks/index.css b/server/src/assets/styles/_blocks/index.css new file mode 100644 index 00000000..f44533a0 --- /dev/null +++ b/server/src/assets/styles/_blocks/index.css @@ -0,0 +1,12 @@ +@import './box.css'; +@import './brand.css'; +@import './breadcrumb.css'; +@import './button.css'; +@import './dropdown.css'; +@import './icon.css'; +@import './input-group.css'; +@import './label.css'; +@import './link.css'; +@import './nav.css'; +@import './select-group.css'; +@import './table.css'; diff --git a/server/src/assets/styles/_blocks/input-group.css b/server/src/assets/styles/_blocks/input-group.css new file mode 100644 index 00000000..fb62c98e --- /dev/null +++ b/server/src/assets/styles/_blocks/input-group.css @@ -0,0 +1,13 @@ +.pc-input-group { + margin-bottom: calc(2 * var(--w)); +} + +.pc-input-group > input { + appearance: none; + display: block; + width: 100%; + background-color: var(--background-default); + border: 1px solid var(--border-default); + border-radius: var(--radius-sm); + padding: calc(2 * var(--v)) calc(3 * var(--v)); +} diff --git a/server/src/assets/styles/_blocks/label.css b/server/src/assets/styles/_blocks/label.css new file mode 100644 index 00000000..8e2f637c --- /dev/null +++ b/server/src/assets/styles/_blocks/label.css @@ -0,0 +1,9 @@ +.pc-label { + display: block; + padding-bottom: var(--v); +} + +.pc-label.required::after { + content: ' *'; + color: var(--text-error); +} diff --git a/server/src/assets/styles/_blocks/link.css b/server/src/assets/styles/_blocks/link.css new file mode 100644 index 00000000..6f233b46 --- /dev/null +++ b/server/src/assets/styles/_blocks/link.css @@ -0,0 +1,12 @@ +.pc-link-btn { + border: none; + padding: var(--w) calc(2 * var(--w)); + font-weight: var(--font-weight-md); + cursor: pointer; + background-color: inherit; +} + +.pc-link-btn:hover, +.pc-link-btn[aria-current='page'] { + background-color: var(--background-default-hover); +} diff --git a/server/src/assets/styles/_blocks/nav.css b/server/src/assets/styles/_blocks/nav.css new file mode 100644 index 00000000..f0ef8a5f --- /dev/null +++ b/server/src/assets/styles/_blocks/nav.css @@ -0,0 +1,79 @@ +.pc-nav { + color: var(--text-muted); +} + +.pc-nav ul { + list-style-type: none; + padding: 0; + margin-block: 0; +} + +/* Links get padding to facilitate clicking */ + +/* First-level */ +.pc-nav .pc-nav-entry > a, +.pc-nav .pc-nav-entry summary { + padding-block: calc(3 * var(--v)); + padding-inline: calc(6 * var(--v)); +} +/* Second-level */ +.pc-nav details a { + display: block; + padding-block: calc(2 * var(--v)); + padding-inline: calc(4 * var(--v)); +} + +/* Active links get decorations */ + +.pc-nav a[aria-current='page'] { + color: var(--text-default); + font-weight: bold; +} + +.pc-nav a[aria-current='page'] { + position: relative; +} + +.pc-nav a[aria-current='page']::before { + position: absolute; + content: ''; + inset: 0; + width: var(--v); + border-top-right-radius: var(--v); + border-bottom-right-radius: var(--v); + background-color: var(--background-action-violet); +} + +/* Active link groups get showcased less prominently */ + +.pc-nav .pc-nav-entry.active summary { + color: var(--text-default); +} + +/* First-level links get a hover effect */ + +.pc-nav a:hover, +.pc-nav .pc-nav-entry summary:hover { + color: var(--text-default); +} + +/* Link group headers are shown as togglable */ + +.pc-nav details > summary { + cursor: pointer; +} + +.pc-nav details > summary::after { + content: '⌄'; + font-size: var(--font-size-lg); + margin-left: auto; +} + +/* Link groups are shown in a box */ + +.pc-nav details ul { + margin-inline: calc(3 * var(--w)); + box-shadow: var(--shadow-inner); + background-color: var(--background-alt-grey); + border-radius: var(--radius-sm); +} diff --git a/server/src/assets/styles/_components/input/input.css b/server/src/assets/styles/_blocks/select-group.css similarity index 63% rename from server/src/assets/styles/_components/input/input.css rename to server/src/assets/styles/_blocks/select-group.css index 7f9f5c9b..72a78fb3 100644 --- a/server/src/assets/styles/_components/input/input.css +++ b/server/src/assets/styles/_blocks/select-group.css @@ -1,17 +1,3 @@ -.pc-input-group { - margin-bottom: calc(2 * var(--w)); -} - -.pc-input-group > input { - appearance: none; - display: block; - width: 100%; - background-color: var(--background-default); - border: 1px solid var(--border-default); - border-radius: var(--radius-sm); - padding: calc(2 * var(--v)) calc(3 * var(--v)); -} - .pc-select-group { margin-bottom: calc(2 * var(--w)); } @@ -29,9 +15,3 @@ border-radius: var(--radius-sm); padding: var(--w) calc(5 * var(--w)) var(--w) calc(3 * var(--v)); } - -.pc-input-group > label, -.pc-select-group > label { - display: block; - padding-bottom: var(--v); -} diff --git a/server/src/assets/styles/_components/table/table.css b/server/src/assets/styles/_blocks/table.css similarity index 100% rename from server/src/assets/styles/_components/table/table.css rename to server/src/assets/styles/_blocks/table.css diff --git a/server/src/assets/styles/_components/card/card.css b/server/src/assets/styles/_components/card/card.css deleted file mode 100644 index 7a18cb75..00000000 --- a/server/src/assets/styles/_components/card/card.css +++ /dev/null @@ -1,9 +0,0 @@ -.pc-card { - background-color: var(--background-default); - box-shadow: var(--shadow-default); -} - -.pc-card__content { - padding: calc(2 * var(--w)); - padding-top: calc(3 * var(--w)); -} diff --git a/server/src/assets/styles/_components/container/container.css b/server/src/assets/styles/_components/container/container.css deleted file mode 100644 index 24469cfd..00000000 --- a/server/src/assets/styles/_components/container/container.css +++ /dev/null @@ -1,5 +0,0 @@ -.pc-container { - width: 100%; - max-width: calc(160 * var(--w)); - margin-inline: auto; -} diff --git a/server/src/assets/styles/_components/index.css b/server/src/assets/styles/_components/index.css deleted file mode 100644 index ffe41087..00000000 --- a/server/src/assets/styles/_components/index.css +++ /dev/null @@ -1,10 +0,0 @@ -@import './breadcrumb/breadcrumb.css'; -@import './button/button.css'; -@import './card/card.css'; -@import './container/container.css'; -@import './dropdown/dropdown.css'; -@import './icon/icon.css'; -@import './input/input.css'; -@import './link/link.css'; -@import './nav/nav.css'; -@import './table/table.css'; diff --git a/server/src/assets/styles/_components/link/link.css b/server/src/assets/styles/_components/link/link.css deleted file mode 100644 index 3e8fcf28..00000000 --- a/server/src/assets/styles/_components/link/link.css +++ /dev/null @@ -1,8 +0,0 @@ -button.pc-link { - background: none; - border: none; - padding: 0; - color: var(--text-link); - cursor: pointer; - text-decoration: underline; -} diff --git a/server/src/assets/styles/_components/nav/nav.css b/server/src/assets/styles/_components/nav/nav.css deleted file mode 100644 index f6f0e1e9..00000000 --- a/server/src/assets/styles/_components/nav/nav.css +++ /dev/null @@ -1,71 +0,0 @@ -.pc-nav { - padding: calc(2 * var(--w)) 0; -} - -.pc-nav > ul { - list-style-type: none; - padding: 0; -} - -.pc-nav li.active { - position: relative; -} - -.pc-nav li.active > details > summary { - font-weight: bold; -} - -.pc-nav > ul > li ul { - list-style-type: none; - padding: 0; - margin: 0 calc(2 * var(--w)); - box-shadow: var(--shadow-inner); - background-color: var(--background-alt-grey); -} - -.pc-nav details > summary { - cursor: pointer; - color: var(--text-muted); -} - -.pc-nav details > summary::after { - content: '⌄'; -} - -.pc-nav a, -.pc-nav details > summary { - display: inline-flex; - column-gap: calc(2 * var(--v)); - align-items: center; - width: 100%; - padding: calc(3 * var(--v)) calc(5 * var(--v)); -} - -.pc-nav a[aria-current='page'] { - font-weight: bold; -} - -.pc-nav a:not([aria-current='page']) { - color: var(--text-muted); -} - -.pc-nav a[aria-current='page'] { - position: relative; -} - -.pc-nav li.active::before, -.pc-nav > ul > li > a[aria-current='page']::before { - position: absolute; - content: ''; - inset: 0; - left: 0; - width: var(--v); - background-color: var(--background-action-violet); - border-top-right-radius: var(--radius-lg); - border-bottom-right-radius: var(--radius-lg); -} - -.pc-nav details summary > svg, -svg.pc-icon--sm { - display: inline; -} diff --git a/server/src/assets/styles/_defaults.css b/server/src/assets/styles/_defaults.css index a35b271e..1de30914 100644 --- a/server/src/assets/styles/_defaults.css +++ b/server/src/assets/styles/_defaults.css @@ -8,28 +8,3 @@ body { h1 { margin-bottom: calc(3 * var(--w)); } - -label.required::after { - content: ' *'; - color: var(--text-error); -} - -button { - cursor: pointer; -} - -button:not(:disabled):hover { - background-color: var(--hover-tint); -} - -a:not(.pc-btn) { - color: currentColor; -} - -a:not(.pc-btn):visited { - color: currentColor; -} - -select { - display: block; -} diff --git a/server/src/assets/styles/_layouts.css b/server/src/assets/styles/_layouts.css deleted file mode 100644 index 38ab85cf..00000000 --- a/server/src/assets/styles/_layouts.css +++ /dev/null @@ -1,52 +0,0 @@ -.pc-app { - display: grid; - grid-template-areas: - 'brand header' - 'sidebar content'; - grid-template-columns: auto 1fr; - grid-template-rows: auto 1fr; - height: 100vh; - background-color: var(--background-alt-grey); -} - -.pc-app__brand { - grid-area: brand; - z-index: 2; - background-color: var(--background-default); - padding: calc(3 * var(--v)) calc(6 * var(--v)); -} - -.pc-app__brand > a { - display: inline-flex; - align-items: center; - column-gap: calc(2 * var(--v)); - font-size: var(--font-size-md); - font-weight: bold; -} - -.pc-app__brand > a > img { - width: calc(8 * var(--v)); - height: calc(8 * var(--v)); -} - -.pc-app__sidebar { - grid-area: sidebar; - z-index: 2; - background-color: var(--background-default); -} - -.pc-app__content { - grid-area: content; - padding: calc(3 * var(--w)); -} - -.pc-app__header { - grid-area: header; - background-color: var(--background-default); - display: flex; - justify-content: end; - align-items: center; - padding: calc(3 * var(--v)) calc(6 * var(--v)); - z-index: 1; - box-shadow: var(--shadow-default); -} diff --git a/server/src/assets/styles/_reset.css b/server/src/assets/styles/_reset.css index 7e369501..ff354e48 100644 --- a/server/src/assets/styles/_reset.css +++ b/server/src/assets/styles/_reset.css @@ -63,3 +63,13 @@ h6 { #__next { isolation: isolate; } + +/* Our own reset */ + +/* +9. Remove default link styles +*/ +a { + color: inherit; + text-decoration: none; +} diff --git a/server/src/assets/styles/_utilities.css b/server/src/assets/styles/_utilities.css index d72944c1..62063f22 100644 --- a/server/src/assets/styles/_utilities.css +++ b/server/src/assets/styles/_utilities.css @@ -3,33 +3,6 @@ place-items: center; } -.pc-row { - display: flex; - gap: var(--row-gap, 0); -} - -.pc-row--middle { - align-items: center; -} - -.pc-background-alt-grey { - background-color: var(--background-alt-grey); -} - -.pc-cols--even { - --cols: 1; - display: grid; - grid-template-columns: repeat(var(--cols), 1fr); - gap: var(--gap, calc(2 * var(--w))); -} - -.pc-grid { - display: grid; - grid-template-rows: repeat(var(--rows), 1fr); - grid-template-columns: repeat(var(--cols), 1fr); - gap: var(--gap, calc(2 * var(--w))); -} - .pc-m { margin: var(--m); } diff --git a/server/src/assets/styles/_utilities/background.css b/server/src/assets/styles/_utilities/background.css new file mode 100644 index 00000000..6e38afed --- /dev/null +++ b/server/src/assets/styles/_utilities/background.css @@ -0,0 +1,7 @@ +.pc-background-default { + background-color: var(--background-default); +} + +.pc-background-alt-grey { + background-color: var(--background-alt-grey); +} diff --git a/server/src/assets/styles/_utilities/container.css b/server/src/assets/styles/_utilities/container.css new file mode 100644 index 00000000..68222b5f --- /dev/null +++ b/server/src/assets/styles/_utilities/container.css @@ -0,0 +1,5 @@ +.pc-container { + max-width: min(80rem, 100%); + margin-inline: auto; + padding-inline: calc(3 * var(--w)); +} diff --git a/server/src/assets/styles/_utilities/flex.css b/server/src/assets/styles/_utilities/flex.css new file mode 100644 index 00000000..8bce8515 --- /dev/null +++ b/server/src/assets/styles/_utilities/flex.css @@ -0,0 +1,9 @@ +.pc-flex-between { + display: flex; + justify-content: space-between; +} + +.pc-flex-end { + display: flex; + justify-content: flex-end; +} diff --git a/server/src/assets/styles/_utilities/gap.css b/server/src/assets/styles/_utilities/gap.css new file mode 100644 index 00000000..da926a79 --- /dev/null +++ b/server/src/assets/styles/_utilities/gap.css @@ -0,0 +1,3 @@ +.pc-gap { + gap: var(--gap, calc(2 * var(--w))); +} diff --git a/server/src/assets/styles/_utilities/grid.css b/server/src/assets/styles/_utilities/grid.css new file mode 100644 index 00000000..0984e457 --- /dev/null +++ b/server/src/assets/styles/_utilities/grid.css @@ -0,0 +1,16 @@ +.pc-grid { + display: grid; +} + +.pc-grid:not(.pc-grid--templated) { + grid-template-rows: repeat(var(--rows, 1), 1fr); + grid-template-columns: repeat(var(--cols, 1), 1fr); +} + +.pc-grid.pc-grid--templated { + grid-template: var(--grid-template); +} + +.pc-grid-area { + grid-area: var(--grid-area); +} diff --git a/server/src/assets/styles/_utilities/index.css b/server/src/assets/styles/_utilities/index.css new file mode 100644 index 00000000..af39618f --- /dev/null +++ b/server/src/assets/styles/_utilities/index.css @@ -0,0 +1,11 @@ +@import './background.css'; +@import './container.css'; +@import './flex.css'; +@import './gap.css'; +@import './grid.css'; +@import './padding.css'; +@import './row.css'; +@import './shadow.css'; +@import './sizing.css'; +@import './text.css'; +@import './z-index.css'; diff --git a/server/src/assets/styles/_utilities/padding.css b/server/src/assets/styles/_utilities/padding.css new file mode 100644 index 00000000..adfe8403 --- /dev/null +++ b/server/src/assets/styles/_utilities/padding.css @@ -0,0 +1,7 @@ +.pc-p { + padding: var(--p); +} + +.pc-p-block { + padding-block: var(--p-block); +} diff --git a/server/src/assets/styles/_utilities/row.css b/server/src/assets/styles/_utilities/row.css new file mode 100644 index 00000000..64bac4f2 --- /dev/null +++ b/server/src/assets/styles/_utilities/row.css @@ -0,0 +1,12 @@ +.pc-row { + display: flex; + gap: var(--row-gap, calc(2 * var(--w))); +} + +.pc-row--middle { + align-items: center; +} + +.pc-row--between { + justify-content: space-between; +} diff --git a/server/src/assets/styles/_utilities/shadow.css b/server/src/assets/styles/_utilities/shadow.css new file mode 100644 index 00000000..69e1aee0 --- /dev/null +++ b/server/src/assets/styles/_utilities/shadow.css @@ -0,0 +1,3 @@ +.pc-shadow { + box-shadow: var(--shadow-default); +} diff --git a/server/src/assets/styles/_utilities/sizing.css b/server/src/assets/styles/_utilities/sizing.css new file mode 100644 index 00000000..a3366119 --- /dev/null +++ b/server/src/assets/styles/_utilities/sizing.css @@ -0,0 +1,3 @@ +.pc-h-fullscreen { + height: 100vh; +} diff --git a/server/src/assets/styles/_utilities/text.css b/server/src/assets/styles/_utilities/text.css new file mode 100644 index 00000000..40f44669 --- /dev/null +++ b/server/src/assets/styles/_utilities/text.css @@ -0,0 +1,7 @@ +.pc-bold { + font-weight: bold; +} + +.pc-text-lg { + font-size: var(--font-size-lg); +} diff --git a/server/src/assets/styles/_utilities/z-index.css b/server/src/assets/styles/_utilities/z-index.css new file mode 100644 index 00000000..b170c834 --- /dev/null +++ b/server/src/assets/styles/_utilities/z-index.css @@ -0,0 +1,3 @@ +.pc-z-index { + z-index: var(--z); +} diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/_variables.css index 7b140960..66ef4ddc 100644 --- a/server/src/assets/styles/_variables.css +++ b/server/src/assets/styles/_variables.css @@ -13,6 +13,7 @@ --font-weight-md: 500; /* Colors */ --background-default: #ffffff; + --background-default-hover: #f1f2f3; --background-alt-grey: #f9fafb; --background-muted: #f0f0f0; --background-action-violet: #6c2bd9; @@ -20,7 +21,7 @@ --background-error: #dd1d1d; --background-error-hover: #b92020; --text-default: #282828; - --text-muted: #636363; + --text-muted: #6e6e6e; --text-on-background-action-violet: #ffffff; --text-action-violet: #6c2bd9; --text-error: #ff0000; diff --git a/server/src/assets/styles/main.css b/server/src/assets/styles/main.css index 6541a401..53ea4eae 100644 --- a/server/src/assets/styles/main.css +++ b/server/src/assets/styles/main.css @@ -1,7 +1,7 @@ @import './_variables.css'; @import './_reset.css'; @import './_defaults.css'; -@import './_layouts.css'; -@import './_components/index.css'; +@import './_blocks/index.css'; @import './_utilities.css'; +@import './_utilities/index.css'; @import './_overrides.css'; diff --git a/server/src/templates/components/attr.njk b/server/src/templates/components/attr.njk deleted file mode 100644 index c06561a0..00000000 --- a/server/src/templates/components/attr.njk +++ /dev/null @@ -1 +0,0 @@ -{% for name, value in attr %}{% if value == true %}{{ name }}{% else %}{{ name }}="{{ value }}"{% endif %}{% endfor %} diff --git a/server/src/templates/components/header.njk b/server/src/templates/components/header.njk index 79fe2384..e3cbe4ff 100644 --- a/server/src/templates/components/header.njk +++ b/server/src/templates/components/header.njk @@ -1,21 +1,21 @@ {% import 'macros/icons.njk' as icons %} -
      +
      • - - {{ icons.user(class_name='pc-icon pc-icon--sm') }} + + {{ icons.user() }} {{ 'header-profile'|trans }}
      • - {{ icons.more(class_name='pc-icon') }} + {{ icons.more(attr={class: 'pc-icon'}) }} -
        - diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk index a05abc2a..361b017e 100644 --- a/server/src/templates/components/nav.njk +++ b/server/src/templates/components/nav.njk @@ -1,41 +1,41 @@ {% import 'macros/icons.njk' as icons %} -
      Vide{{ 'common-table-empty'|trans }}
      +
      {% for column in table.columns %} @@ -18,7 +19,7 @@ diff --git a/server/src/templates/pages/customers/_form.njk b/server/src/templates/pages/customers/_form.njk index 69569cff..cf8effe4 100644 --- a/server/src/templates/pages/customers/_form.njk +++ b/server/src/templates/pages/customers/_form.njk @@ -1,29 +1,30 @@ -{% macro customer_form(customer=null, class_name='') %} -
      +{% import 'macros/buttons.njk' as buttons %} +{% from 'macros/attr.njk' import render_attr %} + +{% macro customer_form(customer=null, attr=null) %} +
      - +
      - +
      - +
      - +
      - + {{ buttons.save(attr={type: 'submit'}) }} {% endmacro %} diff --git a/server/src/templates/pages/customers/add.njk b/server/src/templates/pages/customers/add.njk index 07d39f3b..38f58430 100644 --- a/server/src/templates/pages/customers/add.njk +++ b/server/src/templates/pages/customers/add.njk @@ -1,14 +1,13 @@ {% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import customer_form %} -{% block main_class %}pc-container{% endblock %} +{% set title = 'crm-customers-add-title'|trans %} {% block main %} -

      - {{ 'crm-customers-add-title'|trans }} -

      +
      +

      {{ title }}

      -
      - {{ customer_form(class_name='pc-card__content') }} -
      + {{ customer_form(attr={class: 'pc-box'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/customers/edit.njk b/server/src/templates/pages/customers/edit.njk index 2aac3955..2d5d0312 100644 --- a/server/src/templates/pages/customers/edit.njk +++ b/server/src/templates/pages/customers/edit.njk @@ -2,18 +2,14 @@ {% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import customer_form %} -{% block main_class %}pc-container{% endblock %} - {% set title = 'crm-customers-edit-title'|trans({name: customer.name }) %} {% block main %} +
      {{ breadcrumb([{ title: 'crm-customers-title'|trans, href: path('crm_customers_list') }, { title: title }]) }} -

      - {{ title }} -

      +

      {{ title }}

      -
      - {{ customer_form(customer, class_name='pc-card__content') }} -
      + {{ customer_form(customer, attr={class: 'pc-box'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/customers/list.njk b/server/src/templates/pages/customers/list.njk index f7991da8..682f7463 100644 --- a/server/src/templates/pages/customers/list.njk +++ b/server/src/templates/pages/customers/list.njk @@ -1,16 +1,21 @@ {% extends 'layouts/app.njk' %} +{% import 'macros/links.njk' as links %} {% from 'macros/table.njk' import render_table with context %} {% from 'macros/breadcrumb.njk' import breadcrumb %} -{% block main_class %}pc-container{% endblock %} +{% set title = 'crm-customers-title'|trans %} {% block main %} - {{ breadcrumb([{ title: 'crm-customers-title'|trans }]) }} +
      + {{ breadcrumb([{ title: title }]) }} -
      -

      {{ 'crm-customers-title'|trans }}

      - {{ 'common-add'|trans }} +
      +

      + {{ title }} +

      + {{ links.add(path('crm_customers_add'))}}
      {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/faircalendar/events/_form.njk b/server/src/templates/pages/faircalendar/events/_form.njk index 5afb29b1..6d2af2a0 100644 --- a/server/src/templates/pages/faircalendar/events/_form.njk +++ b/server/src/templates/pages/faircalendar/events/_form.njk @@ -1,7 +1,11 @@ -{% macro event_form(event, types, projects, tasks, times, date=null, class_name='') %} -
      +{% import 'macros/buttons.njk' as buttons %} +{% import 'macros/icons.njk' as icons %} +{% from 'macros/attr.njk' import render_attr %} + +{% macro event_form(event, types, projects, tasks, times, date=null, attr=null) %} +
      - +
      -
      +
      - + {% for task in tasks %} @@ -29,9 +33,9 @@
      -
      +
      - + {% endif %} - - + + {{ buttons.save(attr={type: 'submit'}) }} {% endmacro %} diff --git a/server/src/templates/pages/faircalendar/events/add.njk b/server/src/templates/pages/faircalendar/events/add.njk index 148f1333..60f8613b 100644 --- a/server/src/templates/pages/faircalendar/events/add.njk +++ b/server/src/templates/pages/faircalendar/events/add.njk @@ -2,16 +2,14 @@ {% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import event_form %} -{% block main_class %}pc-container{% endblock %} - {% set title = 'faircalendar-events-add-title'|trans({ date: date }) %} {% block main %} +
      {{ breadcrumb([{ title: 'faircalendar-title'|trans, href: path('faircalendar_index') }, { title: title }]) }}

      {{ title }}

      -
      - {{ event_form(null, types, projects, tasks, times, date, class_name='pc-card__content') }} -
      + {{ event_form(null, types, projects, tasks, times, date, attr=={class: 'pc-box'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/faircalendar/events/edit.njk b/server/src/templates/pages/faircalendar/events/edit.njk index c5c0641e..5d5c6f26 100644 --- a/server/src/templates/pages/faircalendar/events/edit.njk +++ b/server/src/templates/pages/faircalendar/events/edit.njk @@ -1,26 +1,26 @@ {% extends 'layouts/app.njk' %} {% from 'macros/breadcrumb.njk' import breadcrumb %} +{% import 'macros/icons.njk' as icons %} {% from './_form.njk' import event_form %} -{% block main_class %}pc-container{% endblock %} - {% set title = 'faircalendar-events-edit-title'|trans({ date: event.date }) %} {% block main %} +
      {{ breadcrumb([{ title: 'faircalendar-title'|trans, href: path('faircalendar_index') }, { title: title }]) }} -
      +

      {{ title }}

      -
      -
      - {{ event_form(event, types, projects, tasks, times, class_name='pc-card__content') }} -
      + {{ event_form(event, types, projects, tasks, times, attr={class: 'pc-box pc-mt', style: '--mt: calc(4 * var(--w))'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/faircalendar/index.njk b/server/src/templates/pages/faircalendar/index.njk index e261c82b..14149691 100644 --- a/server/src/templates/pages/faircalendar/index.njk +++ b/server/src/templates/pages/faircalendar/index.njk @@ -1,34 +1,34 @@ {% extends 'layouts/app.njk' %} {% from 'macros/breadcrumb.njk' import breadcrumb %} -{% block main_class %}pc-container{% endblock %} - {% set title = 'faircalendar-title'|trans %} {% block main %} -{{ breadcrumb([{ title: title}]) }} +
      + {{ breadcrumb([{ title: title}]) }} -

      {{ title }}

      +

      {{ title }}

      -
      -
      -
      - - -
      -
      - - + +
      +
      + + +
      +
      + + +
      -
      - + - + +
      {% endblock main %} diff --git a/server/src/templates/pages/home.njk b/server/src/templates/pages/home.njk index 7a9c754c..d4203a5f 100644 --- a/server/src/templates/pages/home.njk +++ b/server/src/templates/pages/home.njk @@ -1,7 +1,7 @@ {% extends 'layouts/app.njk' %} -{% block main_class %}pc-container{% endblock %} - {% block main %} -

      {{ 'home-title'|trans({ user: req.user|fullName }) }}

      +
      +

      {{ 'home-title'|trans({ user: req.user|fullName }) }}

      +
      {% endblock main %} diff --git a/server/src/templates/pages/login.njk b/server/src/templates/pages/login.njk index 62149174..a7733659 100644 --- a/server/src/templates/pages/login.njk +++ b/server/src/templates/pages/login.njk @@ -1,28 +1,33 @@ {% extends 'layouts/blank.njk' %} +{% import 'macros/icons.njk' as icons %} +{% from 'macros/attr.njk' import render_attr %} -{% block title %}Se connecter - {{ super() }}{% endblock title %} -{% block body_class %}pc-center pc-background-alt-grey{% endblock body_class %} +{% block body_attr %}{{ render_attr({ class: 'pc-center pc-background-alt-grey' }) }}{% endblock body_attr %} +{% block title %}Se connecter - {{ super() }}{% endblock %} {% block main %} -
      -
      +
      +
      -
      +

      Connexion

      - +
      - +
      - +
      diff --git a/server/src/templates/pages/profile/_form.njk b/server/src/templates/pages/profile/_form.njk index 432c5fb1..8d723271 100644 --- a/server/src/templates/pages/profile/_form.njk +++ b/server/src/templates/pages/profile/_form.njk @@ -1,31 +1,32 @@ +{% import 'macros/buttons.njk' as buttons %} +{% from 'macros/attr.njk' import render_attr %} + {% macro profile_fields(user, require_password=false) %}
      - +
      - +
      - +
      - +
      {% endmacro %} -{% macro profile_form(user, class_name='') %} -
      +{% macro profile_form(user, attr=null) %} + {{ profile_fields(user) }} - + {{ buttons.save(attr={ type: 'submit' }) }} {% endmacro %} diff --git a/server/src/templates/pages/profile/edit.njk b/server/src/templates/pages/profile/edit.njk index 2a52813a..97399393 100644 --- a/server/src/templates/pages/profile/edit.njk +++ b/server/src/templates/pages/profile/edit.njk @@ -2,18 +2,16 @@ {% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import profile_form %} -{% block main_class %}pc-container{% endblock %} - {% set title = 'profile-title'|trans %} {% block main %} +
      {{ breadcrumb([{ title: title }]) }}

      {{ title }}

      -
      - {{ profile_form(user, class_name='pc-card__content') }} -
      + {{ profile_form(user, attr={class: 'pc-box pc-mt', style: '--mt: calc(3 * var(--w))'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/projects/_form.njk b/server/src/templates/pages/projects/_form.njk index 71e2e991..2dbbd384 100644 --- a/server/src/templates/pages/projects/_form.njk +++ b/server/src/templates/pages/projects/_form.njk @@ -1,12 +1,15 @@ -{% macro project_form(project, customers, class_name='') %} -
      +{% import 'macros/buttons.njk' as buttons %} +{% from 'macros/attr.njk' import render_attr %} + +{% macro project_form(project, customers, attr=null) %} +
      - +
      - +
      - + {{ buttons.save(attr={type: 'submit'}) }} {% endmacro %} diff --git a/server/src/templates/pages/projects/add.njk b/server/src/templates/pages/projects/add.njk index c1d91690..9a5abb51 100644 --- a/server/src/templates/pages/projects/add.njk +++ b/server/src/templates/pages/projects/add.njk @@ -2,18 +2,16 @@ {% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import project_form %} -{% block main_class %}pc-container{% endblock %} - {% set title = 'crm-projects-add-title'|trans %} {% block main %} +
      {{ breadcrumb([{ title: 'crm-projects-title'|trans, href: path('crm_projects_list') }, { title: title }]) }}

      {{ title }}

      -
      - {{ project_form(null, customers, class_name='pc-card__content') }} -
      + {{ project_form(null, customers, attr={class: 'pc-box'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/projects/edit.njk b/server/src/templates/pages/projects/edit.njk index c36ca0e3..f13adb21 100644 --- a/server/src/templates/pages/projects/edit.njk +++ b/server/src/templates/pages/projects/edit.njk @@ -2,18 +2,16 @@ {% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import project_form %} -{% block main_class %}pc-container{% endblock %} - {% set title = 'crm-projects-edit-title'|trans({name: project.name }) %} {% block main %} +
      {{ breadcrumb([{ title: 'crm-projects-title'|trans, href: path('crm_projects_list') }, { title: title }]) }}

      {{ title }}

      -
      - {{ project_form(project, customers, class_name='pc-card__content') }} -
      + {{ project_form(project, customers, attr={class: 'pc-box'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/projects/list.njk b/server/src/templates/pages/projects/list.njk index ebb09d6c..6d31b50c 100644 --- a/server/src/templates/pages/projects/list.njk +++ b/server/src/templates/pages/projects/list.njk @@ -1,16 +1,17 @@ {% extends 'layouts/app.njk' %} +{% import 'macros/links.njk' as links %} {% from 'macros/table.njk' import render_table with context %} {% from 'macros/breadcrumb.njk' import breadcrumb %} -{% block main_class %}pc-container{% endblock %} - {% block main %} +
      {{ breadcrumb([{ title: 'crm-projects-title'|trans }]) }} -
      +

      {{ 'crm-projects-title'|trans }}

      - {{ 'common-add'|trans }} + {{ links.add(path('crm_projects_add'))}}
      {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/tasks/_form.njk b/server/src/templates/pages/tasks/_form.njk index 3c3657a8..5daa7a53 100644 --- a/server/src/templates/pages/tasks/_form.njk +++ b/server/src/templates/pages/tasks/_form.njk @@ -1,12 +1,13 @@ -{% macro task_form(task=null, class_name='') %} -
      +{% import 'macros/buttons.njk' as buttons %} +{% from 'macros/attr.njk' import render_attr %} + +{% macro task_form(task=null, attr=null) %} +
      - +
      - + {{ buttons.save(attr={type: 'submit'}) }} {% endmacro %} diff --git a/server/src/templates/pages/tasks/add.njk b/server/src/templates/pages/tasks/add.njk index 4b9584db..afe542f3 100644 --- a/server/src/templates/pages/tasks/add.njk +++ b/server/src/templates/pages/tasks/add.njk @@ -2,18 +2,16 @@ {% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import task_form %} -{% block main_class %}pc-container{% endblock %} - {% set title = 'crm-tasks-add-title'|trans %} {% block main %} +
      {{ breadcrumb([{ title: 'crm-tasks-title'|trans, href: path('crm_tasks_list') }, { title: title }]) }}

      {{ title }}

      -
      - {{ task_form(class_name='pc-card__content') }} -
      + {{ task_form(attr={class: 'pc-box'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/tasks/edit.njk b/server/src/templates/pages/tasks/edit.njk index 92e2d647..50f4a7ef 100644 --- a/server/src/templates/pages/tasks/edit.njk +++ b/server/src/templates/pages/tasks/edit.njk @@ -2,18 +2,16 @@ {% from 'macros/breadcrumb.njk' import breadcrumb %} {% from './_form.njk' import task_form %} -{% block main_class %}pc-container{% endblock %} - {% set title = 'crm-tasks-edit-title'|trans({name: task.name }) %} {% block main %} +
      {{ breadcrumb([{ title: 'crm-tasks-title'|trans, href: path('crm_tasks_list') }, { title: title }]) }}

      {{ title }}

      -
      - {{ task_form(task, class_name='pc-card__content') }} -
      + {{ task_form(task, attr={ class: 'pc-box' }) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/tasks/list.njk b/server/src/templates/pages/tasks/list.njk index dae7ed8f..bb6fb175 100644 --- a/server/src/templates/pages/tasks/list.njk +++ b/server/src/templates/pages/tasks/list.njk @@ -1,16 +1,17 @@ {% extends 'layouts/app.njk' %} +{% import 'macros/links.njk' as links %} {% from 'macros/table.njk' import render_table with context %} {% from 'macros/breadcrumb.njk' import breadcrumb %} -{% block main_class %}pc-container{% endblock %} - {% block main %} +
      {{ breadcrumb([{ title: 'crm-tasks-title'|trans }]) }} -
      +

      {{ 'crm-tasks-title'|trans }}

      - {{ 'common-add'|trans }} + {{ links.add(path('crm_tasks_add'))}}
      {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} +
      {% endblock main %} diff --git a/server/src/templates/pages/users/_form.njk b/server/src/templates/pages/users/_form.njk index eb59f036..0b0148ea 100644 --- a/server/src/templates/pages/users/_form.njk +++ b/server/src/templates/pages/users/_form.njk @@ -1,9 +1,11 @@ +{% import 'macros/buttons.njk' as buttons %} +{% from 'macros/attr.njk' import render_attr %} {% from 'pages/profile/_form.njk' import profile_fields %} {% macro _user_administrative_fields(userAdministrative, contracts, workingTimes) %} -
      +
      - + {% for workingTime in workingTimes %} @@ -21,7 +23,7 @@
      - + @@ -37,31 +39,31 @@
      -
      +
      - +
      - +
      - +
      -
      +
      - +
      - +
      @@ -69,7 +71,7 @@ {% macro _user_role_field(user, roles) %}
      - +
      {% if value.actions.edit %} - {{ icons.pencil(class_name='pc-icon pc-icon--sm pc-icon--action-violet') }} + {{ icons.pencil(attr={class: 'pc-icon pc-icon--sm pc-icon--action-violet'}) }} {% endif %}
      - - - {% for column in table.columns %} - - {% endfor %} - - - - {% for row in table.rows %} - - {% for value in row %} - {% if value.actions %} - - {% else %} - - {% endif %} +{% set attr = attr|merge({class: 'pc-table-wrapper ' + attr.class|default('')}) %} +
      +
      {{ column|trans }}
      - {% if value.actions.edit %} - - {{ icons.pencil(attr={class: 'pc-icon pc-icon--sm pc-icon--action-violet'}) }} - - {% endif %} - - {% if value.safe %} - {{ value.safe|safe }} - {% elseif value.trans %} - {{ value.trans.message|trans(value.trans.params) }} - {% else %} - {{ value }} - {% endif %} -
      + + + {% for column in table.columns %} + {% endfor %} - {% else %} + + + {% for row in table.rows %} - + {% for value in row %} + + {% endfor %} - {% endfor %} - -
      {{ column|trans }}
      {{ 'common-table-empty'|trans }} + {{ _render_value(value) }} +
      + {% else %} +
      {{ 'common-table-empty'|trans }}
      +
    +{% endmacro %} + +{% macro render_inline(inline) %} +{% set attr = attr|merge({class: 'pc-table-wrapper ' + attr.class|default('')}) %} +
    + + + {% for column, value in inline.columns|zip(inline.row) %} + + + + + {% else %} + + + + {% endfor %} + +
    {{ column|trans }} + {{ _render_value(value) }} +
    {{ 'common-table-empty'|trans }}
    +
    {% endmacro %} diff --git a/server/src/templates/pages/customers/add.njk b/server/src/templates/pages/customers/add.njk index 38f58430..b2f1da95 100644 --- a/server/src/templates/pages/customers/add.njk +++ b/server/src/templates/pages/customers/add.njk @@ -6,6 +6,8 @@ {% block main %}
    + {{ breadcrumb([{ title: 'crm-customers-title'|trans, href: path('crm_customers_list') }, { title: title }]) }} +

    {{ title }}

    {{ customer_form(attr={class: 'pc-box'}) }} diff --git a/server/src/templates/pages/faircalendar/index.njk b/server/src/templates/pages/faircalendar/index.njk index 14149691..8f943b68 100644 --- a/server/src/templates/pages/faircalendar/index.njk +++ b/server/src/templates/pages/faircalendar/index.njk @@ -29,6 +29,7 @@
    {% endblock main %} diff --git a/server/src/templates/pages/leave_requests/_form.njk b/server/src/templates/pages/leave_requests/_form.njk new file mode 100644 index 00000000..d08854bb --- /dev/null +++ b/server/src/templates/pages/leave_requests/_form.njk @@ -0,0 +1,70 @@ +{% import 'macros/buttons.njk' as buttons %} +{% from 'macros/attr.njk' import render_attr %} + +{% macro leave_request_form(leaveRequest, types, attr=null) %} +
    +
    + + +
    + +
    +
    + + +
    + +
    + + +
    +
    + +
    +
    + + +
    + +
    + + +
    +
    + +
    + + +
    + + {{ buttons.save(attr={type: 'submit'}) }} +
    +{% endmacro %} + +{% macro leave_request_moderation_form(leaveRequest) %} +
    +
    + + +
    + +
    + + +
    +
    +{% endmacro %} diff --git a/server/src/templates/pages/leave_requests/add.njk b/server/src/templates/pages/leave_requests/add.njk new file mode 100644 index 00000000..fca10b1d --- /dev/null +++ b/server/src/templates/pages/leave_requests/add.njk @@ -0,0 +1,15 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} +{% from './_form.njk' import leave_request_form %} + +{% set title = 'leave-requests-add-title'|trans %} + +{% block main %} +
    + {{ breadcrumb([{ title: 'people-title'|trans }, { title: 'leaves-title'|trans, href: path('people_leaves_list') }, { title: 'leave-requests-title'|trans, href: path('people_leave_requests_list') }, { title: title }]) }} + +

    {{ title }}

    + + {{ leave_request_form(null, types, attr={class: 'pc-box'}) }} +
    +{% endblock main %} diff --git a/server/src/templates/pages/leave_requests/detail.njk b/server/src/templates/pages/leave_requests/detail.njk new file mode 100644 index 00000000..2f8e93d8 --- /dev/null +++ b/server/src/templates/pages/leave_requests/detail.njk @@ -0,0 +1,25 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} +{% from 'macros/table.njk' import render_inline %} +{% from './_form.njk' import leave_request_moderation_form with context %} + +{% set title = 'leave-requests-edit-title'|trans({ user: leaveRequest.user|fullName }) %} + +{% block main %} +
    + {{ breadcrumb([{ title: 'people-title'|trans }, { title: 'leaves-title'|trans, href: path('people_leaves_list') }, { title: 'leave-requests-title'|trans, href: path('people_leave_requests_list') }, { title: title }]) }} + +

    {{ title }}

    + + {{ render_inline(inline, attr={class: 'pc-box'}) }} + +
    + {% if canModerate %} +

    {{ 'leave-requests-moderation'|trans }}

    + {{ leave_request_moderation_form(leaveRequest) }} + {% else %} +

    {{ 'leave-requests-error-cannot-moderate'|trans }}

    + {% endif %} +
    +
    +{% endblock main %} diff --git a/server/src/templates/pages/leave_requests/edit.njk b/server/src/templates/pages/leave_requests/edit.njk new file mode 100644 index 00000000..fd11d96e --- /dev/null +++ b/server/src/templates/pages/leave_requests/edit.njk @@ -0,0 +1,15 @@ +{% extends 'layouts/app.njk' %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} +{% from './_form.njk' import leave_request_form %} + +{% set title = 'leave-requests-edit-title'|trans({ user: leaveRequest.user|fullName }) %} + +{% block main %} +
    + {{ breadcrumb([{ title: 'people-title'|trans }, { title: 'leaves-title'|trans, href: path('people_leaves_list') }, { title: 'leave-requests-title'|trans, href: path('people_leave_requests_list') }, { title: title }]) }} + +

    {{ title }}

    + + {{ leave_request_form(leaveRequest, types, attr={class: 'pc-box'}) }} +
    +{% endblock main %} diff --git a/server/src/templates/pages/leave_requests/list.njk b/server/src/templates/pages/leave_requests/list.njk new file mode 100644 index 00000000..2a379a21 --- /dev/null +++ b/server/src/templates/pages/leave_requests/list.njk @@ -0,0 +1,21 @@ +{% extends 'layouts/app.njk' %} +{% import 'macros/links.njk' as links %} +{% from 'macros/table.njk' import render_table with context %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} + +{% set title = 'leave-requests-title'|trans %} + +{% block main %} +
    + {{ breadcrumb([{ title: 'people-title'|trans }, { title: 'leaves-title'|trans, href: path('people_leaves_list') }, { title: title }]) }} + +
    +

    + {{ title }} +

    + {{ links.add(path('people_leave_requests_add'), text='leave-requests-add-title'|trans) }} +
    + + {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} +
    +{% endblock main %} diff --git a/server/src/templates/pages/leaves/list.njk b/server/src/templates/pages/leaves/list.njk new file mode 100644 index 00000000..97e4d133 --- /dev/null +++ b/server/src/templates/pages/leaves/list.njk @@ -0,0 +1,25 @@ +{% extends 'layouts/app.njk' %} +{% import 'macros/icons.njk' as icons %} +{% import 'macros/links.njk' as links %} +{% from 'macros/table.njk' import render_table with context %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} + +{% set title = 'leaves-title'|trans %} + +{% block main %} +
    + {{ breadcrumb([{ title: 'people-title'|trans }, { title: title }]) }} + + + + {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} +
    +{% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index e92538c5..342af4de 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -1,5 +1,6 @@ common-form-save = Enregistrer common-form-delete = Supprimer +common-view = Voir common-add = Ajouter common-edit = Modifier common-actions = Actions @@ -26,6 +27,8 @@ faircalendar-type-option = {$type -> [dojo] Dojos [support] Supports [formationConference] Formations / Confs + [leave] Congés + [holiday] Jour férié *[other] Autre } faircalendar-taskId-title = Mission @@ -98,3 +101,41 @@ users-transportFee = Frais de transport users-sustainableMobilityFee = Forfait mobilité durable users-joiningDate = Date d'entrée users-leavingDate = Date de sortie + +leaves-title = Congés +leaves-user = Coopérateur·ice - salarié·e +leaves-period = Période +leaves-type = Type de congé +leaves-type-value = {$type -> + [paid] Congé payé + [unpaid] Congé sans solde + [special] Congé exceptionnel + [medical] Congé maladie + [illimited] Congé illimité + *[other] Autre +} +leaves-startDate = Du +leaves-endDate = Au +leaves-period-value = Du {$startDate} au {$endDate} +leaves-allDay = Toute la journée +leaves-comment = Commentaire +leaves-status = État +leaves-status-value = {$status -> + [pending] En attente de validation + [accepted] Accepté + [refused] Refusé + *[other] Autre +} +leaves-duration = Durée +leaves-duration-value = {$days -> + [one] 1 jour + *[other] {$days} jours +} +leaves-see-requests = Voir les demandes de congés +leave-requests-title = Demandes de congés +leave-requests-add-title = Faire une demande de congés +leave-requests-edit-title = Demande de {$user} +leave-requests-error-cannot-moderate = Vous ne pouvez pas modérer cette demande de congés. +leave-requests-moderation = Modération +leave-requests-moderation-accept = Accepter la demande de congés +leave-requests-moderation-deny = Refuser la demande de congés From 44eb1ec4c5e491024eea3e6c4a24f9a948a3be23 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Wed, 27 Sep 2023 23:36:51 +0200 Subject: [PATCH 27/49] Add PayrollElements pages, rework Table implementation to reuse logic for HTML and CSV outputs --- .../Query/GetUserElementsQueryHandler.spec.ts | 2 +- .../Query/GetUsersElementsQueryHandler.ts | 2 +- .../Payslip/View/UserElementsView.ts | 2 +- .../Adapter/FluentTranslatorAdapter.ts | 8 +- .../src/Infrastructure/Common/Table/Table.ts | 34 ----- .../Common/Templating/filters.ts | 28 ---- .../Infrastructure/Common/Templating/index.ts | 60 -------- .../Common/Utils/formatUtils.ts | 7 + .../Customer/Table/CustomerTableFactory.ts | 35 ++--- .../Customer/customer.module.ts | 4 +- .../Controller/FairCalendarController.ts | 2 +- .../Leave/Table/LeaveRequestTableFactory.ts | 86 ++++------- .../Leave/Table/LeaveTableFactory.ts | 57 +++----- .../GetPayrollElementsController.ts | 33 +++++ .../Table/PayrollElementsTableFactory.ts | 70 +++++++++ .../Action/GetUsersElementsCsvAction.ts | 2 +- .../User/Table/UserTableFactory.ts | 37 ++--- .../HumanResource/humanResource.module.ts | 12 +- .../Project/Table/ProjectTableFactory.ts | 33 +++-- .../Infrastructure/Project/project.module.ts | 4 +- .../src/Infrastructure/Tables/RowFactory.ts | 135 ++++++++++++++++++ .../Infrastructure/Tables/TableCsvFactory.ts | 24 ++++ server/src/Infrastructure/Tables/index.ts | 15 ++ .../Infrastructure/Tables/tables.module.ts | 14 ++ .../Task/Table/TaskTableFactory.ts | 27 ++-- server/src/Infrastructure/Task/task.module.ts | 8 +- .../Infrastructure/Templates/ITemplates.ts | 9 ++ .../NunjucksTemplates/NunjucksTemplates.ts | 108 ++++++++++++++ .../NunjucksTemplates/TablesExtension.ts | 46 ++++++ .../Templates/templates.module.ts | 13 ++ .../Translations/ITranslator.ts} | 0 .../Translations/translations.module.ts | 14 ++ server/src/assets/customElements/blobLink.js | 9 ++ server/src/assets/customElements/index.js | 2 + server/src/assets/styles/_blocks/link.css | 4 + server/src/main.ts | 16 +-- server/src/templates/components/nav.njk | 5 + server/src/templates/macros/table.njk | 84 ----------- .../templates/pages/customers/_address.njk | 1 + server/src/templates/pages/customers/list.njk | 3 +- .../templates/pages/leave_requests/detail.njk | 3 +- .../templates/pages/leave_requests/list.njk | 3 +- server/src/templates/pages/leaves/list.njk | 3 +- .../pages/payroll_elements/_leaves.njk | 7 + .../pages/payroll_elements/index.njk | 29 ++++ server/src/templates/pages/projects/list.njk | 3 +- server/src/templates/pages/tasks/list.njk | 3 +- server/src/templates/pages/users/list.njk | 3 +- server/src/templates/tables/cells/actions.njk | 23 +++ server/src/templates/tables/inlinetable.njk | 22 +++ server/src/templates/tables/table.njk | 30 ++++ server/src/translations/fr-FR.ftl | 34 +++++ 52 files changed, 818 insertions(+), 400 deletions(-) delete mode 100644 server/src/Infrastructure/Common/Table/Table.ts delete mode 100644 server/src/Infrastructure/Common/Templating/filters.ts delete mode 100644 server/src/Infrastructure/Common/Templating/index.ts create mode 100644 server/src/Infrastructure/HumanResource/PayrollElements/Controller/GetPayrollElementsController.ts create mode 100644 server/src/Infrastructure/HumanResource/PayrollElements/Table/PayrollElementsTableFactory.ts create mode 100644 server/src/Infrastructure/Tables/RowFactory.ts create mode 100644 server/src/Infrastructure/Tables/TableCsvFactory.ts create mode 100644 server/src/Infrastructure/Tables/index.ts create mode 100644 server/src/Infrastructure/Tables/tables.module.ts create mode 100644 server/src/Infrastructure/Templates/ITemplates.ts create mode 100644 server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts create mode 100644 server/src/Infrastructure/Templates/NunjucksTemplates/TablesExtension.ts create mode 100644 server/src/Infrastructure/Templates/templates.module.ts rename server/src/{Application/ITranslations.ts => Infrastructure/Translations/ITranslator.ts} (100%) create mode 100644 server/src/Infrastructure/Translations/translations.module.ts create mode 100644 server/src/assets/customElements/blobLink.js delete mode 100644 server/src/templates/macros/table.njk create mode 100644 server/src/templates/pages/customers/_address.njk create mode 100644 server/src/templates/pages/payroll_elements/_leaves.njk create mode 100644 server/src/templates/pages/payroll_elements/index.njk create mode 100644 server/src/templates/tables/cells/actions.njk create mode 100644 server/src/templates/tables/inlinetable.njk create mode 100644 server/src/templates/tables/table.njk diff --git a/server/src/Application/HumanResource/Payslip/Query/GetUserElementsQueryHandler.spec.ts b/server/src/Application/HumanResource/Payslip/Query/GetUserElementsQueryHandler.spec.ts index d2ddec91..7e54fb9f 100644 --- a/server/src/Application/HumanResource/Payslip/Query/GetUserElementsQueryHandler.spec.ts +++ b/server/src/Application/HumanResource/Payslip/Query/GetUserElementsQueryHandler.spec.ts @@ -160,7 +160,7 @@ describe('GetUserElementsQueryHandler', () => { transportFee, sustainableMobilityFee, 5, - 'yes', + true, new UserLeavesView(0, [ leaveRequestSlot1, leaveRequestSlot2, diff --git a/server/src/Application/HumanResource/Payslip/Query/GetUsersElementsQueryHandler.ts b/server/src/Application/HumanResource/Payslip/Query/GetUsersElementsQueryHandler.ts index 301c83f9..7f7f1c5b 100644 --- a/server/src/Application/HumanResource/Payslip/Query/GetUsersElementsQueryHandler.ts +++ b/server/src/Application/HumanResource/Payslip/Query/GetUsersElementsQueryHandler.ts @@ -60,7 +60,7 @@ export class GetUsersElementsQueryHandler { user.getUserAdministrative().getTransportFee() * 0.01, user.getUserAdministrative().getSustainableMobilityFee() * 0.01, mealTicketsByUser[user.getId()], - user.getUserAdministrative().haveHealthInsurance() ? 'yes' : 'no', + user.getUserAdministrative().haveHealthInsurance(), this.createUserLeavesView(userLeaves.paid, date), this.createUserLeavesView(userLeaves.unpaid, date), this.createUserLeavesView(userLeaves.medical, date), diff --git a/server/src/Application/HumanResource/Payslip/View/UserElementsView.ts b/server/src/Application/HumanResource/Payslip/View/UserElementsView.ts index 1c96c128..52e6504d 100644 --- a/server/src/Application/HumanResource/Payslip/View/UserElementsView.ts +++ b/server/src/Application/HumanResource/Payslip/View/UserElementsView.ts @@ -13,7 +13,7 @@ export class UserElementsView { public readonly transportFee: number, public readonly sustainableMobilityFee: number, public readonly mealTickets: number, - public readonly healthInsurance: string, + public readonly healthInsurance: boolean, public readonly paidLeaves: UserLeavesView, public readonly unpaidLeaves: UserLeavesView, public readonly sickLeaves: UserLeavesView, diff --git a/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts b/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts index c51f00a3..6f784c71 100644 --- a/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts +++ b/server/src/Infrastructure/Adapter/FluentTranslatorAdapter.ts @@ -2,7 +2,7 @@ import * as fs from 'fs'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import * as fluent from '@fluent/bundle'; -import { ITranslator } from 'src/Application/ITranslations'; +import { ITranslator } from 'src/Infrastructure/Translations/ITranslator'; @Injectable() export class FluentTranslatorAdapter implements ITranslator { @@ -48,9 +48,9 @@ const _translate = ( ): string | null => { const message = bundle.getMessage(key); - if (message && message.value) { - return bundle.formatPattern(message.value, params); - } else { + if (!message || !message.value) { return key; } + + return bundle.formatPattern(message.value, params); }; diff --git a/server/src/Infrastructure/Common/Table/Table.ts b/server/src/Infrastructure/Common/Table/Table.ts deleted file mode 100644 index 7dbb097f..00000000 --- a/server/src/Infrastructure/Common/Table/Table.ts +++ /dev/null @@ -1,34 +0,0 @@ -type SafeValue = { - safe: any; -}; - -type TransValue = { - trans: { - message: string; - params?: object; - }; -}; - -export type ActionsValue = { - actions: { - view?: { - url: string; - }; - edit?: { - url: string; - }; - delete?: { - url: string; - }; - }; -}; - -export type Row = (string | number | TransValue | SafeValue | ActionsValue)[]; - -export class Table { - constructor(public readonly columns: string[], public readonly rows: Row[]) {} -} - -export class Inline { - constructor(public readonly columns: string[], public readonly row: Row) {} -} diff --git a/server/src/Infrastructure/Common/Templating/filters.ts b/server/src/Infrastructure/Common/Templating/filters.ts deleted file mode 100644 index 553a9373..00000000 --- a/server/src/Infrastructure/Common/Templating/filters.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Environment } from 'nunjucks'; -import { ITranslator } from 'src/Application/ITranslations'; -import { formatHtmlDate, minutesToHours } from '../Utils/dateUtils'; -import { formatFullName } from '../Utils/formatUtils'; -import { ArrayUtils } from '../Utils/ArrayUtils'; - -export const registerFilters = (env: Environment, translator: ITranslator) => { - env.addFilter('trans', (key, params = {}) => - translator.translate(key, params) - ); - env.addFilter('startswith', (value: string | null, other: string) => - value ? value.startsWith(other) : false - ); - env.addFilter('minutesToHours', minutes => minutesToHours(minutes)); - env.addFilter('fullName', obj => formatFullName(obj)); - env.addFilter('htmlDate', value => formatHtmlDate(value)); - env.addFilter('zip', (left, right) => ArrayUtils.zip(left, right)); - env.addFilter('merge', (left, right) => { - const result = {}; - for (const key in left) { - result[key] = left[key]; - } - for (const key in right) { - result[key] = right[key]; - } - return result; - }); -}; diff --git a/server/src/Infrastructure/Common/Templating/index.ts b/server/src/Infrastructure/Common/Templating/index.ts deleted file mode 100644 index ae5ec2b8..00000000 --- a/server/src/Infrastructure/Common/Templating/index.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { NestExpressApplication } from '@nestjs/platform-express'; -import { NextFunction, Request, Response } from 'express'; -import { FileSystemLoader, Environment, TemplateCallback } from 'nunjucks'; -import { RouteNameResolver } from '../ExtendedRouting/RouteNameResolver'; - -type ContextProcessorFn = ( - ctx: Record, - req: Request, - res: Response -) => void; - -export const nunjucks = async ( - app: NestExpressApplication, - { watch } = { watch: false } -) => { - const express = app.getHttpAdapter().getInstance(); - - const loader = new FileSystemLoader(express.get('views'), { watch }); - const env = new Environment(loader); - - const engine = ( - name: string, - ctx: Record, - cb: TemplateCallback - ) => { - env.render(name, { ...ctx, ...ctx._locals.njkCtx }, cb); - }; - - const routeNameResolver = app.get(RouteNameResolver); - - const ctxProcessors: ContextProcessorFn[] = [ - (ctx, req, _res) => { - ctx['req'] = req; - - ctx['path'] = (name: string, params: object = {}) => { - try { - return routeNameResolver.resolve(name, params); - } catch { - return '#'; - } - }; - - ctx['view_name'] = routeNameResolver.getName(req.url); - } - ]; - - app.use((req: Request, res: Response, next: NextFunction): void => { - const ctx = (res.locals.njkCtx = res.locals.njkCtx ?? {}); - ctxProcessors.forEach(fn => fn(ctx, req, res)); - next(); - }); - - return { - env, - engine, - contextProcessor: (fn: ContextProcessorFn) => { - ctxProcessors.push(fn); - } - }; -}; diff --git a/server/src/Infrastructure/Common/Utils/formatUtils.ts b/server/src/Infrastructure/Common/Utils/formatUtils.ts index f16dbb20..26cc178a 100644 --- a/server/src/Infrastructure/Common/Utils/formatUtils.ts +++ b/server/src/Infrastructure/Common/Utils/formatUtils.ts @@ -5,3 +5,10 @@ export const formatFullName = (obj: { firstName: string; lastName: string; }): string => `${capitalize(obj.firstName)} ${capitalize(obj.lastName)}`; + +export const htmlToText = (trustedHtml: string): string => { + // See: https://stackoverflow.com/a/5002161 + return trustedHtml + .replace(//g, '\n') + .replace(/<\/?[^>]+(>|$)/g, ''); +}; diff --git a/server/src/Infrastructure/Customer/Table/CustomerTableFactory.ts b/server/src/Infrastructure/Customer/Table/CustomerTableFactory.ts index dff5604c..05fc6a1e 100644 --- a/server/src/Infrastructure/Customer/Table/CustomerTableFactory.ts +++ b/server/src/Infrastructure/Customer/Table/CustomerTableFactory.ts @@ -1,11 +1,15 @@ import { Injectable } from '@nestjs/common'; import { CustomerView } from 'src/Application/Customer/View/CustomerView'; import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; -import { Row, Table } from 'src/Infrastructure/Common/Table/Table'; +import { RowFactory } from 'src/Infrastructure/Tables/RowFactory'; +import { Row, Table } from 'src/Infrastructure/Tables'; @Injectable() export class CustomerTableFactory { - constructor(private readonly resolver: RouteNameResolver) {} + constructor( + private readonly resolver: RouteNameResolver, + private readonly rowFactory: RowFactory + ) {} public create(customers: CustomerView[]): Table { const columns = [ @@ -14,22 +18,19 @@ export class CustomerTableFactory { 'common-actions' ]; - const rows = customers.map( - (customer): Row => [ - customer.name, - { - safe: `${customer.address.street}
    ${customer.address.zipCode} ${customer.address.city}
    ${customer.address.country}` - }, - { - actions: { - edit: { - url: this.resolver.resolve('crm_customers_edit', { - id: customer.id - }) - } + const rows = customers.map(customer => + this.rowFactory + .createBuilder() + .value(customer.name) + .template('pages/customers/_address.njk', { address: customer.address }) + .actions({ + edit: { + url: this.resolver.resolve('crm_customers_edit', { + id: customer.id + }) } - } - ] + }) + .build() ); return new Table(columns, rows); diff --git a/server/src/Infrastructure/Customer/customer.module.ts b/server/src/Infrastructure/Customer/customer.module.ts index 573c6f50..e05a3665 100644 --- a/server/src/Infrastructure/Customer/customer.module.ts +++ b/server/src/Infrastructure/Customer/customer.module.ts @@ -15,12 +15,14 @@ import { AddCustomerController } from './Controller/AddCustomerController'; import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; import { EditCustomerController } from './Controller/EditCustomerController'; import { CustomerTableFactory } from './Table/CustomerTableFactory'; +import { TablesModule } from '../Tables/tables.module'; @Module({ imports: [ BusModule, TypeOrmModule.forFeature([Customer, Address]), - ExtendedRoutingModule + ExtendedRoutingModule, + TablesModule ], controllers: [ ListCustomersController, diff --git a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts index faae8186..33f36741 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts @@ -12,7 +12,7 @@ import { IQueryBus } from 'src/Application/IQueryBus'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; import { FairCalendarControllerDTO } from '../DTO/FairCalendarControllerDTO'; -import { ITranslator } from 'src/Application/ITranslations'; +import { ITranslator } from 'src/Infrastructure/Translations/ITranslator'; import { minutesToHours } from 'src/Infrastructure/Common/Utils/dateUtils'; import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser'; import { UserView } from 'src/Application/HumanResource/User/View/UserView'; diff --git a/server/src/Infrastructure/HumanResource/Leave/Table/LeaveRequestTableFactory.ts b/server/src/Infrastructure/HumanResource/Leave/Table/LeaveRequestTableFactory.ts index 28176789..9af7bbd2 100644 --- a/server/src/Infrastructure/HumanResource/Leave/Table/LeaveRequestTableFactory.ts +++ b/server/src/Infrastructure/HumanResource/Leave/Table/LeaveRequestTableFactory.ts @@ -2,18 +2,20 @@ import { Injectable } from '@nestjs/common'; import { LeaveRequestDetailView } from 'src/Application/HumanResource/Leave/View/LeaveRequestDetailView'; import { LeaveRequestView } from 'src/Application/HumanResource/Leave/View/LeaveRequestView'; import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; -import { - ActionsValue, - Inline, - Row, - Table -} from 'src/Infrastructure/Common/Table/Table'; +import { Inline, Row, Table } from 'src/Infrastructure/Tables'; import { formatDate } from 'src/Infrastructure/Common/Utils/dateUtils'; import { formatFullName } from 'src/Infrastructure/Common/Utils/formatUtils'; +import { + ActionsOptions, + RowFactory +} from 'src/Infrastructure/Tables/RowFactory'; @Injectable() export class LeaveRequestTableFactory { - constructor(private readonly resolver: RouteNameResolver) {} + constructor( + private readonly resolver: RouteNameResolver, + private rowFactory: RowFactory + ) {} public create(leaveRequests: LeaveRequestView[], userId: string): Table { const columns = [ @@ -26,7 +28,7 @@ export class LeaveRequestTableFactory { const rows = leaveRequests.map( (leaveRequest): Row => { - const actions: ActionsValue['actions'] = { + const actions: ActionsOptions = { view: { url: this.resolver.resolve('people_leave_requests_detail', { id: leaveRequest.id @@ -42,31 +44,17 @@ export class LeaveRequestTableFactory { }; } - return [ - formatFullName(leaveRequest.user), - { - trans: { - message: 'leaves-period-value', - params: { - startDate: leaveRequest.startDate, - endDate: leaveRequest.endDate - } - } - }, - { - trans: { - message: 'leaves-type-value', - params: { type: leaveRequest.type } - } - }, - { - trans: { - message: 'leaves-status-value', - params: { status: leaveRequest.status } - } - }, - { actions } - ]; + return this.rowFactory + .createBuilder() + .value(formatFullName(leaveRequest.user)) + .trans('leaves-period-value', { + startDate: leaveRequest.startDate, + endDate: leaveRequest.endDate + }) + .trans('leaves-type-value', { type: leaveRequest.type }) + .trans('leaves-status-value', { status: leaveRequest.status }) + .actions(actions) + .build(); } ); @@ -83,29 +71,15 @@ export class LeaveRequestTableFactory { 'leaves-comment' ]; - const row: Row = [ - { - trans: { - message: 'leaves-status-value', - params: { status: leaveRequest.status } - } - }, - { - trans: { - message: 'leaves-type-value', - params: { type: leaveRequest.type } - } - }, - formatDate(new Date(leaveRequest.startDate)), - formatDate(new Date(leaveRequest.endDate)), - { - trans: { - message: 'leaves-duration-value', - params: { days: leaveRequest.duration } - } - }, - leaveRequest.comment - ]; + const row = this.rowFactory + .createBuilder() + .trans('leaves-status-value', { status: leaveRequest.status }) + .trans('leaves-type-value', { type: leaveRequest.type }) + .value(formatDate(new Date(leaveRequest.startDate))) + .value(formatDate(new Date(leaveRequest.endDate))) + .trans('leaves-duration-value', { days: leaveRequest.duration }) + .value(leaveRequest.comment) + .build(); return new Inline(columns, row); } diff --git a/server/src/Infrastructure/HumanResource/Leave/Table/LeaveTableFactory.ts b/server/src/Infrastructure/HumanResource/Leave/Table/LeaveTableFactory.ts index 96419722..e8da86ec 100644 --- a/server/src/Infrastructure/HumanResource/Leave/Table/LeaveTableFactory.ts +++ b/server/src/Infrastructure/HumanResource/Leave/Table/LeaveTableFactory.ts @@ -1,16 +1,19 @@ import { Injectable } from '@nestjs/common'; import { LeaveRequestView } from 'src/Application/HumanResource/Leave/View/LeaveRequestView'; import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; -import { - ActionsValue, - Row, - Table -} from 'src/Infrastructure/Common/Table/Table'; +import { Row, Table } from 'src/Infrastructure/Tables'; import { formatFullName } from 'src/Infrastructure/Common/Utils/formatUtils'; +import { + ActionsOptions, + RowFactory +} from 'src/Infrastructure/Tables/RowFactory'; @Injectable() export class LeaveTableFactory { - constructor(private readonly resolver: RouteNameResolver) {} + constructor( + private readonly resolver: RouteNameResolver, + private readonly rowFactory: RowFactory + ) {} public create(leaveRequests: LeaveRequestView[]): Table { const columns = [ @@ -23,7 +26,7 @@ export class LeaveTableFactory { const rows = leaveRequests.map( (leaveRequest): Row => { - const actions: ActionsValue['actions'] = {}; + const actions: ActionsOptions = {}; if (leaveRequest.canCancel) { actions.delete = { @@ -33,35 +36,17 @@ export class LeaveTableFactory { }; } - return [ - formatFullName(leaveRequest.user), - { - trans: { - message: 'leaves-period-value', - params: { - startDate: leaveRequest.startDate, - endDate: leaveRequest.endDate - } - } - }, - { - trans: { - message: 'leaves-duration-value', - params: { - days: leaveRequest.duration - } - } - }, - { - trans: { - message: 'leaves-type-value', - params: { type: leaveRequest.type } - } - }, - { - actions - } - ]; + return this.rowFactory + .createBuilder() + .value(formatFullName(leaveRequest.user)) + .trans('leaves-period-value', { + startDate: leaveRequest.startDate, + endDate: leaveRequest.endDate + }) + .trans('leaves-duration-value', { days: leaveRequest.duration }) + .trans('leaves-type-value', { type: leaveRequest.type }) + .actions(actions) + .build(); } ); diff --git a/server/src/Infrastructure/HumanResource/PayrollElements/Controller/GetPayrollElementsController.ts b/server/src/Infrastructure/HumanResource/PayrollElements/Controller/GetPayrollElementsController.ts new file mode 100644 index 00000000..6ab670e1 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/PayrollElements/Controller/GetPayrollElementsController.ts @@ -0,0 +1,33 @@ +import { Controller, Inject, Get, UseGuards, Render } from '@nestjs/common'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { GetUsersElementsQuery } from 'src/Application/HumanResource/Payslip/Query/GetUsersElementsQuery'; +import { UserElementsView } from 'src/Application/HumanResource/Payslip/View/UserElementsView'; +import { IsAuthenticatedGuard } from '../../User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; +import { TableCsvFactory } from 'src/Infrastructure/Tables/TableCsvFactory'; +import { PayrollElementsTableFactory } from '../Table/PayrollElementsTableFactory'; + +@Controller('app/people/payroll_elements') +@UseGuards(IsAuthenticatedGuard) +export class GetPayrollElementsController { + constructor( + @Inject('IQueryBus') + private readonly queryBus: IQueryBus, + private readonly tableCsvFactory: TableCsvFactory, + private readonly tableFactory: PayrollElementsTableFactory + ) {} + + @Get() + @WithName('people_payroll_elements') + @Render('pages/payroll_elements/index.njk') + public async get() { + const elements: UserElementsView[] = await this.queryBus.execute( + new GetUsersElementsQuery(new Date()) + ); + + const table = this.tableFactory.create(elements); + const csv = this.tableCsvFactory.toCsv(table); + + return { table, csv, date: new Date() }; + } +} diff --git a/server/src/Infrastructure/HumanResource/PayrollElements/Table/PayrollElementsTableFactory.ts b/server/src/Infrastructure/HumanResource/PayrollElements/Table/PayrollElementsTableFactory.ts new file mode 100644 index 00000000..62a9d300 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/PayrollElements/Table/PayrollElementsTableFactory.ts @@ -0,0 +1,70 @@ +import { Injectable } from '@nestjs/common'; +import { UserElementsView } from 'src/Application/HumanResource/Payslip/View/UserElementsView'; +import { Table } from 'src/Infrastructure/Tables'; +import { RowFactory } from 'src/Infrastructure/Tables/RowFactory'; +import { formatFullName } from 'src/Infrastructure/Common/Utils/formatUtils'; + +@Injectable() +export class PayrollElementsTableFactory { + constructor(private readonly cells: RowFactory) {} + + public create(elements: UserElementsView[]): Table { + const columns = [ + 'payroll-elements-user', + 'payroll-elements-contract', + 'payroll-elements-joiningDate', + 'payroll-elements-annualEarnings', + 'payroll-elements-monthlyEarnings', + 'payroll-elements-workingTime', + 'payroll-elements-transportFee', + 'payroll-elements-sustainableMobilityFee', + 'payroll-elements-mealTickets', + 'payroll-elements-healthInsurance', + 'payroll-elements-paidLeaves', + 'payroll-elements-unpaidLeaves', + 'payroll-elements-medicalLeaves', + 'payroll-elements-specialLeaves' + ]; + + const rows = []; + + for (const item of elements) { + const row = this.cells + .createBuilder() + .value(formatFullName(item)) + .trans('payroll-elements-contract-value', { + contract: item.contract, + executivePosition: item.isExecutivePosition ? 'yes' : 'no' + }) + .trans('common-date', { date: new Date(item.joiningDate) }) + .trans('common-money', { value: item.annualEarnings }) + .trans('common-money', { value: item.monthlyEarnings }) + .trans('users-workingTime-value', { + workingTime: item.workingTime + }) + .trans('common-money', { value: item.transportFee }) + .trans('common-money', { + value: item.sustainableMobilityFee + }) + .value(item.mealTickets) + .trans(item.healthInsurance ? 'common-yes' : 'common-no') + .template('pages/payroll_elements/_leaves.njk', { + leaves: item.paidLeaves + }) + .template('pages/payroll_elements/_leaves.njk', { + leaves: item.unpaidLeaves + }) + .template('pages/payroll_elements/_leaves.njk', { + leaves: item.sickLeaves + }) + .template('pages/payroll_elements/_leaves.njk', { + leaves: item.exceptionalLeaves + }) + .build(); + + rows.push(row); + } + + return new Table(columns, rows); + } +} diff --git a/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsCsvAction.ts b/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsCsvAction.ts index bb8c93b4..586fe531 100644 --- a/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsCsvAction.ts +++ b/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsCsvAction.ts @@ -72,7 +72,7 @@ export class GetUsersElementsCsvAction { this.formatNumber(payslip.transportFee), this.formatNumber(payslip.sustainableMobilityFee), payslip.mealTickets, - payslip.healthInsurance === 'yes' ? 'Oui' : 'Non', + payslip.healthInsurance ? 'Oui' : 'Non', this.formatNumber(payslip.paidLeaves.totalDays), this.formatNumber(payslip.unpaidLeaves.totalDays), this.formatNumber(payslip.sickLeaves.totalDays), diff --git a/server/src/Infrastructure/HumanResource/User/Table/UserTableFactory.ts b/server/src/Infrastructure/HumanResource/User/Table/UserTableFactory.ts index ecea3ffc..9329027b 100644 --- a/server/src/Infrastructure/HumanResource/User/Table/UserTableFactory.ts +++ b/server/src/Infrastructure/HumanResource/User/Table/UserTableFactory.ts @@ -1,11 +1,15 @@ import { Injectable } from '@nestjs/common'; import { UserView } from 'src/Application/HumanResource/User/View/UserView'; import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; -import { Row, Table } from 'src/Infrastructure/Common/Table/Table'; +import { RowFactory } from 'src/Infrastructure/Tables/RowFactory'; +import { Table } from 'src/Infrastructure/Tables'; @Injectable() export class UserTableFactory { - constructor(private readonly resolver: RouteNameResolver) {} + constructor( + private readonly resolver: RouteNameResolver, + private readonly rowFactory: RowFactory + ) {} public create(users: UserView[]): Table { const columns = [ @@ -16,22 +20,21 @@ export class UserTableFactory { 'common-actions' ]; - const rows = users.map( - (user): Row => [ - user.firstName, - user.lastName, - user.email, - { trans: { message: 'users-role-value', params: { role: user.role } } }, - { - actions: { - edit: { - url: this.resolver.resolve('people_users_edit', { - id: user.id - }) - } + const rows = users.map(user => + this.rowFactory + .createBuilder() + .value(user.firstName) + .value(user.lastName) + .value(user.email) + .trans('users-role-value', { role: user.role }) + .actions({ + edit: { + url: this.resolver.resolve('people_users_edit', { + id: user.id + }) } - } - ] + }) + .build() ); return new Table(columns, rows); diff --git a/server/src/Infrastructure/HumanResource/humanResource.module.ts b/server/src/Infrastructure/HumanResource/humanResource.module.ts index 092e357a..592a0f1e 100644 --- a/server/src/Infrastructure/HumanResource/humanResource.module.ts +++ b/server/src/Infrastructure/HumanResource/humanResource.module.ts @@ -87,6 +87,10 @@ import { LeaveRequestTableFactory } from './Leave/Table/LeaveRequestTableFactory import { GetLeaveRequestController } from './Leave/Controller/GetLeaveRequestController'; import { ModerateLeaveRequestController } from './Leave/Controller/ModerateLeaveRequestController'; import { DeleteLeaveRequestController } from './Leave/Controller/DeleteLeaveRequestController'; +import { GetPayrollElementsController } from './PayrollElements/Controller/GetPayrollElementsController'; +import { PayrollElementsTableFactory } from './PayrollElements/Table/PayrollElementsTableFactory'; +import { FluentTranslatorAdapter } from '../Adapter/FluentTranslatorAdapter'; +import { TablesModule } from '../Tables/tables.module'; @Module({ imports: [ @@ -106,7 +110,8 @@ import { DeleteLeaveRequestController } from './Leave/Controller/DeleteLeaveRequ UserSavingsRecord, InterestRate ]), - ExtendedRoutingModule + ExtendedRoutingModule, + TablesModule ], controllers: [ LoginController, @@ -122,6 +127,7 @@ import { DeleteLeaveRequestController } from './Leave/Controller/DeleteLeaveRequ GetLeaveRequestController, ModerateLeaveRequestController, DeleteLeaveRequestController, + GetPayrollElementsController, GetLeavesAction, GetLeavesCalendarAction, GetUsersElementsAction, @@ -164,6 +170,7 @@ import { DeleteLeaveRequestController } from './Leave/Controller/DeleteLeaveRequ provide: 'IMealTicketRemovalRepository', useClass: MealTicketRemovalRepository }, + { provide: 'ITranslator', useClass: FluentTranslatorAdapter }, Date, LoginQueryHandler, CreateUserCommandHandler, @@ -199,7 +206,8 @@ import { DeleteLeaveRequestController } from './Leave/Controller/DeleteLeaveRequ IncreaseUserSavingsRecordCommandHandler, UserTableFactory, LeaveTableFactory, - LeaveRequestTableFactory + LeaveRequestTableFactory, + PayrollElementsTableFactory ] }) export class HumanResourceModule {} diff --git a/server/src/Infrastructure/Project/Table/ProjectTableFactory.ts b/server/src/Infrastructure/Project/Table/ProjectTableFactory.ts index 2a0bdd4a..ffb82a64 100644 --- a/server/src/Infrastructure/Project/Table/ProjectTableFactory.ts +++ b/server/src/Infrastructure/Project/Table/ProjectTableFactory.ts @@ -1,11 +1,15 @@ import { Injectable } from '@nestjs/common'; import { ProjectView } from 'src/Application/Project/View/ProjectView'; import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; -import { Row, Table } from 'src/Infrastructure/Common/Table/Table'; +import { RowFactory } from 'src/Infrastructure/Tables/RowFactory'; +import { Table } from 'src/Infrastructure/Tables'; @Injectable() export class ProjectTableFactory { - constructor(private readonly resolver: RouteNameResolver) {} + constructor( + private readonly resolver: RouteNameResolver, + private readonly rowFactory: RowFactory + ) {} public create(projects: ProjectView[]): Table { const columns = [ @@ -14,20 +18,19 @@ export class ProjectTableFactory { 'common-actions' ]; - const rows = projects.map( - (project): Row => [ - project.name, - project.customer.name, - { - actions: { - edit: { - url: this.resolver.resolve('crm_projects_edit', { - id: project.id - }) - } + const rows = projects.map(project => + this.rowFactory + .createBuilder() + .value(project.name) + .value(project.customer.name) + .actions({ + edit: { + url: this.resolver.resolve('crm_projects_edit', { + id: project.id + }) } - } - ] + }) + .build() ); return new Table(columns, rows); diff --git a/server/src/Infrastructure/Project/project.module.ts b/server/src/Infrastructure/Project/project.module.ts index e9f4b142..00b1b369 100644 --- a/server/src/Infrastructure/Project/project.module.ts +++ b/server/src/Infrastructure/Project/project.module.ts @@ -15,12 +15,14 @@ import { AddProjectController } from './Controller/AddProjectController'; import { EditProjectController } from './Controller/EditProjectController'; import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; import { ProjectTableFactory } from './Table/ProjectTableFactory'; +import { TablesModule } from '../Tables/tables.module'; @Module({ imports: [ BusModule, TypeOrmModule.forFeature([Project, Customer]), - ExtendedRoutingModule + ExtendedRoutingModule, + TablesModule ], controllers: [ ListProjectsController, diff --git a/server/src/Infrastructure/Tables/RowFactory.ts b/server/src/Infrastructure/Tables/RowFactory.ts new file mode 100644 index 00000000..89bc3aa6 --- /dev/null +++ b/server/src/Infrastructure/Tables/RowFactory.ts @@ -0,0 +1,135 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { ITranslator } from 'src/Infrastructure/Translations/ITranslator'; +import { ITemplates } from 'src/Infrastructure/Templates/ITemplates'; +import { ICell } from '.'; +import { htmlToText } from '../Common/Utils/formatUtils'; + +class ValueCell implements ICell { + public readonly name = 'scalar'; + + constructor(private readonly value: any) {} + + public renderHtml(): string { + return this.renderText(); + } + + public renderText(): string { + return this.value.toString(); + } +} + +class TemplateCell implements ICell { + public readonly name = 'template'; + + constructor( + private readonly templateName: string, + private readonly context: object, + private readonly templates: ITemplates + ) {} + + public renderHtml(): string { + return this.templates.render(this.templateName, this.context); + } + + public renderText(): string { + return htmlToText(this.renderHtml()); + } +} + +export type ActionsOptions = { + view?: { + url: string; + }; + edit?: { + url: string; + }; + delete?: { + url: string; + }; +}; + +class ActionsCell implements ICell { + public readonly name = 'actions'; + + constructor( + private readonly options: ActionsOptions, + private readonly templates: ITemplates + ) {} + + public renderHtml(): string { + return this.templates.render('tables/cells/actions.njk', { + actions: this.options + }); + } + + public renderText(): string { + throw new Error('Does not render to text'); + } +} + +class TransCell implements ICell { + public readonly name = 'trans'; + + constructor( + public readonly message: string, + public readonly params: object, + private readonly translator: ITranslator + ) {} + + public renderHtml(): string { + return this.renderText(); + } + + public renderText(): string { + return this.translator.translate(this.message, this.params); + } +} + +@Injectable() +export class RowFactory { + constructor( + @Inject('ITranslator') + private readonly translator: ITranslator, + @Inject('ITemplates') + private readonly templates: ITemplates + ) {} + + public createBuilder(): RowBuilder { + return new RowBuilder(this.translator, this.templates); + } +} + +class RowBuilder { + private cells: ICell[]; + + constructor( + private readonly translator: ITranslator, + private readonly templates: ITemplates + ) { + this.cells = []; + } + + public value(value: string | number): RowBuilder { + this.cells.push(new ValueCell(value)); + return this; + } + + public template(name: string, context: object): RowBuilder { + this.cells.push(new TemplateCell(name, context, this.templates)); + return this; + } + + public trans(message: string, params?: object): RowBuilder { + this.cells.push(new TransCell(message, params, this.translator)); + return this; + } + + public actions(options: ActionsOptions): RowBuilder { + this.cells.push(new ActionsCell(options, this.templates)); + return this; + } + + public build(): ICell[] { + return this.cells; + } +} diff --git a/server/src/Infrastructure/Tables/TableCsvFactory.ts b/server/src/Infrastructure/Tables/TableCsvFactory.ts new file mode 100644 index 00000000..7acdabbd --- /dev/null +++ b/server/src/Infrastructure/Tables/TableCsvFactory.ts @@ -0,0 +1,24 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { ITranslator } from '../Translations/ITranslator'; +import { Table } from './'; + +@Injectable() +export class TableCsvFactory { + constructor( + @Inject('ITranslator') + private translator: ITranslator + ) {} + + public toCsv(table: Table): string { + const header = table.columns.map(name => this.translator.translate(name)); + const rows = table.rows.map(row => + row + .map(cell => { + const text = cell.renderText(); + return `"${text}"`; // Use quotes to allow newlines + }) + .join(';') + ); + return [header.join(';'), ...rows].join('\n'); + } +} diff --git a/server/src/Infrastructure/Tables/index.ts b/server/src/Infrastructure/Tables/index.ts new file mode 100644 index 00000000..31cc0c33 --- /dev/null +++ b/server/src/Infrastructure/Tables/index.ts @@ -0,0 +1,15 @@ +export interface ICell { + name: string; + renderHtml(): string; + renderText(): string; +} + +export type Row = ICell[]; + +export class Table { + constructor(public readonly columns: string[], public readonly rows: Row[]) {} +} + +export class Inline { + constructor(public readonly columns: string[], public readonly row: Row) {} +} diff --git a/server/src/Infrastructure/Tables/tables.module.ts b/server/src/Infrastructure/Tables/tables.module.ts new file mode 100644 index 00000000..cdce07ec --- /dev/null +++ b/server/src/Infrastructure/Tables/tables.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; +import { RowFactory } from './RowFactory'; +import { TemplatesModule } from '../Templates/templates.module'; +import { TranslationsModule } from '../Translations/translations.module'; +import { TableCsvFactory } from './TableCsvFactory'; + +const providers = [RowFactory, TableCsvFactory]; + +@Module({ + imports: [TemplatesModule, TranslationsModule], + providers: [...providers], + exports: [...providers] +}) +export class TablesModule {} diff --git a/server/src/Infrastructure/Task/Table/TaskTableFactory.ts b/server/src/Infrastructure/Task/Table/TaskTableFactory.ts index a37f3a66..f1600437 100644 --- a/server/src/Infrastructure/Task/Table/TaskTableFactory.ts +++ b/server/src/Infrastructure/Task/Table/TaskTableFactory.ts @@ -1,26 +1,29 @@ import { Injectable } from '@nestjs/common'; import { TaskView } from 'src/Application/Task/View/TaskView'; import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; -import { Row, Table } from 'src/Infrastructure/Common/Table/Table'; +import { RowFactory } from 'src/Infrastructure/Tables/RowFactory'; +import { Table } from 'src/Infrastructure/Tables'; @Injectable() export class TaskTableFactory { - constructor(private readonly resolver: RouteNameResolver) {} + constructor( + private readonly resolver: RouteNameResolver, + private readonly rowFactory: RowFactory + ) {} public create(tasks: TaskView[]): Table { const columns = ['crm-tasks-name', 'common-actions']; - const rows = tasks.map( - (task): Row => [ - task.name, - { - actions: { - edit: { - url: this.resolver.resolve('crm_tasks_edit', { id: task.id }) - } + const rows = tasks.map(task => + this.rowFactory + .createBuilder() + .value(task.name) + .actions({ + edit: { + url: this.resolver.resolve('crm_tasks_edit', { id: task.id }) } - } - ] + }) + .build() ); return new Table(columns, rows); diff --git a/server/src/Infrastructure/Task/task.module.ts b/server/src/Infrastructure/Task/task.module.ts index 806c4e6a..3eead8a6 100644 --- a/server/src/Infrastructure/Task/task.module.ts +++ b/server/src/Infrastructure/Task/task.module.ts @@ -13,9 +13,15 @@ import { ListTasksController } from './Controller/ListTasksController'; import { AddTaskController } from './Controller/AddTaskController'; import { EditTaskController } from './Controller/EditTaskController'; import { TaskTableFactory } from './Table/TaskTableFactory'; +import { TablesModule } from '../Tables/tables.module'; @Module({ - imports: [BusModule, TypeOrmModule.forFeature([Task]), ExtendedRoutingModule], + imports: [ + BusModule, + TypeOrmModule.forFeature([Task]), + ExtendedRoutingModule, + TablesModule + ], controllers: [ListTasksController, AddTaskController, EditTaskController], providers: [ { provide: 'ITaskRepository', useClass: TaskRepository }, diff --git a/server/src/Infrastructure/Templates/ITemplates.ts b/server/src/Infrastructure/Templates/ITemplates.ts new file mode 100644 index 00000000..b3982e58 --- /dev/null +++ b/server/src/Infrastructure/Templates/ITemplates.ts @@ -0,0 +1,9 @@ +import { NestExpressApplication } from '@nestjs/platform-express'; + +export interface ITemplates { + registerViewEngine(app: NestExpressApplication, assetsRoot: string): void; + + render(name: string, context: object): string; + + markSafe(html: string): any; +} diff --git a/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts b/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts new file mode 100644 index 00000000..5e681b78 --- /dev/null +++ b/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts @@ -0,0 +1,108 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { NextFunction, Response } from 'express'; +import { NestExpressApplication } from '@nestjs/platform-express'; +import { Environment, FileSystemLoader, TemplateCallback } from 'nunjucks'; +import { runtime } from 'nunjucks'; +import { ITemplates } from '../ITemplates'; +import { RouteNameResolver } from '../../Common/ExtendedRouting/RouteNameResolver'; +import { ITranslator } from 'src/Infrastructure/Translations/ITranslator'; +import { formatFullName } from '../../Common/Utils/formatUtils'; +import { + formatDate, + formatHtmlDate, + minutesToHours +} from '../../Common/Utils/dateUtils'; +import { ArrayUtils } from '../../Common/Utils/ArrayUtils'; +import { TablesExtension } from './TablesExtension'; + +@Injectable() +export class NunjucksTemplates implements ITemplates { + private env: Environment; + + constructor( + private readonly resolver: RouteNameResolver, + @Inject('ITranslator') + private readonly translator: ITranslator + ) {} + + private createEnv(viewsDir: string): Environment { + const loader = new FileSystemLoader(viewsDir, { + watch: process.env.NODE_ENV !== 'production' + }); + const env = new Environment(loader); + + env.addFilter('trans', (key, params = {}) => + this.translator.translate(key, params) + ); + env.addFilter('startswith', (value: string | null, other: string) => + value ? value.startsWith(other) : false + ); + env.addFilter('minutesToHours', minutes => minutesToHours(minutes)); + env.addFilter('fullName', obj => formatFullName(obj)); + env.addFilter('date', value => formatDate(value)); + env.addFilter('htmlDate', value => formatHtmlDate(value)); + env.addFilter('htmlYearMonth', value => formatHtmlDate(value).slice(0, 7)); + env.addFilter('zip', (left, right) => ArrayUtils.zip(left, right)); + env.addFilter('merge', (left, right) => { + const result = {}; + for (const key in left) { + result[key] = left[key]; + } + for (const key in right) { + result[key] = right[key]; + } + return result; + }); + + env.addExtension('tables', new TablesExtension(this)); + + return env; + } + + registerViewEngine(app: NestExpressApplication, assetsRoot: string): void { + const express = app.getHttpAdapter().getInstance(); + + this.env = this.createEnv(express.get('views')); + + app.use((req: Request, res: Response, next: NextFunction): void => { + const ctx = (res.locals.njkCtx = res.locals.njkCtx ?? {}); + + ctx['req'] = req; + + ctx['path'] = (name: string, params: object = {}) => { + try { + return this.resolver.resolve(name, params); + } catch { + return '#'; + } + }; + + ctx['view_name'] = this.resolver.getName(req.url); + + ctx['asset'] = (path: string) => `${assetsRoot}/${path}`; + + next(); + }); + + app.engine( + 'njk', + ( + name: string, + ctx: Record, + cb: TemplateCallback + ) => { + this.env.render(name, { ...ctx, ...ctx._locals.njkCtx }, cb); + } + ); + + app.setViewEngine('njk'); + } + + public render(name: string, context: object): string { + return this.env.render(name, context); + } + + public markSafe(html: string): any { + return new runtime.SafeString(html); + } +} diff --git a/server/src/Infrastructure/Templates/NunjucksTemplates/TablesExtension.ts b/server/src/Infrastructure/Templates/NunjucksTemplates/TablesExtension.ts new file mode 100644 index 00000000..49bc4022 --- /dev/null +++ b/server/src/Infrastructure/Templates/NunjucksTemplates/TablesExtension.ts @@ -0,0 +1,46 @@ +import { Extension } from 'nunjucks'; +import { ITemplates } from '../ITemplates'; +import { Inline, Table } from 'src/Infrastructure/Tables'; + +// See: https://mozilla.github.io/nunjucks/api.html#custom-tags +export class TablesExtension implements Extension { + public readonly tags = ['table', 'inlinetable']; + + constructor(private readonly templates: ITemplates) {} + + public parse(parser: any, nodes: any, _lexer: any) { + const tagToken = parser.nextToken(); + + const args = parser.parseSignature(null, true); + parser.advanceAfterBlockEnd(tagToken.value); + + const methodName = + tagToken.value === 'table' ? 'renderTable' : 'renderInlineTable'; + + return new nodes.CallExtension(this, methodName, args, []); + } + + public renderTable( + _context: object, + table: Table, + extraContext: object = {} + ) { + const html = this.templates.render('tables/table.njk', { + table, + ...extraContext + }); + return this.templates.markSafe(html); + } + + public renderInlineTable( + _context: object, + inline: Inline, + extraContext: object = {} + ) { + const html = this.templates.render('tables/inlinetable.njk', { + inline, + ...extraContext + }); + return this.templates.markSafe(html); + } +} diff --git a/server/src/Infrastructure/Templates/templates.module.ts b/server/src/Infrastructure/Templates/templates.module.ts new file mode 100644 index 00000000..0905d785 --- /dev/null +++ b/server/src/Infrastructure/Templates/templates.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; +import { TranslationsModule } from '../Translations/translations.module'; +import { NunjucksTemplates } from './NunjucksTemplates/NunjucksTemplates'; + +const providers = [{ provide: 'ITemplates', useClass: NunjucksTemplates }]; + +@Module({ + imports: [ExtendedRoutingModule, TranslationsModule], + providers: [...providers], + exports: [...providers] +}) +export class TemplatesModule {} diff --git a/server/src/Application/ITranslations.ts b/server/src/Infrastructure/Translations/ITranslator.ts similarity index 100% rename from server/src/Application/ITranslations.ts rename to server/src/Infrastructure/Translations/ITranslator.ts diff --git a/server/src/Infrastructure/Translations/translations.module.ts b/server/src/Infrastructure/Translations/translations.module.ts new file mode 100644 index 00000000..1940b859 --- /dev/null +++ b/server/src/Infrastructure/Translations/translations.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { FluentTranslatorAdapter } from '../Adapter/FluentTranslatorAdapter'; + +const providers = [ + { provide: 'ITranslator', useClass: FluentTranslatorAdapter } +]; + +@Module({ + imports: [ConfigModule], + providers: [...providers], + exports: [...providers] +}) +export class TranslationsModule {} diff --git a/server/src/assets/customElements/blobLink.js b/server/src/assets/customElements/blobLink.js new file mode 100644 index 00000000..a06e4e74 --- /dev/null +++ b/server/src/assets/customElements/blobLink.js @@ -0,0 +1,9 @@ +export default class extends HTMLAnchorElement { + connectedCallback() { + const blob = new Blob([this.dataset.blobContent], { + type: this.dataset.blobMimeType + }); + + this.href = URL.createObjectURL(blob); + } +} diff --git a/server/src/assets/customElements/index.js b/server/src/assets/customElements/index.js index 83758a50..90392cbb 100644 --- a/server/src/assets/customElements/index.js +++ b/server/src/assets/customElements/index.js @@ -1,3 +1,5 @@ import fullcalendar from './fullcalendar'; +import blobLink from './blobLink'; customElements.define('pc-fullcalendar', fullcalendar); +customElements.define('pc-blob-link', blobLink, { extends: 'a' }); diff --git a/server/src/assets/styles/_blocks/link.css b/server/src/assets/styles/_blocks/link.css index 6f233b46..4c99a7e3 100644 --- a/server/src/assets/styles/_blocks/link.css +++ b/server/src/assets/styles/_blocks/link.css @@ -10,3 +10,7 @@ .pc-link-btn[aria-current='page'] { background-color: var(--background-default-hover); } + +a[target='_blank']::after { + content: '↗'; +} diff --git a/server/src/main.ts b/server/src/main.ts index e5e137cf..684616d7 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -8,12 +8,9 @@ import * as session from 'express-session'; import * as connectPgSimple from 'connect-pg-simple'; import { NestExpressApplication } from '@nestjs/platform-express'; import { AppModule } from './app.module'; -import { nunjucks } from './Infrastructure/Common/Templating'; -import { registerFilters } from './Infrastructure/Common/Templating/filters'; +import { ITemplates } from './Infrastructure/Templates/ITemplates'; async function bootstrap() { - const isProd = process.env.NODE_ENV === 'production'; - const app = await NestFactory.create(AppModule); const sessionPgPool = new pg.Pool({ @@ -51,15 +48,8 @@ async function bootstrap() { const viewsDir = path.join(__dirname, '..', 'templates'); app.setBaseViewsDir(viewsDir); - const translator = app.get('ITranslator'); - - const njk = await nunjucks(app, { watch: !isProd }); - registerFilters(njk.env, translator); - njk.contextProcessor((ctx, _req, _res) => { - ctx.asset = (path: string) => `/public/${path}`; - }); - app.engine('njk', njk.engine); - app.setViewEngine('njk'); + const templates: ITemplates = app.get('ITemplates'); + templates.registerViewEngine(app, '/public'); await app.listen(3000, '0.0.0.0'); } diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk index fb6180d0..8bc66a9c 100644 --- a/server/src/templates/components/nav.njk +++ b/server/src/templates/components/nav.njk @@ -56,6 +56,11 @@ {{ 'users-title'|trans }} +
  • + + {{ 'payroll-elements-title'|trans }} + +
  • {{ 'leaves-title'|trans }} diff --git a/server/src/templates/macros/table.njk b/server/src/templates/macros/table.njk deleted file mode 100644 index c97fe01f..00000000 --- a/server/src/templates/macros/table.njk +++ /dev/null @@ -1,84 +0,0 @@ -{% import 'macros/icons.njk' as icons %} -{% from 'macros/attr.njk' import render_attr %} - -{% macro _render_value(value) %} - {% if value.actions %} - - {% if value.actions.view %} - - {{ icons.eye(attr={class: 'pc-icon--action-violet'}) }} - - {% endif %} - {% if value.actions.edit %} - - {{ icons.pencil(attr={class: 'pc-icon--action-violet'}) }} - - {% endif %} - {% if value.actions.delete %} -
    - -
    - {% endif %} - - {% elseif value.safe %} - {{ value.safe|safe }} - {% elseif value.trans %} - {{ value.trans.message|trans(value.trans.params) }} - {% else %} - {{ value }} - {% endif %} -{% endmacro %} - -{% macro render_table(table, attr={}) %} -{% set attr = attr|merge({class: 'pc-table-wrapper ' + attr.class|default('')}) %} -
    - - - - {% for column in table.columns %} - - {% endfor %} - - - - {% for row in table.rows %} - - {% for value in row %} - - {% endfor %} - - {% else %} - - - - {% endfor %} - -
    {{ column|trans }}
    - {{ _render_value(value) }} -
    {{ 'common-table-empty'|trans }}
    -
    -{% endmacro %} - -{% macro render_inline(inline) %} -{% set attr = attr|merge({class: 'pc-table-wrapper ' + attr.class|default('')}) %} -
    - - - {% for column, value in inline.columns|zip(inline.row) %} - - - - - {% else %} - - - - {% endfor %} - -
    {{ column|trans }} - {{ _render_value(value) }} -
    {{ 'common-table-empty'|trans }}
    -
    -{% endmacro %} diff --git a/server/src/templates/pages/customers/_address.njk b/server/src/templates/pages/customers/_address.njk new file mode 100644 index 00000000..efe58d43 --- /dev/null +++ b/server/src/templates/pages/customers/_address.njk @@ -0,0 +1 @@ +{{ address.street }}
    {{ address.zipCode }} {{ address.city }}
    {{ address.country }} diff --git a/server/src/templates/pages/customers/list.njk b/server/src/templates/pages/customers/list.njk index 682f7463..55ff8365 100644 --- a/server/src/templates/pages/customers/list.njk +++ b/server/src/templates/pages/customers/list.njk @@ -1,6 +1,5 @@ {% extends 'layouts/app.njk' %} {% import 'macros/links.njk' as links %} -{% from 'macros/table.njk' import render_table with context %} {% from 'macros/breadcrumb.njk' import breadcrumb %} {% set title = 'crm-customers-title'|trans %} @@ -16,6 +15,6 @@ {{ links.add(path('crm_customers_add'))}}
  • - {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} + {% table table, { attr: {class: 'pc-mt', style: '--mt: calc(4 * var(--w))'} } %}
    {% endblock main %} diff --git a/server/src/templates/pages/leave_requests/detail.njk b/server/src/templates/pages/leave_requests/detail.njk index 2f8e93d8..e887bdae 100644 --- a/server/src/templates/pages/leave_requests/detail.njk +++ b/server/src/templates/pages/leave_requests/detail.njk @@ -1,6 +1,5 @@ {% extends 'layouts/app.njk' %} {% from 'macros/breadcrumb.njk' import breadcrumb %} -{% from 'macros/table.njk' import render_inline %} {% from './_form.njk' import leave_request_moderation_form with context %} {% set title = 'leave-requests-edit-title'|trans({ user: leaveRequest.user|fullName }) %} @@ -11,7 +10,7 @@

    {{ title }}

    - {{ render_inline(inline, attr={class: 'pc-box'}) }} + {% inlinetable inline, { attr: { class: 'pc-box' } } %}
    {% if canModerate %} diff --git a/server/src/templates/pages/leave_requests/list.njk b/server/src/templates/pages/leave_requests/list.njk index 2a379a21..cdb49cc6 100644 --- a/server/src/templates/pages/leave_requests/list.njk +++ b/server/src/templates/pages/leave_requests/list.njk @@ -1,6 +1,5 @@ {% extends 'layouts/app.njk' %} {% import 'macros/links.njk' as links %} -{% from 'macros/table.njk' import render_table with context %} {% from 'macros/breadcrumb.njk' import breadcrumb %} {% set title = 'leave-requests-title'|trans %} @@ -16,6 +15,6 @@ {{ links.add(path('people_leave_requests_add'), text='leave-requests-add-title'|trans) }}
    - {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} + {% table table, { attr: {class: 'pc-mt', style: '--mt: calc(4 * var(--w))'} } %}
    {% endblock main %} diff --git a/server/src/templates/pages/leaves/list.njk b/server/src/templates/pages/leaves/list.njk index 97e4d133..a869078d 100644 --- a/server/src/templates/pages/leaves/list.njk +++ b/server/src/templates/pages/leaves/list.njk @@ -1,7 +1,6 @@ {% extends 'layouts/app.njk' %} {% import 'macros/icons.njk' as icons %} {% import 'macros/links.njk' as links %} -{% from 'macros/table.njk' import render_table with context %} {% from 'macros/breadcrumb.njk' import breadcrumb %} {% set title = 'leaves-title'|trans %} @@ -20,6 +19,6 @@
    - {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} + {% table table, { attr: {class: 'pc-mt', style: '--mt: calc(4 * var(--w))'} } %}
    {% endblock main %} diff --git a/server/src/templates/pages/payroll_elements/_leaves.njk b/server/src/templates/pages/payroll_elements/_leaves.njk new file mode 100644 index 00000000..546c1fca --- /dev/null +++ b/server/src/templates/pages/payroll_elements/_leaves.njk @@ -0,0 +1,7 @@ +{%- if leaves.totalDays > 0 -%} + {{ leaves.totalDays }}
    + {%- for leave in leaves.leaves -%} + {{ leave.startDate|date }} -> {{ leave.endDate|date }} + {%- if not loop.last %}
    {% endif -%} + {%- endfor -%} +{%- endif -%} diff --git a/server/src/templates/pages/payroll_elements/index.njk b/server/src/templates/pages/payroll_elements/index.njk new file mode 100644 index 00000000..d36689d2 --- /dev/null +++ b/server/src/templates/pages/payroll_elements/index.njk @@ -0,0 +1,29 @@ +{% extends 'layouts/app.njk' %} +{% import 'macros/links.njk' as links %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} + +{% set title = 'payroll-elements-title'|trans %} + +{% block main %} +
    + {{ breadcrumb([{ title: 'people-title'|trans }, { title: title }]) }} + + + + {% table table, { attr: { class: 'pc-mt', style: '--mt: calc(4 * var(--w))' } } %} +
    +{% endblock main %} diff --git a/server/src/templates/pages/projects/list.njk b/server/src/templates/pages/projects/list.njk index 6d31b50c..18e8fb6e 100644 --- a/server/src/templates/pages/projects/list.njk +++ b/server/src/templates/pages/projects/list.njk @@ -1,6 +1,5 @@ {% extends 'layouts/app.njk' %} {% import 'macros/links.njk' as links %} -{% from 'macros/table.njk' import render_table with context %} {% from 'macros/breadcrumb.njk' import breadcrumb %} {% block main %} @@ -12,6 +11,6 @@ {{ links.add(path('crm_projects_add'))}}
    - {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} + {% table table, { attr: {class: 'pc-mt', style: '--mt: calc(4 * var(--w))'} } %}
    {% endblock main %} diff --git a/server/src/templates/pages/tasks/list.njk b/server/src/templates/pages/tasks/list.njk index bb6fb175..d72487a9 100644 --- a/server/src/templates/pages/tasks/list.njk +++ b/server/src/templates/pages/tasks/list.njk @@ -1,6 +1,5 @@ {% extends 'layouts/app.njk' %} {% import 'macros/links.njk' as links %} -{% from 'macros/table.njk' import render_table with context %} {% from 'macros/breadcrumb.njk' import breadcrumb %} {% block main %} @@ -12,6 +11,6 @@ {{ links.add(path('crm_tasks_add'))}}
    - {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} + {% table table, { attr: {class: 'pc-mt', style: '--mt: calc(4 * var(--w))'} } %}
    {% endblock main %} diff --git a/server/src/templates/pages/users/list.njk b/server/src/templates/pages/users/list.njk index e0bbaf74..c280eeb2 100644 --- a/server/src/templates/pages/users/list.njk +++ b/server/src/templates/pages/users/list.njk @@ -1,6 +1,5 @@ {% extends 'layouts/app.njk' %} {% import 'macros/links.njk' as links %} -{% from 'macros/table.njk' import render_table with context %} {% from 'macros/breadcrumb.njk' import breadcrumb %} {% set title = 'users-title'|trans %} @@ -16,6 +15,6 @@ {{ links.add(path('people_users_add'))}} - {{ render_table(table, attr={class: 'pc-mt', style: '--mt: calc(4 * var(--w))'}) }} + {% table table, { attr: {class: 'pc-mt', style: '--mt: calc(4 * var(--w))'} } %} {% endblock main %} diff --git a/server/src/templates/tables/cells/actions.njk b/server/src/templates/tables/cells/actions.njk new file mode 100644 index 00000000..bf65abf5 --- /dev/null +++ b/server/src/templates/tables/cells/actions.njk @@ -0,0 +1,23 @@ +{% import 'macros/icons.njk' as icons %} + + + {% if actions.view %} + + {{ icons.eye(attr={class: 'pc-icon--action-violet'}) }} + + {% endif %} + + {% if actions.edit %} + + {{ icons.pencil(attr={class: 'pc-icon--action-violet'}) }} + + {% endif %} + + {% if actions.delete %} +
    + +
    + {% endif %} +
    diff --git a/server/src/templates/tables/inlinetable.njk b/server/src/templates/tables/inlinetable.njk new file mode 100644 index 00000000..91db35e9 --- /dev/null +++ b/server/src/templates/tables/inlinetable.njk @@ -0,0 +1,22 @@ +{% from 'macros/attr.njk' import render_attr %} + +{% set attr = attr|default({})|merge({class: 'pc-table-wrapper ' + attr.class|default('')}) %} + +
    + + + {% for column, cell in inline.columns|zip(inline.row) %} + + + + + {% else %} + + + + {% endfor %} + +
    {{ column|trans }} + {{ cell.renderHtml()|safe }} +
    {{ 'common-table-empty'|trans }}
    +
    diff --git a/server/src/templates/tables/table.njk b/server/src/templates/tables/table.njk new file mode 100644 index 00000000..b7202646 --- /dev/null +++ b/server/src/templates/tables/table.njk @@ -0,0 +1,30 @@ +{% from 'macros/attr.njk' import render_attr %} + +{% set attr = attr|default({})|merge({class: 'pc-table-wrapper ' + attr.class|default('')}) %} + +
    + + + + {% for column in table.columns %} + + {% endfor %} + + + + {% for row in table.rows %} + + {% for cell in row %} + + {% endfor %} + + {% else %} + + + + {% endfor %} + +
    {{ column|trans }}
    + {{ cell.renderHtml()|safe }} +
    {{ 'common-table-empty'|trans }}
    +
    diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index 342af4de..e55b8c1b 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -7,6 +7,8 @@ common-actions = Actions common-yes = Oui common-no = Non common-table-empty = Aucun élément +common-money = {NUMBER($value, style: "currency", currency: "EUR", minimumFractionDigits: 2, maximumFractionDigits: 2)} € +common-date = {DATETIME($date, month: "numeric", year: "numeric", day: "numeric")} site-title = Permacoop @@ -114,6 +116,14 @@ leaves-type-value = {$type -> [illimited] Congé illimité *[other] Autre } +leaves-type-value-plural = {$type -> + [paid] Congés payés + [unpaid] Congés sans solde + [special] Congés exceptionnels + [medical] Congés maladie + [illimited] Congés illimités + *[other] Autre +} leaves-startDate = Du leaves-endDate = Au leaves-period-value = Du {$startDate} au {$endDate} @@ -139,3 +149,27 @@ leave-requests-error-cannot-moderate = Vous ne pouvez pas modérer cette demande leave-requests-moderation = Modération leave-requests-moderation-accept = Accepter la demande de congés leave-requests-moderation-deny = Refuser la demande de congés + +payroll-elements-title = Éléments de paie +payroll-elements-user = Salarié·e / stagiaire +payroll-elements-contract = Contrat +payroll-elements-contract-value = { users-contract-value } {$executivePosition -> + [yes] Cadre + *[no] {""} +} +payroll-elements-joiningDate = Date d'entrée +payroll-elements-annualEarnings = Salaire brut annuel +payroll-elements-monthlyEarnings = Salaire brut mensuel +payroll-elements-workingTime = TC / TP +payroll-elements-executive = Cadre +payroll-elements-transportFee = Transport +payroll-elements-sustainableMobilityFee = Mobilité durable +payroll-elements-mealTickets = Tickets resto +payroll-elements-healthInsurance = Mutuelle +payroll-elements-paidLeaves = Congés payés +payroll-elements-unpaidLeaves = Congés sans solde +payroll-elements-medicalLeaves = Congés maladie +payroll-elements-specialLeaves = Congés exceptionnels +payroll-elements-download = Télécharger +payroll-elements-filename = Fairness - Éléments de paie - {$date}.csv +payroll-elements-wiki = Voir le Wiki From deba484ab2ed517ddf9a27c9677a230642b931c6 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Thu, 28 Sep 2023 00:31:00 +0200 Subject: [PATCH 28/49] Add meal tickets pages, remove obsolete actions --- .../Home/Controller/HomeController.ts | 25 ++++- server/src/Infrastructure/Home/home.module.ts | 5 +- .../Leave/Action/AcceptLeaveRequestAction.ts | 49 --------- .../Leave/Action/CreateLeaveRequestAction.ts | 53 --------- .../Leave/Action/DeleteLeaveRequestAction.ts | 39 ------- .../Leave/Action/GetLeaveRequestAction.ts | 39 ------- .../Leave/Action/GetLeaveRequestsAction.ts | 35 ------ .../Leave/Action/GetLeavesAction.ts | 36 ------ .../Leave/Action/GetLeavesCalendarAction.ts | 42 ------- .../GetPendingLeaveRequestsCountAction.ts | 26 ----- .../Leave/Action/RefuseLeaveRequestAction.ts | 49 --------- .../Leave/Action/UpdateLeaveRequestAction.ts | 59 ---------- .../Action/CreateMealTicketRemovalAction.ts | 46 -------- .../Action/GetAvailableMealTicketsAction.ts | 38 ------- .../AddMealTicketRemovalController.ts | 54 +++++++++ .../Controller/ListMealTicketsController.ts | 41 +++++++ .../MealTicket/DTO/MealTicketRemovalDTO.ts | 9 +- .../Table/MealTicketTableFactory.ts | 30 +++++ .../Payslip/Action/GetUsersElementsAction.ts | 23 ---- .../Action/GetUsersElementsCsvAction.ts | 104 ------------------ .../HumanResource/humanResource.module.ts | 37 ++----- server/src/assets/styles/_defaults.css | 22 +++- server/src/assets/styles/_variables.css | 2 + server/src/templates/components/nav.njk | 5 + server/src/templates/pages/home.njk | 14 +++ .../src/templates/pages/meal_tickets/add.njk | 22 ++++ .../src/templates/pages/meal_tickets/list.njk | 23 ++++ server/src/translations/fr-FR.ftl | 14 +++ 28 files changed, 259 insertions(+), 682 deletions(-) delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/AcceptLeaveRequestAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/CreateLeaveRequestAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/DeleteLeaveRequestAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/GetLeaveRequestAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/GetLeaveRequestsAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/GetLeavesAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/GetLeavesCalendarAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/GetPendingLeaveRequestsCountAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/RefuseLeaveRequestAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Leave/Action/UpdateLeaveRequestAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/MealTicket/Action/CreateMealTicketRemovalAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/MealTicket/Action/GetAvailableMealTicketsAction.ts create mode 100644 server/src/Infrastructure/HumanResource/MealTicket/Controller/AddMealTicketRemovalController.ts create mode 100644 server/src/Infrastructure/HumanResource/MealTicket/Controller/ListMealTicketsController.ts create mode 100644 server/src/Infrastructure/HumanResource/MealTicket/Table/MealTicketTableFactory.ts delete mode 100644 server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsAction.ts delete mode 100644 server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsCsvAction.ts create mode 100644 server/src/templates/pages/meal_tickets/add.njk create mode 100644 server/src/templates/pages/meal_tickets/list.njk diff --git a/server/src/Infrastructure/Home/Controller/HomeController.ts b/server/src/Infrastructure/Home/Controller/HomeController.ts index 60a73402..dd2282bc 100644 --- a/server/src/Infrastructure/Home/Controller/HomeController.ts +++ b/server/src/Infrastructure/Home/Controller/HomeController.ts @@ -1,5 +1,14 @@ -import { Controller, Get, Render, Res, UseGuards } from '@nestjs/common'; +import { + Controller, + Get, + Inject, + Render, + Res, + UseGuards +} from '@nestjs/common'; import { Response } from 'express'; +import { GetPendingLeaveRequestsCountQuery } from 'src/Application/HumanResource/Leave/Query/GetPendingLeaveRequestsCountQuery'; +import { IQueryBus } from 'src/Application/IQueryBus'; import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; @@ -7,13 +16,21 @@ import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Secu @Controller() @UseGuards(IsAuthenticatedGuard) export class HomeController { - constructor(private readonly resolver: RouteNameResolver) {} + constructor( + private readonly resolver: RouteNameResolver, + @Inject('IQueryBus') + private readonly queryBus: IQueryBus + ) {} @Get('app') @WithName('home') @Render('pages/home.njk') - public get() { - return {}; + public async get() { + const pendingLeaves = await this.queryBus.execute( + new GetPendingLeaveRequestsCountQuery() + ); + + return { pendingLeaves }; } @Get() diff --git a/server/src/Infrastructure/Home/home.module.ts b/server/src/Infrastructure/Home/home.module.ts index 517266ad..49ad485c 100644 --- a/server/src/Infrastructure/Home/home.module.ts +++ b/server/src/Infrastructure/Home/home.module.ts @@ -1,9 +1,10 @@ import { Module } from '@nestjs/common'; -import { HomeController } from './Controller/HomeController'; +import { BusModule } from '../bus.module'; import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; +import { HomeController } from './Controller/HomeController'; @Module({ - imports: [ExtendedRoutingModule], + imports: [BusModule, ExtendedRoutingModule], controllers: [HomeController] }) export class HomeModule {} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/AcceptLeaveRequestAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/AcceptLeaveRequestAction.ts deleted file mode 100644 index e9f59ee4..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/AcceptLeaveRequestAction.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { - Controller, - Inject, - BadRequestException, - UseGuards, - Param, - Put, - Body -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UserRole, User } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { LoggedUser } from '../../User/Decorator/LoggedUser'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { ModerationDTO } from '../DTO/ModerationDTO'; -import { AcceptLeaveRequestCommand } from 'src/Application/HumanResource/Leave/Command/AcceptLeaveRequestCommand'; - -@Controller('leave-requests') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class AcceptLeaveRequestAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Put(':id/accept') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Accept leave request' }) - public async index( - @Param() dto: IdDTO, - @Body() moderation: ModerationDTO, - @LoggedUser() user: User - ) { - try { - const id = await this.commandBus.execute( - new AcceptLeaveRequestCommand(user, dto.id, moderation.comment) - ); - - return { id }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/CreateLeaveRequestAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/CreateLeaveRequestAction.ts deleted file mode 100644 index 16ebb42a..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/CreateLeaveRequestAction.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { - Body, - Post, - Controller, - Inject, - BadRequestException, - UseGuards -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { LeaveRequestDTO } from '../DTO/LeaveRequestDTO'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { UserRole, User } from 'src/Domain/HumanResource/User/User.entity'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { CreateLeaveRequestCommand } from 'src/Application/HumanResource/Leave/Command/CreateLeaveRequestCommand'; -import { LoggedUser } from '../../User/Decorator/LoggedUser'; - -@Controller('leave-requests') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class CreateLeaveRequestAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Post() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Create new leave request' }) - public async index(@Body() dto: LeaveRequestDTO, @LoggedUser() user: User) { - const { type, startDate, startsAllDay, endDate, endsAllDay, comment } = dto; - - try { - const id = await this.commandBus.execute( - new CreateLeaveRequestCommand( - user, - type, - startDate, - startsAllDay, - endDate, - endsAllDay, - comment - ) - ); - - return { id }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/DeleteLeaveRequestAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/DeleteLeaveRequestAction.ts deleted file mode 100644 index c8a8a360..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/DeleteLeaveRequestAction.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - Controller, - Inject, - BadRequestException, - UseGuards, - Param, - Delete -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UserRole, User } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { LoggedUser } from '../../User/Decorator/LoggedUser'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { DeleteLeaveRequestCommand } from 'src/Application/HumanResource/Leave/Command/DeleteLeaveRequestCommand'; - -@Controller('leave-requests') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class DeleteLeaveRequestAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Delete(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Delete leave request' }) - public async index(@Param() { id }: IdDTO, @LoggedUser() user: User) { - try { - await this.commandBus.execute(new DeleteLeaveRequestCommand(id, user)); - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/GetLeaveRequestAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/GetLeaveRequestAction.ts deleted file mode 100644 index 1fbdc320..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/GetLeaveRequestAction.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - Controller, - Inject, - UseGuards, - Get, - Param, - NotFoundException -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { GetLeaveRequestByIdQuery } from 'src/Application/HumanResource/Leave/Query/GetLeaveRequestByIdQuery'; -import { LeaveRequestDetailView } from 'src/Application/HumanResource/Leave/View/LeaveRequestDetailView'; - -@Controller('leave-requests') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetLeaveRequestAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get leave request' }) - public async index(@Param() dto: IdDTO): Promise { - try { - return await this.queryBus.execute(new GetLeaveRequestByIdQuery(dto.id)); - } catch (e) { - throw new NotFoundException(e.message); - } - } -} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/GetLeaveRequestsAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/GetLeaveRequestsAction.ts deleted file mode 100644 index c1caee0a..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/GetLeaveRequestsAction.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Controller, Inject, UseGuards, Get, Query } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { User, UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { LeaveRequestView } from 'src/Application/HumanResource/Leave/View/LeaveRequestView'; -import { GetLeaveRequestsQuery } from 'src/Application/HumanResource/Leave/Query/GetLeaveRequestsQuery'; -import { PaginationDTO } from 'src/Infrastructure/Common/DTO/PaginationDTO'; -import { Pagination } from 'src/Application/Common/Pagination'; -import { LoggedUser } from '../../User/Decorator/LoggedUser'; - -@Controller('leave-requests') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetLeaveRequestsAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get all leave requests' }) - public async index( - @Query() pagination: PaginationDTO, - @LoggedUser() user: User - ): Promise> { - return await this.queryBus.execute( - new GetLeaveRequestsQuery(user.getId(), pagination.page) - ); - } -} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/GetLeavesAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/GetLeavesAction.ts deleted file mode 100644 index cfd43425..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/GetLeavesAction.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Controller, Inject, UseGuards, Get, Query } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { User, UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { LeaveRequestView } from 'src/Application/HumanResource/Leave/View/LeaveRequestView'; -import { GetLeaveRequestsQuery } from 'src/Application/HumanResource/Leave/Query/GetLeaveRequestsQuery'; -import { PaginationDTO } from 'src/Infrastructure/Common/DTO/PaginationDTO'; -import { Pagination } from 'src/Application/Common/Pagination'; -import { Status } from 'src/Domain/HumanResource/Leave/LeaveRequest.entity'; -import { LoggedUser } from '../../User/Decorator/LoggedUser'; - -@Controller('leaves') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetLeavesAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get all leaves' }) - public async index( - @Query() pagination: PaginationDTO, - @LoggedUser() user: User - ): Promise> { - return await this.queryBus.execute( - new GetLeaveRequestsQuery(user.getId(), pagination.page, Status.ACCEPTED) - ); - } -} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/GetLeavesCalendarAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/GetLeavesCalendarAction.ts deleted file mode 100644 index 0f95448f..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/GetLeavesCalendarAction.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { - Controller, - Inject, - BadRequestException, - Get, - Res, - UseGuards -} from '@nestjs/common'; -import { Response } from 'express'; -import { ApiTags, ApiOperation, ApiSecurity } from '@nestjs/swagger'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { CalendarTokenGuard } from 'src/Infrastructure/HumanResource/User/Security/CalendarTokenGuard'; -import { GetLeavesCalendarQuery } from 'src/Application/HumanResource/Leave/Query/GetLeavesCalendarQuery'; - -@Controller('leaves') -@ApiTags('Human Resource') -@ApiSecurity('calendar_token') -@UseGuards(CalendarTokenGuard) -export class GetLeavesCalendarAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get('calendar.ics') - @ApiOperation({ summary: 'Export leaves to iCalendar format' }) - public async index(@Res() res: Response): Promise { - res.header('Content-Type', 'text/calendar;charset=UTF-8'); - res.header('Cache-Control', 'no-store, no-cache, must-revalidate'); - res.attachment('leaves.ics'); - - let ics: string; - - try { - ics = await this.queryBus.execute(new GetLeavesCalendarQuery()); - } catch (e) { - throw new BadRequestException(e.message); - } - - return res.send(ics); - } -} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/GetPendingLeaveRequestsCountAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/GetPendingLeaveRequestsCountAction.ts deleted file mode 100644 index c7150a2f..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/GetPendingLeaveRequestsCountAction.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Controller, Inject, UseGuards, Get } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { GetPendingLeaveRequestsCountQuery } from 'src/Application/HumanResource/Leave/Query/GetPendingLeaveRequestsCountQuery'; - -@Controller('leave-requests/pending-count') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetPendingLeaveRequestsCountAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get count of pending leave requests' }) - public async index(): Promise { - return await this.queryBus.execute(new GetPendingLeaveRequestsCountQuery()); - } -} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/RefuseLeaveRequestAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/RefuseLeaveRequestAction.ts deleted file mode 100644 index 6b706919..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/RefuseLeaveRequestAction.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { - Controller, - Inject, - BadRequestException, - UseGuards, - Param, - Put, - Body -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UserRole, User } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { RefuseLeaveRequestCommand } from 'src/Application/HumanResource/Leave/Command/RefuseLeaveRequestCommand'; -import { LoggedUser } from '../../User/Decorator/LoggedUser'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { ModerationDTO } from '../DTO/ModerationDTO'; - -@Controller('leave-requests') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class RefuseLeaveRequestAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Put(':id/refuse') - @Roles(UserRole.COOPERATOR) - @ApiOperation({ summary: 'Refuse leave request' }) - public async index( - @Param() dto: IdDTO, - @Body() moderation: ModerationDTO, - @LoggedUser() user: User - ) { - try { - const id = await this.commandBus.execute( - new RefuseLeaveRequestCommand(user, dto.id, moderation.comment) - ); - - return { id }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/HumanResource/Leave/Action/UpdateLeaveRequestAction.ts b/server/src/Infrastructure/HumanResource/Leave/Action/UpdateLeaveRequestAction.ts deleted file mode 100644 index 1a76cd33..00000000 --- a/server/src/Infrastructure/HumanResource/Leave/Action/UpdateLeaveRequestAction.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { - Body, - Controller, - Inject, - BadRequestException, - UseGuards, - Put, - Param -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { LeaveRequestDTO } from '../DTO/LeaveRequestDTO'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { User, UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { UpdateLeaveRequestCommand } from 'src/Application/HumanResource/Leave/Command/UpdateLeaveRequestCommand'; -import { LoggedUser } from '../../User/Decorator/LoggedUser'; - -@Controller('leave-requests') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class UpdateLeaveRequestAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Put(':id') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Update existing leave request' }) - public async index( - @Param() { id }, - @Body() dto: LeaveRequestDTO, - @LoggedUser() user: User - ) { - const { type, startDate, startsAllDay, endDate, endsAllDay, comment } = dto; - - try { - await this.commandBus.execute( - new UpdateLeaveRequestCommand( - id, - type, - startDate, - startsAllDay, - endDate, - endsAllDay, - user, - comment - ) - ); - - return { id }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/HumanResource/MealTicket/Action/CreateMealTicketRemovalAction.ts b/server/src/Infrastructure/HumanResource/MealTicket/Action/CreateMealTicketRemovalAction.ts deleted file mode 100644 index d9e9b380..00000000 --- a/server/src/Infrastructure/HumanResource/MealTicket/Action/CreateMealTicketRemovalAction.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { - Body, - Post, - Controller, - Inject, - BadRequestException, - UseGuards -} from '@nestjs/common'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { AuthGuard } from '@nestjs/passport'; -import { ICommandBus } from 'src/Application/ICommandBus'; -import { MealTicketRemovalDTO } from '../DTO/MealTicketRemovalDTO'; -import { User, UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { LoggedUser } from '../../User/Decorator/LoggedUser'; -import { CreateMealTicketRemovalCommand } from 'src/Application/HumanResource/MealTicket/Command/CreateMealTicketRemovalCommand'; - -@Controller('meal-tickets') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class CreateMealTicketRemovalAction { - constructor( - @Inject('ICommandBus') - private readonly commandBus: ICommandBus - ) {} - - @Post('removals') - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Create new meal ticket removal' }) - public async index( - @Body() { date, comment }: MealTicketRemovalDTO, - @LoggedUser() user: User - ) { - try { - await this.commandBus.execute( - new CreateMealTicketRemovalCommand(date, user, comment) - ); - - return { date }; - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/HumanResource/MealTicket/Action/GetAvailableMealTicketsAction.ts b/server/src/Infrastructure/HumanResource/MealTicket/Action/GetAvailableMealTicketsAction.ts deleted file mode 100644 index 4a289931..00000000 --- a/server/src/Infrastructure/HumanResource/MealTicket/Action/GetAvailableMealTicketsAction.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { - Get, - Controller, - Inject, - BadRequestException, - UseGuards -} from '@nestjs/common'; -import { IQueryBus } from '@nestjs/cqrs'; -import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { AuthGuard } from '@nestjs/passport'; -import { UserRole } from 'src/Domain/HumanResource/User/User.entity'; -import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; -import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; -import { GetMealTicketsPerMonthQuery } from 'src/Application/HumanResource/MealTicket/Query/GetMealTicketsPerMonthQuery'; - -@Controller('meal-tickets') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer'), RolesGuard) -export class GetAvailableMealTicketsAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get() - @Roles(UserRole.COOPERATOR, UserRole.EMPLOYEE) - @ApiOperation({ summary: 'Get all available meal tickets' }) - public async index() { - try { - return await this.queryBus.execute( - new GetMealTicketsPerMonthQuery(new Date()) - ); - } catch (e) { - throw new BadRequestException(e.message); - } - } -} diff --git a/server/src/Infrastructure/HumanResource/MealTicket/Controller/AddMealTicketRemovalController.ts b/server/src/Infrastructure/HumanResource/MealTicket/Controller/AddMealTicketRemovalController.ts new file mode 100644 index 00000000..8820f414 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/MealTicket/Controller/AddMealTicketRemovalController.ts @@ -0,0 +1,54 @@ +import { + Body, + Post, + Controller, + Inject, + BadRequestException, + UseGuards, + Get, + Render, + Res +} from '@nestjs/common'; +import { Response } from 'express'; +import { ICommandBus } from 'src/Application/ICommandBus'; +import { MealTicketRemovalDTO } from '../DTO/MealTicketRemovalDTO'; +import { User } from 'src/Domain/HumanResource/User/User.entity'; +import { LoggedUser } from '../../User/Decorator/LoggedUser'; +import { CreateMealTicketRemovalCommand } from 'src/Application/HumanResource/MealTicket/Command/CreateMealTicketRemovalCommand'; +import { IsAuthenticatedGuard } from '../../User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; +import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver'; + +@Controller('app/people/meal-tickets/removal/add') +@UseGuards(IsAuthenticatedGuard) +export class AddMealTicketRemovalController { + constructor( + @Inject('ICommandBus') + private readonly commandBus: ICommandBus, + private readonly resolver: RouteNameResolver + ) {} + + @Get() + @WithName('people_meal_tickets_removal_add') + @Render('pages/meal_tickets/add.njk') + public async get() { + return {}; + } + + @Post() + public async post( + @Body() { date }: MealTicketRemovalDTO, + @LoggedUser() user: User, + @Res() res: Response + ) { + try { + await this.commandBus.execute( + new CreateMealTicketRemovalCommand(date, user) + ); + + res.redirect(303, this.resolver.resolve('people_meal_tickets_list')); + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/HumanResource/MealTicket/Controller/ListMealTicketsController.ts b/server/src/Infrastructure/HumanResource/MealTicket/Controller/ListMealTicketsController.ts new file mode 100644 index 00000000..8cfd29d8 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/MealTicket/Controller/ListMealTicketsController.ts @@ -0,0 +1,41 @@ +import { + Controller, + Inject, + UseGuards, + Get, + Render, + BadRequestException +} from '@nestjs/common'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; +import { GetMealTicketsPerMonthQuery } from 'src/Application/HumanResource/MealTicket/Query/GetMealTicketsPerMonthQuery'; +import { MealTicketsPerMonthView } from 'src/Application/HumanResource/MealTicket/Views/MealTicketsPerMonthView'; +import { MealTicketTableFactory } from '../Table/MealTicketTableFactory'; + +@Controller('app/people/meal_tickets') +@UseGuards(IsAuthenticatedGuard) +export class ListMealTicketsController { + constructor( + @Inject('IQueryBus') + private readonly queryBus: IQueryBus, + private readonly tableFactory: MealTicketTableFactory + ) {} + + @Get() + @WithName('people_meal_tickets_list') + @Render('pages/meal_tickets/list.njk') + public async get() { + try { + const mealTickets: MealTicketsPerMonthView[] = await this.queryBus.execute( + new GetMealTicketsPerMonthQuery(new Date()) + ); + + const table = this.tableFactory.create(mealTickets); + + return { table }; + } catch (e) { + throw new BadRequestException(e.message); + } + } +} diff --git a/server/src/Infrastructure/HumanResource/MealTicket/DTO/MealTicketRemovalDTO.ts b/server/src/Infrastructure/HumanResource/MealTicket/DTO/MealTicketRemovalDTO.ts index e5dca7cd..f8e2d2f1 100644 --- a/server/src/Infrastructure/HumanResource/MealTicket/DTO/MealTicketRemovalDTO.ts +++ b/server/src/Infrastructure/HumanResource/MealTicket/DTO/MealTicketRemovalDTO.ts @@ -1,12 +1,7 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsDateString } from 'class-validator'; +import { IsNotEmpty, IsISO8601, IsOptional } from 'class-validator'; export class MealTicketRemovalDTO { - @ApiProperty() @IsNotEmpty() - @IsDateString() + @IsISO8601() public date: string; - - @ApiProperty() - public comment: string; } diff --git a/server/src/Infrastructure/HumanResource/MealTicket/Table/MealTicketTableFactory.ts b/server/src/Infrastructure/HumanResource/MealTicket/Table/MealTicketTableFactory.ts new file mode 100644 index 00000000..b700d389 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/MealTicket/Table/MealTicketTableFactory.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@nestjs/common'; +import { Row, Table } from 'src/Infrastructure/Tables'; +import { formatFullName } from 'src/Infrastructure/Common/Utils/formatUtils'; +import { RowFactory } from 'src/Infrastructure/Tables/RowFactory'; +import { MealTicketsPerMonthView } from 'src/Application/HumanResource/MealTicket/Views/MealTicketsPerMonthView'; + +@Injectable() +export class MealTicketTableFactory { + constructor(private rowFactory: RowFactory) {} + + public create(views: MealTicketsPerMonthView[]): Table { + const columns = [ + 'meal-tickets-user', + 'meal-tickets-num-tickets', + 'meal-tickets-num-exceptions' + ]; + + const rows = views.map( + (view): Row => + this.rowFactory + .createBuilder() + .value(formatFullName(view)) + .value(view.mealTickets) + .value(view.mealTicketRemovals) + .build() + ); + + return new Table(columns, rows); + } +} diff --git a/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsAction.ts b/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsAction.ts deleted file mode 100644 index 8de46837..00000000 --- a/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsAction.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Controller, Inject, Get, UseGuards, Query } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { GetUsersElementsQuery } from 'src/Application/HumanResource/Payslip/Query/GetUsersElementsQuery'; -import { UserElementsView } from 'src/Application/HumanResource/Payslip/View/UserElementsView'; - -@Controller('payslips') -@ApiTags('Human Resource') -@ApiBearerAuth() -@UseGuards(AuthGuard('bearer')) -export class GetUsersElementsAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - @Get() - @ApiOperation({ summary: 'Get elements for payslips' }) - public async index(): Promise { - return await this.queryBus.execute(new GetUsersElementsQuery(new Date())); - } -} diff --git a/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsCsvAction.ts b/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsCsvAction.ts deleted file mode 100644 index 586fe531..00000000 --- a/server/src/Infrastructure/HumanResource/Payslip/Action/GetUsersElementsCsvAction.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Controller, Inject, Get, UseGuards, Res } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { ApiCookieAuth } from '@nestjs/swagger'; -import { IQueryBus } from 'src/Application/IQueryBus'; -import { GetUsersElementsQuery } from 'src/Application/HumanResource/Payslip/Query/GetUsersElementsQuery'; -import { UserElementsView } from 'src/Application/HumanResource/Payslip/View/UserElementsView'; -import { Response } from 'express'; -import { format } from 'date-fns'; -import { LeaveRequestSlotView } from 'src/Application/HumanResource/Leave/View/LeaveRequestSlotView'; - -@Controller('payslips.csv') -@ApiCookieAuth() -@UseGuards(AuthGuard('bearer')) -export class GetUsersElementsCsvAction { - constructor( - @Inject('IQueryBus') - private readonly queryBus: IQueryBus - ) {} - - private formatNumber(value: number): string { - return value.toLocaleString('fr-FR').replace(/\s/g, ''); - } - - @Get() - public async index(@Res() res: Response) { - res.header('Content-Type', 'text/csv'); - - const date = new Date(); - - const month = date.toISOString().substring(0, 7); - - res.attachment(`Fairness - Éléments de paie - ${month}.csv`); - - const payslips: UserElementsView[] = await this.queryBus.execute( - new GetUsersElementsQuery(date) - ); - - const headers = [ - 'NOM', - 'Prénom', - 'Contrat', - "Date d'entrée", - 'Salaire annuel brut', - 'Salaire mensuel brut', - 'Temps de travail', - 'Frais de transport', - 'Forfait mobilité durable', - 'Titres restaurant', - 'Mutuelle', - 'Congés payés', - 'Congés sans solde', - 'Congés maladie', - 'Congés exceptionnels', - 'Notes' - ]; - - const paidLeavesIndex = headers.findIndex( - value => value === 'Congés payés' - ); - - const rows: string[] = []; - - for (const payslip of payslips) { - const row = [ - payslip.lastName.toUpperCase(), - payslip.firstName, - payslip.contract, - payslip.joiningDate, - this.formatNumber(payslip.annualEarnings), - this.formatNumber(Math.round(payslip.monthlyEarnings * 100) / 100), - payslip.workingTime === 'full_time' ? 'Temps plein' : 'Temps partiel', - this.formatNumber(payslip.transportFee), - this.formatNumber(payslip.sustainableMobilityFee), - payslip.mealTickets, - payslip.healthInsurance ? 'Oui' : 'Non', - this.formatNumber(payslip.paidLeaves.totalDays), - this.formatNumber(payslip.unpaidLeaves.totalDays), - this.formatNumber(payslip.sickLeaves.totalDays), - this.formatNumber(payslip.exceptionalLeaves.totalDays), - '' - ]; - - rows.push(row.join(';')); - - for (const leave of payslip.paidLeaves.leaves) { - const leaveRow = row.map((_, index) => - index === paidLeavesIndex ? this.formatLeaves(leave) : '' - ); - rows.push(leaveRow.join(';')); - } - } - - const csv: string = [headers.join(';'), ...rows].join('\n'); - - return res.send(csv); - } - - private formatLeaves(leave: LeaveRequestSlotView): string { - const formatDate = (dateString: string): string => - format(new Date(dateString), 'dd/MM/yyyy'); - - return formatDate(leave.startDate) + ' - ' + formatDate(leave.endDate); - } -} diff --git a/server/src/Infrastructure/HumanResource/humanResource.module.ts b/server/src/Infrastructure/HumanResource/humanResource.module.ts index 592a0f1e..0ac839c6 100644 --- a/server/src/Infrastructure/HumanResource/humanResource.module.ts +++ b/server/src/Infrastructure/HumanResource/humanResource.module.ts @@ -23,18 +23,13 @@ import { LeaveRequest } from 'src/Domain/HumanResource/Leave/LeaveRequest.entity import { LeaveRequestRepository } from './Leave/Repository/LeaveRequestRepository'; import { CreateLeaveRequestCommandHandler } from 'src/Application/HumanResource/Leave/Command/CreateLeaveRequestCommandHandler'; import { DoesLeaveRequestExistForPeriod } from 'src/Domain/HumanResource/Leave/Specification/DoesLeaveRequestExistForPeriod'; -import { CreateLeaveRequestAction } from './Leave/Action/CreateLeaveRequestAction'; import { RefuseLeaveRequestCommandHandler } from 'src/Application/HumanResource/Leave/Command/RefuseLeaveRequestCommandHandler'; -import { RefuseLeaveRequestAction } from './Leave/Action/RefuseLeaveRequestAction'; import { CanLeaveRequestBeModerated } from 'src/Domain/HumanResource/Leave/Specification/CanLeaveRequestBeModerated'; import { AcceptedLeaveRequestEventListener } from 'src/Application/HumanResource/Leave/Event/AcceptedLeaveRequestEventListener'; import { EventRepository } from '../FairCalendar/Repository/EventRepository'; import { Event } from 'src/Domain/FairCalendar/Event.entity'; import { AcceptLeaveRequestCommandHandler } from 'src/Application/HumanResource/Leave/Command/AcceptLeaveRequestCommandHandler'; -import { AcceptLeaveRequestAction } from './Leave/Action/AcceptLeaveRequestAction'; import { GetLeaveRequestsQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetLeaveRequestsQueryHandler'; -import { GetLeaveRequestsAction } from './Leave/Action/GetLeaveRequestsAction'; -import { GetLeaveRequestAction } from './Leave/Action/GetLeaveRequestAction'; import { DoesLeaveExistForPeriod } from 'src/Domain/FairCalendar/Specification/DoesLeaveExistForPeriod'; import { LeaveRequestToLeavesConverter } from 'src/Domain/HumanResource/Leave/Converter/LeaveRequestToLeavesConverter'; import { LeaveRepository } from './Leave/Repository/LeaveRepository'; @@ -44,18 +39,13 @@ import { CooperativeRepository } from '../Settings/Repository/CooperativeReposit import { Cooperative } from 'src/Domain/Settings/Cooperative.entity'; import { UpdateUserCommandHandler } from 'src/Application/HumanResource/User/Command/UpdateUserCommandHandler'; import { GetUserAdministrativeByIdQueryHandler } from 'src/Application/HumanResource/User/Query/GetUserAdministrativeByIdQueryHandler'; -import { GetLeavesAction } from './Leave/Action/GetLeavesAction'; import { MealTicketRemoval } from 'src/Domain/HumanResource/MealTicket/MealTicketRemoval.entity'; import { MealTicketRemovalRepository } from './MealTicket/Repository/MealTicketRemovalRepository'; import { IsMealTicketRemovalAlreadyExist } from 'src/Domain/HumanResource/MealTicket/Specification/IsMealTicketRemovalAlreadyExist'; import { CreateMealTicketRemovalCommandHandler } from 'src/Application/HumanResource/MealTicket/Command/CreateMealTicketRemovalCommandHandler'; -import { CreateMealTicketRemovalAction } from './MealTicket/Action/CreateMealTicketRemovalAction'; import { DoesLeaveRequestBelongToUser } from 'src/Domain/HumanResource/Leave/Specification/DoesLeaveRequestBelongToUser'; import { DeleteLeaveRequestCommandHandler } from 'src/Application/HumanResource/Leave/Command/DeleteLeaveRequestCommandHandler'; -import { DeleteLeaveRequestAction } from './Leave/Action/DeleteLeaveRequestAction'; -import { GetAvailableMealTicketsAction } from './MealTicket/Action/GetAvailableMealTicketsAction'; import { GetMealTicketsPerMonthQueryHandler } from 'src/Application/HumanResource/MealTicket/Query/GetMealTicketsPerMonthQueryHandler'; -import { UpdateLeaveRequestAction } from './Leave/Action/UpdateLeaveRequestAction'; import { UpdateLeaveRequestCommandHandler } from 'src/Application/HumanResource/Leave/Command/UpdateLeaveRequestCommandHandler'; import { UserSavingsRecord } from 'src/Domain/HumanResource/Savings/UserSavingsRecord.entity'; import { UserSavingsRecordRepository } from './Savings/Repository/UserSavingsRecordRepository'; @@ -63,13 +53,9 @@ import { IncreaseUserSavingsRecordCommandHandler } from 'src/Application/HumanRe import { IncreaseUserSavingsRecordAction } from './Savings/Action/IncreaseUserSavingsRecordAction'; import { InterestRate } from 'src/Domain/HumanResource/Savings/InterestRate.entity'; import { InterestRateRepository } from './Savings/Repository/InterestRateRepository'; -import { GetUsersElementsAction } from './Payslip/Action/GetUsersElementsAction'; -import { GetUsersElementsCsvAction } from './Payslip/Action/GetUsersElementsCsvAction'; import { GetUsersElementsQueryHandler } from 'src/Application/HumanResource/Payslip/Query/GetUsersElementsQueryHandler'; import { GetLeavesByMonthQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetLeavesByMonthQueryHandler'; -import { GetLeavesCalendarAction } from './Leave/Action/GetLeavesCalendarAction'; import { GetLeavesCalendarQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetLeavesCalendarQueryHandler'; -import { GetPendingLeaveRequestsCountAction } from './Leave/Action/GetPendingLeaveRequestsCountAction'; import { GetPendingLeaveRequestsCountQueryHandler } from 'src/Application/HumanResource/Leave/Query/GetPendingLeaveRequestsCountQueryHandler'; import { LogoutController } from './User/Controller/LogoutController'; import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module'; @@ -91,6 +77,9 @@ import { GetPayrollElementsController } from './PayrollElements/Controller/GetPa import { PayrollElementsTableFactory } from './PayrollElements/Table/PayrollElementsTableFactory'; import { FluentTranslatorAdapter } from '../Adapter/FluentTranslatorAdapter'; import { TablesModule } from '../Tables/tables.module'; +import { ListMealTicketsController } from './MealTicket/Controller/ListMealTicketsController'; +import { MealTicketTableFactory } from './MealTicket/Table/MealTicketTableFactory'; +import { AddMealTicketRemovalController } from './MealTicket/Controller/AddMealTicketRemovalController'; @Module({ imports: [ @@ -128,21 +117,8 @@ import { TablesModule } from '../Tables/tables.module'; ModerateLeaveRequestController, DeleteLeaveRequestController, GetPayrollElementsController, - GetLeavesAction, - GetLeavesCalendarAction, - GetUsersElementsAction, - GetUsersElementsCsvAction, - GetLeaveRequestsAction, - GetPendingLeaveRequestsCountAction, - GetLeaveRequestAction, - CreateLeaveRequestAction, - RefuseLeaveRequestAction, - AcceptLeaveRequestAction, - CreateMealTicketRemovalAction, - GetAvailableMealTicketsAction, - DeleteLeaveRequestAction, - CreateMealTicketRemovalAction, - UpdateLeaveRequestAction, + ListMealTicketsController, + AddMealTicketRemovalController, IncreaseUserSavingsRecordAction ], providers: [ @@ -207,7 +183,8 @@ import { TablesModule } from '../Tables/tables.module'; UserTableFactory, LeaveTableFactory, LeaveRequestTableFactory, - PayrollElementsTableFactory + PayrollElementsTableFactory, + MealTicketTableFactory ] }) export class HumanResourceModule {} diff --git a/server/src/assets/styles/_defaults.css b/server/src/assets/styles/_defaults.css index 5e736fba..89adfd83 100644 --- a/server/src/assets/styles/_defaults.css +++ b/server/src/assets/styles/_defaults.css @@ -5,10 +5,30 @@ body { font-size: var(--font-size-default); } +h1, +h2, +h3, +h4, +h5, +h6 { + margin: var(--title-spacing); +} + h1 { - margin-bottom: calc(3 * var(--w)); + font-size: 2.25rem; + line-height: 2.5rem; +} + +h2 { + font-size: 1.75rem; + line-height: 2rem; } main { overflow-y: auto; } + +p { + font-size: 1rem; + margin: var(--text-spacing); +} diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/_variables.css index a4a6be7f..e62da8e3 100644 --- a/server/src/assets/styles/_variables.css +++ b/server/src/assets/styles/_variables.css @@ -2,6 +2,8 @@ /* Spacing */ --v: 0.25rem; --w: 0.5rem; + --text-spacing: 0 0 calc(3 * var(--w)) 0; + --title-spacing: 0 0 calc(3 * var(--w)) 0; /* Fonts */ --font-default: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk index 8bc66a9c..ed65393b 100644 --- a/server/src/templates/components/nav.njk +++ b/server/src/templates/components/nav.njk @@ -61,6 +61,11 @@ {{ 'payroll-elements-title'|trans }} +
  • + + {{ 'meal-tickets-title'|trans }} + +
  • {{ 'leaves-title'|trans }} diff --git a/server/src/templates/pages/home.njk b/server/src/templates/pages/home.njk index d4203a5f..89f75c35 100644 --- a/server/src/templates/pages/home.njk +++ b/server/src/templates/pages/home.njk @@ -3,5 +3,19 @@ {% block main %} {% endblock main %} diff --git a/server/src/templates/pages/meal_tickets/add.njk b/server/src/templates/pages/meal_tickets/add.njk new file mode 100644 index 00000000..fb12394e --- /dev/null +++ b/server/src/templates/pages/meal_tickets/add.njk @@ -0,0 +1,22 @@ +{% extends 'layouts/app.njk' %} +{% import 'macros/buttons.njk' as buttons %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} + +{% set title = 'meal-tickets-add-removal-title'|trans %} + +{% block main %} +
    + {{ breadcrumb([{ title: 'people-title'|trans }, { title: 'meal-tickets-title', href: path('people_meal_tickets_list') }, { title: title }]) }} + +

    {{ title }}

    + +
    +
    + + +
    + + {{ buttons.save() }} +
    +
    +{% endblock main %} diff --git a/server/src/templates/pages/meal_tickets/list.njk b/server/src/templates/pages/meal_tickets/list.njk new file mode 100644 index 00000000..1c66278f --- /dev/null +++ b/server/src/templates/pages/meal_tickets/list.njk @@ -0,0 +1,23 @@ +{% extends 'layouts/app.njk' %} +{% import 'macros/icons.njk' as icons %} +{% from 'macros/breadcrumb.njk' import breadcrumb %} + +{% set title = 'meal-tickets-title'|trans %} + +{% block main %} +
    + {{ breadcrumb([{ title: 'people-title'|trans }, { title: title }]) }} + + + + {% table table, { attr: {class: 'pc-mt', style: '--mt: calc(4 * var(--w))'} } %} +
    +{% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index e55b8c1b..1d59e928 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -17,6 +17,13 @@ header-dropdown = Voir plus d'actions header-logout = Se déconnecter home-title = Bonjour, {$user} ! +home-pending-leaves-title = Demandes de congés +home-pending-leaves = {$leaves -> + [0] Aucune demande de congés + [1] 1 demande de congés + *[other] {$leaves} demandes de congés +} en attente de validation +home-pending-leaves-see-all = Voir les demandes de congés dashboard-title = Tableau de bord @@ -173,3 +180,10 @@ payroll-elements-specialLeaves = Congés exceptionnels payroll-elements-download = Télécharger payroll-elements-filename = Fairness - Éléments de paie - {$date}.csv payroll-elements-wiki = Voir le Wiki + +meal-tickets-title = Tickets resto +meal-tickets-user = Coopérateur·ice - Salarié·e +meal-tickets-num-tickets = Nb tickets restaurant +meal-tickets-num-exceptions = Nb exceptions +meal-tickets-add-removal-title = Ajouter une exception +meal-tickets-removal-date = Je ne souhaite pas recevoir de ticket restaurant pour la date du : From 823a1adb5030b1892d26a16c2e46c46b2d8ea989 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Thu, 28 Sep 2023 01:11:18 +0200 Subject: [PATCH 29/49] Bring back calendar ICS export, add calendar url widget --- .../ExportLeavesCalendarController.ts | 40 +++++++++++++++++++ .../Leave/Controller/ListLeavesController.ts | 4 +- .../HumanResource/humanResource.module.ts | 2 + .../NunjucksTemplates/NunjucksTemplates.ts | 15 ++++++- server/src/assets/customElements/clipboard.js | 23 +++++++++++ server/src/assets/customElements/index.js | 2 + server/src/assets/styles/_blocks/button.css | 6 +++ .../src/assets/styles/_blocks/input-group.css | 1 + server/src/assets/styles/_variables.css | 2 + server/src/templates/macros/icons.njk | 4 ++ server/src/templates/pages/leaves/list.njk | 12 ++++++ server/src/translations/fr-FR.ftl | 3 ++ 12 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 server/src/Infrastructure/HumanResource/Leave/Controller/ExportLeavesCalendarController.ts create mode 100644 server/src/assets/customElements/clipboard.js diff --git a/server/src/Infrastructure/HumanResource/Leave/Controller/ExportLeavesCalendarController.ts b/server/src/Infrastructure/HumanResource/Leave/Controller/ExportLeavesCalendarController.ts new file mode 100644 index 00000000..552ea639 --- /dev/null +++ b/server/src/Infrastructure/HumanResource/Leave/Controller/ExportLeavesCalendarController.ts @@ -0,0 +1,40 @@ +import { + Controller, + Inject, + BadRequestException, + Get, + Res, + UseGuards +} from '@nestjs/common'; +import { Response } from 'express'; +import { IQueryBus } from 'src/Application/IQueryBus'; +import { CalendarTokenGuard } from 'src/Infrastructure/HumanResource/User/Security/CalendarTokenGuard'; +import { GetLeavesCalendarQuery } from 'src/Application/HumanResource/Leave/Query/GetLeavesCalendarQuery'; +import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName'; + +@Controller('api/leaves/calendar.ics') +@UseGuards(CalendarTokenGuard) +export class ExportLeavesCalendarController { + constructor( + @Inject('IQueryBus') + private readonly queryBus: IQueryBus + ) {} + + @Get() + @WithName('people_leaves_calendar') + public async get(@Res() res: Response): Promise { + res.header('Content-Type', 'text/calendar;charset=UTF-8'); + res.header('Cache-Control', 'no-store, no-cache, must-revalidate'); + res.attachment('leaves.ics'); + + let ics: string; + + try { + ics = await this.queryBus.execute(new GetLeavesCalendarQuery()); + } catch (e) { + throw new BadRequestException(e.message); + } + + return res.send(ics); + } +} diff --git a/server/src/Infrastructure/HumanResource/Leave/Controller/ListLeavesController.ts b/server/src/Infrastructure/HumanResource/Leave/Controller/ListLeavesController.ts index 6895a75c..57a8195b 100644 --- a/server/src/Infrastructure/HumanResource/Leave/Controller/ListLeavesController.ts +++ b/server/src/Infrastructure/HumanResource/Leave/Controller/ListLeavesController.ts @@ -40,6 +40,8 @@ export class ListLeavesController { const table = this.tableFactory.create(leaves.items); - return { table }; + const calendarToken = process.env.CALENDAR_TOKEN; + + return { table, calendarToken }; } } diff --git a/server/src/Infrastructure/HumanResource/humanResource.module.ts b/server/src/Infrastructure/HumanResource/humanResource.module.ts index 0ac839c6..6b58667e 100644 --- a/server/src/Infrastructure/HumanResource/humanResource.module.ts +++ b/server/src/Infrastructure/HumanResource/humanResource.module.ts @@ -80,6 +80,7 @@ import { TablesModule } from '../Tables/tables.module'; import { ListMealTicketsController } from './MealTicket/Controller/ListMealTicketsController'; import { MealTicketTableFactory } from './MealTicket/Table/MealTicketTableFactory'; import { AddMealTicketRemovalController } from './MealTicket/Controller/AddMealTicketRemovalController'; +import { ExportLeavesCalendarController } from './Leave/Controller/ExportLeavesCalendarController'; @Module({ imports: [ @@ -116,6 +117,7 @@ import { AddMealTicketRemovalController } from './MealTicket/Controller/AddMealT GetLeaveRequestController, ModerateLeaveRequestController, DeleteLeaveRequestController, + ExportLeavesCalendarController, GetPayrollElementsController, ListMealTicketsController, AddMealTicketRemovalController, diff --git a/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts b/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts index 5e681b78..5c243a95 100644 --- a/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts +++ b/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import { NextFunction, Response } from 'express'; +import { NextFunction, Request, Response } from 'express'; import { NestExpressApplication } from '@nestjs/platform-express'; import { Environment, FileSystemLoader, TemplateCallback } from 'nunjucks'; import { runtime } from 'nunjucks'; @@ -77,6 +77,19 @@ export class NunjucksTemplates implements ITemplates { } }; + ctx['url'] = (name: string, params: object = {}) => { + try { + const path = this.resolver.resolve(name, params); + const proto = req.protocol; + const origin = req.get('Host'); + const baseUrl = `${proto}://${origin}`; + const url = new URL(path, baseUrl); + return url.toString(); + } catch { + return '#'; + } + }; + ctx['view_name'] = this.resolver.getName(req.url); ctx['asset'] = (path: string) => `${assetsRoot}/${path}`; diff --git a/server/src/assets/customElements/clipboard.js b/server/src/assets/customElements/clipboard.js new file mode 100644 index 00000000..bc9387c0 --- /dev/null +++ b/server/src/assets/customElements/clipboard.js @@ -0,0 +1,23 @@ +export default class extends HTMLButtonElement { + connectedCallback() { + /** @type {HTMLInputElement|null} */ + const sourceEl = document.querySelector(this.dataset.clipboardSource); + + if (!sourceEl) { + throw new Error('Source element not found'); + } + + this.sourceEl = sourceEl; + + this.addEventListener('click', this.#handleClick); + } + + #handleClick = () => { + this.sourceEl.select(); // Visual feedback + navigator.clipboard.writeText(this.sourceEl.value); + }; + + disconnectedCallback() { + this.removeEventListener('click', this.#handleClick); + } +} diff --git a/server/src/assets/customElements/index.js b/server/src/assets/customElements/index.js index 90392cbb..5511dc8d 100644 --- a/server/src/assets/customElements/index.js +++ b/server/src/assets/customElements/index.js @@ -1,5 +1,7 @@ import fullcalendar from './fullcalendar'; import blobLink from './blobLink'; +import clipboard from './clipboard'; customElements.define('pc-fullcalendar', fullcalendar); customElements.define('pc-blob-link', blobLink, { extends: 'a' }); +customElements.define('pc-clipboard', clipboard, { extends: 'button' }); diff --git a/server/src/assets/styles/_blocks/button.css b/server/src/assets/styles/_blocks/button.css index c32da737..a2e95a58 100644 --- a/server/src/assets/styles/_blocks/button.css +++ b/server/src/assets/styles/_blocks/button.css @@ -17,3 +17,9 @@ background-color: var(--background-error); color: var(--text-on-error); } + +.pc-btn--muted { + --hover-tint: var(--background-muted-hover); + background-color: var(--background-muted); + color: var(--text-on-muted); +} diff --git a/server/src/assets/styles/_blocks/input-group.css b/server/src/assets/styles/_blocks/input-group.css index fb62c98e..5e56d309 100644 --- a/server/src/assets/styles/_blocks/input-group.css +++ b/server/src/assets/styles/_blocks/input-group.css @@ -2,6 +2,7 @@ margin-bottom: calc(2 * var(--w)); } +.pc-input, .pc-input-group > input { appearance: none; display: block; diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/_variables.css index e62da8e3..e0af9b09 100644 --- a/server/src/assets/styles/_variables.css +++ b/server/src/assets/styles/_variables.css @@ -18,12 +18,14 @@ --background-default-hover: #f1f2f3; --background-alt-grey: #f9fafb; --background-muted: #f0f0f0; + --background-muted-hover: #dadada; --background-action-violet: #6c2bd9; --background-action-violet-hover: #52289b; --background-error: #dd1d1d; --background-error-hover: #b92020; --text-default: #282828; --text-muted: #6e6e6e; + --text-on-muted: #282828; --text-on-background-action-violet: #ffffff; --text-action-violet: #6c2bd9; --text-error: #ff0000; diff --git a/server/src/templates/macros/icons.njk b/server/src/templates/macros/icons.njk index 84d97eae..06b5e551 100644 --- a/server/src/templates/macros/icons.njk +++ b/server/src/templates/macros/icons.njk @@ -63,3 +63,7 @@ {% macro eye(attr=null) %} {{ _icon(attr, paths=["M15 12a3 3 0 11-6 0 3 3 0 016 0z", "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"]) }} {% endmacro %} + +{% macro clipboard(attr=null) %} + {{ _icon(attr, paths=["M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5A3.375 3.375 0 006.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0015 2.25h-1.5a2.251 2.251 0 00-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 00-9-9z"]) }} +{% endmacro %} diff --git a/server/src/templates/pages/leaves/list.njk b/server/src/templates/pages/leaves/list.njk index a869078d..193c0cd9 100644 --- a/server/src/templates/pages/leaves/list.njk +++ b/server/src/templates/pages/leaves/list.njk @@ -19,6 +19,18 @@ +
    + +
    + +
    +
    + +
    +
    + {% table table, { attr: {class: 'pc-mt', style: '--mt: calc(4 * var(--w))'} } %} {% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index 1d59e928..81827832 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -156,6 +156,7 @@ leave-requests-error-cannot-moderate = Vous ne pouvez pas modérer cette demande leave-requests-moderation = Modération leave-requests-moderation-accept = Accepter la demande de congés leave-requests-moderation-deny = Refuser la demande de congés +leaves-calendar-url-title = Lien d'abonnement au calendrier payroll-elements-title = Éléments de paie payroll-elements-user = Salarié·e / stagiaire @@ -187,3 +188,5 @@ meal-tickets-num-tickets = Nb tickets restaurant meal-tickets-num-exceptions = Nb exceptions meal-tickets-add-removal-title = Ajouter une exception meal-tickets-removal-date = Je ne souhaite pas recevoir de ticket restaurant pour la date du : + +clipboard-copy = Copier dans le presse papier From 079b8fee75df55352c80f6d52384ab68f224a8ff Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Thu, 28 Sep 2023 09:04:06 +0200 Subject: [PATCH 30/49] Add calendar overview --- ...view.ts => FairCalendarOverviewFactory.ts} | 4 +- .../Controller/FairCalendarController.ts | 12 +++++- .../Table/FairCalendarOverviewTableFactory.ts | 37 +++++++++++++++++++ .../FairCalendar/faircalendar.module.ts | 12 ++++-- server/src/assets/styles/_blocks/badge.css | 14 +++++-- server/src/assets/styles/_blocks/table.css | 13 ++++++- .../src/assets/styles/_utilities/border.css | 4 ++ server/src/assets/styles/_utilities/index.css | 1 + server/src/assets/styles/_utilities/text.css | 3 ++ server/src/assets/styles/_variables.css | 12 +++--- .../pages/faircalendar/_overview_badge.njk | 3 ++ .../templates/pages/faircalendar/index.njk | 2 + server/src/translations/fr-FR.ftl | 5 +++ 13 files changed, 104 insertions(+), 18 deletions(-) rename server/src/Domain/FairCalendar/{GetFairCalendarOverview.ts => FairCalendarOverviewFactory.ts} (90%) create mode 100644 server/src/Infrastructure/FairCalendar/Table/FairCalendarOverviewTableFactory.ts create mode 100644 server/src/assets/styles/_utilities/text.css create mode 100644 server/src/templates/pages/faircalendar/_overview_badge.njk diff --git a/server/src/Domain/FairCalendar/GetFairCalendarOverview.ts b/server/src/Domain/FairCalendar/FairCalendarOverviewFactory.ts similarity index 90% rename from server/src/Domain/FairCalendar/GetFairCalendarOverview.ts rename to server/src/Domain/FairCalendar/FairCalendarOverviewFactory.ts index c520d553..672c0855 100644 --- a/server/src/Domain/FairCalendar/GetFairCalendarOverview.ts +++ b/server/src/Domain/FairCalendar/FairCalendarOverviewFactory.ts @@ -4,13 +4,13 @@ import { CooperativeNotFoundException } from '../Settings/Repository/Cooperative import { ICooperativeRepository } from '../Settings/Repository/ICooperativeRepository'; import { ICalendarOverview } from './ICalendarOverview'; -export class GetFairCalendarOverview { +export class FairCalendarOverviewFactory { constructor( @Inject('ICooperativeRepository') private readonly cooperativeRepository: ICooperativeRepository ) {} - public async index(items: FairCalendarView[]): Promise { + public async create(items: FairCalendarView[]): Promise { const cooperative = await this.cooperativeRepository.find(); if (!cooperative) { throw new CooperativeNotFoundException(); diff --git a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts index 33f36741..8d2e6f09 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts @@ -18,6 +18,8 @@ import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/Logg import { UserView } from 'src/Application/HumanResource/User/View/UserView'; import { GetUsersQuery } from 'src/Application/HumanResource/User/Query/GetUsersQuery'; import { FairCalendarView } from 'src/Application/FairCalendar/View/FairCalendarView'; +import { FairCalendarOverviewFactory } from 'src/Domain/FairCalendar/FairCalendarOverviewFactory'; +import { FairCalendarOverviewTableFactory } from '../Table/FairCalendarOverviewTableFactory'; @Controller('app/faircalendar') @UseGuards(IsAuthenticatedGuard) @@ -26,7 +28,9 @@ export class FairCalendarController { @Inject('IQueryBus') private readonly queryBus: IQueryBus, @Inject('ITranslator') - private readonly translator: ITranslator + private readonly translator: ITranslator, + private overviewFactory: FairCalendarOverviewFactory, + private overviewTableFactory: FairCalendarOverviewTableFactory ) {} @Get() @@ -45,6 +49,9 @@ export class FairCalendarController { new GetMonthlyFairCalendarQuery(date, userId) ); + const overview = await this.overviewFactory.create(events); + const overviewTable = this.overviewTableFactory.create(overview); + const fullCalendarEvents = events.map(event => { let title = `${minutesToHours(event.time)} - `; @@ -82,7 +89,8 @@ export class FairCalendarController { return { users, fullCalendarEvents, - date + date, + overviewTable }; } } diff --git a/server/src/Infrastructure/FairCalendar/Table/FairCalendarOverviewTableFactory.ts b/server/src/Infrastructure/FairCalendar/Table/FairCalendarOverviewTableFactory.ts new file mode 100644 index 00000000..679e1f7f --- /dev/null +++ b/server/src/Infrastructure/FairCalendar/Table/FairCalendarOverviewTableFactory.ts @@ -0,0 +1,37 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { RowFactory } from 'src/Infrastructure/Tables/RowFactory'; +import { Table } from 'src/Infrastructure/Tables'; +import { ICalendarOverview } from 'src/Domain/FairCalendar/ICalendarOverview'; +import { EventType } from 'src/Domain/FairCalendar/Event.entity'; +import { ITranslator } from 'src/Infrastructure/Translations/ITranslator'; + +@Injectable() +export class FairCalendarOverviewTableFactory { + constructor( + private readonly rowFactory: RowFactory, + @Inject('ITranslator') + private readonly translator: ITranslator + ) {} + + public create(overview: ICalendarOverview): Table { + const columns = []; + const rowBuilder = this.rowFactory.createBuilder(); + + const eventTypes: string[] = Object.values(EventType); + eventTypes.splice(-1, 0, 'leave'); + + for (const type of eventTypes) { + columns.push( + this.translator.translate('faircalendar-type-option', { type }) + ); + rowBuilder.template('pages/faircalendar/_overview_badge.njk', { + type, + days: overview[type] + }); + } + + const row = rowBuilder.build(); + + return new Table(columns, [row]); + } +} diff --git a/server/src/Infrastructure/FairCalendar/faircalendar.module.ts b/server/src/Infrastructure/FairCalendar/faircalendar.module.ts index cd8a3d13..593c0af6 100644 --- a/server/src/Infrastructure/FairCalendar/faircalendar.module.ts +++ b/server/src/Infrastructure/FairCalendar/faircalendar.module.ts @@ -12,7 +12,6 @@ import { Task } from 'src/Domain/Task/Task.entity'; import { Project } from 'src/Domain/Project/Project.entity'; import { ProjectRepository } from '../Project/Repository/ProjectRepository'; import { DateUtilsAdapter } from '../Adapter/DateUtilsAdapter'; -import { GetFairCalendarOverview } from 'src/Domain/FairCalendar/GetFairCalendarOverview'; import { GetMonthlyFairCalendarQueryHandler } from 'src/Application/FairCalendar/Query/GetMonthlyFairCalendarQueryHandler'; import { GetEventByIdQueryHandler } from 'src/Application/FairCalendar/Query/GetEventByIdQueryHandler'; import { DoesEventBelongToUser } from 'src/Domain/FairCalendar/Specification/DoesEventBelongToUser'; @@ -26,12 +25,18 @@ import { FairCalendarController } from './Controller/FairCalendarController'; import { AddEventController } from './Controller/AddEventController'; import { EditEventController } from './Controller/EditEventController'; import { DeleteEventController } from './Controller/DeleteEventController'; +import { FairCalendarOverviewFactory } from 'src/Domain/FairCalendar/FairCalendarOverviewFactory'; +import { FairCalendarOverviewTableFactory } from './Table/FairCalendarOverviewTableFactory'; +import { TranslationsModule } from '../Translations/translations.module'; +import { TablesModule } from '../Tables/tables.module'; @Module({ imports: [ BusModule, ConfigModule, - TypeOrmModule.forFeature([Project, Event, Task, Leave, Cooperative]) + TypeOrmModule.forFeature([Project, Event, Task, Leave, Cooperative]), + TranslationsModule, + TablesModule ], controllers: [ FairCalendarController, @@ -55,7 +60,8 @@ import { DeleteEventController } from './Controller/DeleteEventController'; UpdateEventCommandHandler, GetEventByIdQueryHandler, DoesEventBelongToUser, - GetFairCalendarOverview + FairCalendarOverviewFactory, + FairCalendarOverviewTableFactory ] }) export class FairCalendarModule {} diff --git a/server/src/assets/styles/_blocks/badge.css b/server/src/assets/styles/_blocks/badge.css index 60e04c46..eec7909f 100644 --- a/server/src/assets/styles/_blocks/badge.css +++ b/server/src/assets/styles/_blocks/badge.css @@ -1,6 +1,12 @@ .pc-badge { - display: grid; - place-items: center; - border-radius: 50%; - background: var(--background-muted); + --badge-color: inherit; + --badge-background: var(--background-muted); + display: inline-flex; + justify-content: center; + align-items: center; + padding: 0 calc(2 * var(--v)); + color: var(--badge-color, inherit); + background-color: var(--badge-background); + border: 1px solid var(--badge-background); + border-radius: var(--badge-radius, calc(1 * var(--w))); } diff --git a/server/src/assets/styles/_blocks/table.css b/server/src/assets/styles/_blocks/table.css index 46414ee0..6e8e339a 100644 --- a/server/src/assets/styles/_blocks/table.css +++ b/server/src/assets/styles/_blocks/table.css @@ -1,5 +1,9 @@ .pc-table-wrapper { overflow-x: auto; + border: 1px solid var(--border-default); +} + +.pc-table-wrapper:not(.pc-table--no-shadow) { box-shadow: var(--shadow-default); } @@ -12,12 +16,19 @@ table.pc-table { .pc-table thead { font-weight: var(--font-weight-md); - text-align: left; color: var(--text-muted); text-transform: uppercase; background-color: var(--background-alt-grey); } +.pc-table-wrapper:not(.pc-table--center) thead { + text-align: left; +} + +.pc-table--center { + text-align: center; +} + @media (prefers-color-scheme: dark) { .pc-table thead { background-color: var(--background-default); diff --git a/server/src/assets/styles/_utilities/border.css b/server/src/assets/styles/_utilities/border.css index 2e0853a5..589f4a0e 100644 --- a/server/src/assets/styles/_utilities/border.css +++ b/server/src/assets/styles/_utilities/border.css @@ -1,3 +1,7 @@ .pc-circle { border-radius: 50%; } + +.pc-border-default { + border: 1px solid var(--border-default); +} diff --git a/server/src/assets/styles/_utilities/index.css b/server/src/assets/styles/_utilities/index.css index 08cb473c..5d395b91 100644 --- a/server/src/assets/styles/_utilities/index.css +++ b/server/src/assets/styles/_utilities/index.css @@ -8,4 +8,5 @@ @import './row.css'; @import './shadow.css'; @import './sizing.css'; +@import './text.css'; @import './z-index.css'; diff --git a/server/src/assets/styles/_utilities/text.css b/server/src/assets/styles/_utilities/text.css new file mode 100644 index 00000000..bb2f030a --- /dev/null +++ b/server/src/assets/styles/_utilities/text.css @@ -0,0 +1,3 @@ +.pc-bold { + font-weight: bold; +} diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/_variables.css index e0af9b09..7fd205be 100644 --- a/server/src/assets/styles/_variables.css +++ b/server/src/assets/styles/_variables.css @@ -47,9 +47,9 @@ --event-support-background: rgb(229, 237, 255); --event-support-border: rgb(229, 237, 255); --event-support-text: rgb(81, 69, 205); - --event-formation_conference-background: rgb(254, 236, 220); - --event-formation_conference-border: rgb(254, 236, 220); - --event-formation_conference-text: rgb(180, 52, 3); + --event-formationConference-background: rgb(254, 236, 220); + --event-formationConference-border: rgb(254, 236, 220); + --event-formationConference-text: rgb(180, 52, 3); --event-leave-background: rgb(253, 246, 178); --event-leave-border: rgb(253, 246, 178); --event-leave-text: rgb(142, 75, 16); @@ -80,9 +80,9 @@ --event-support-background: rgb(81, 69, 205); --event-support-border: rgb(81, 69, 205); --event-support-text: var(--text-default); - --event-formation_conference-background: rgb(180, 52, 3); - --event-formation_conference-border: rgb(180, 52, 3); - --event-formation_conference-text: var(--text-default); + --event-formationConference-background: rgb(180, 52, 3); + --event-formationConference-border: rgb(180, 52, 3); + --event-formationConference-text: var(--text-default); --event-other-background: rgb(36, 38, 45); --event-other-border: rgb(36, 38, 45); --event-other-text: var(--text-default); diff --git a/server/src/templates/pages/faircalendar/_overview_badge.njk b/server/src/templates/pages/faircalendar/_overview_badge.njk new file mode 100644 index 00000000..9a5ab397 --- /dev/null +++ b/server/src/templates/pages/faircalendar/_overview_badge.njk @@ -0,0 +1,3 @@ + + {{ 'faircalendar-overview-days'|trans({ days: days }) }} + diff --git a/server/src/templates/pages/faircalendar/index.njk b/server/src/templates/pages/faircalendar/index.njk index 8f943b68..ecb72e40 100644 --- a/server/src/templates/pages/faircalendar/index.njk +++ b/server/src/templates/pages/faircalendar/index.njk @@ -26,6 +26,8 @@ + {% table overviewTable, { attr: {class: 'pc-table--center pc-table--no-shadow pc-m', style: '--m: calc(2 * var(--w)) 0'} } %} + + [0] 0 + [1] 1 jour + *[other] {$days} jours +} crm-title = FairCRM From 1bc0a9db500da63fc5cee5431d95714ba79d36ba Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Thu, 28 Sep 2023 12:37:05 +0200 Subject: [PATCH 31/49] Add dynamic faircalendar filters, rework faircalendar layout --- server/package.json | 5 +- .../ExtendedRouting/RouteNameResolver.ts | 4 +- .../Controller/FairCalendarController.ts | 17 ++++- .../DTO/FairCalendarControllerDTO.ts | 18 ++++- .../NunjucksTemplates/NunjucksTemplates.ts | 13 +++- .../customElements/fairCalendarFiltersForm.js | 71 +++++++++++++++++++ .../src/assets/customElements/fullcalendar.js | 2 +- server/src/assets/customElements/index.js | 4 ++ server/src/assets/lib/turbolite.js | 42 +++++++++++ server/src/assets/styles/_utilities/index.css | 4 +- server/src/assets/styles/_utilities/list.css | 5 ++ .../src/assets/styles/_utilities/padding.css | 7 -- .../assets/styles/_utilities/placement.css | 4 ++ .../src/assets/styles/_utilities/sizing.css | 4 ++ .../spacing.css} | 15 ++-- server/src/assets/styles/_utilities/text.css | 4 ++ server/src/assets/styles/_variables.css | 4 +- server/src/assets/styles/main.css | 1 - .../templates/pages/faircalendar/index.njk | 58 ++++++++++----- server/src/translations/fr-FR.ftl | 7 +- 20 files changed, 240 insertions(+), 49 deletions(-) create mode 100644 server/src/assets/customElements/fairCalendarFiltersForm.js create mode 100644 server/src/assets/lib/turbolite.js create mode 100644 server/src/assets/styles/_utilities/list.css delete mode 100644 server/src/assets/styles/_utilities/padding.css create mode 100644 server/src/assets/styles/_utilities/placement.css rename server/src/assets/styles/{_utilities.css => _utilities/spacing.css} (52%) diff --git a/server/package.json b/server/package.json index 69c85ecb..3650af21 100644 --- a/server/package.json +++ b/server/package.json @@ -7,8 +7,9 @@ "scripts": { "prebuild": "rimraf dist", "build": "nest build", - "assets:build": "esbuild src/assets/main.js --bundle --minify --outfile=dist/public/app.js", - "assets:watch": "npm run assets:build -- --watch", + "_esbuild": "esbuild src/assets/main.js --bundle --outfile=dist/public/app.js", + "assets:build": "npm run _esbuild -- --minify", + "assets:watch": "npm run _esbuild -- --watch", "format": "prettier --write \"src/**/*.ts\" \"src/assets/**/*\" \"e2e/**/*.js\"", "start": "nest start", "start:dev": "nest start --preserveWatchOutput --watch --debug", diff --git a/server/src/Infrastructure/Common/ExtendedRouting/RouteNameResolver.ts b/server/src/Infrastructure/Common/ExtendedRouting/RouteNameResolver.ts index 3efb644a..97bcc0e0 100644 --- a/server/src/Infrastructure/Common/ExtendedRouting/RouteNameResolver.ts +++ b/server/src/Infrastructure/Common/ExtendedRouting/RouteNameResolver.ts @@ -66,7 +66,9 @@ export class RouteNameResolver { } public getName(path: string): string | null { - const parts = this.splitPath([path]); + const pathWithoutQueryString = path.split('?')[0]; + + const parts = this.splitPath([pathWithoutQueryString]); const entries = Array.from(this.nameMap.entries()); entries.sort( diff --git a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts index 8d2e6f09..54a42081 100644 --- a/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts +++ b/server/src/Infrastructure/FairCalendar/Controller/FairCalendarController.ts @@ -40,7 +40,11 @@ export class FairCalendarController { @Query() dto: FairCalendarControllerDTO, @LoggedUser() user: User ) { - const date = dto.date ? new Date(dto.date) : new Date(); + const date = + dto.month !== undefined && dto.year !== undefined + ? new Date(dto.year, dto.month, 15) + : new Date(); + const userId = dto.userId ? dto.userId : user['id']; const users: UserView[] = await this.queryBus.execute(new GetUsersQuery()); @@ -86,11 +90,20 @@ export class FairCalendarController { }; }); + const currentYear = date.getFullYear(); + const minYear = dto.minYear ?? currentYear - 5; + const maxYear = dto.maxYear ?? currentYear; + return { users, + overviewTable, fullCalendarEvents, date, - overviewTable + currentMonth: date.getMonth(), + currentYear: date.getFullYear(), + minYear, + maxYear, + userId }; } } diff --git a/server/src/Infrastructure/FairCalendar/DTO/FairCalendarControllerDTO.ts b/server/src/Infrastructure/FairCalendar/DTO/FairCalendarControllerDTO.ts index 57bbac22..ee19fa0b 100644 --- a/server/src/Infrastructure/FairCalendar/DTO/FairCalendarControllerDTO.ts +++ b/server/src/Infrastructure/FairCalendar/DTO/FairCalendarControllerDTO.ts @@ -1,4 +1,4 @@ -import { IsOptional, IsUUID, IsISO8601 } from 'class-validator'; +import { IsOptional, IsUUID, IsNumber } from 'class-validator'; // TODO test export class FairCalendarControllerDTO { @@ -6,7 +6,19 @@ export class FairCalendarControllerDTO { @IsOptional() public userId?: string; - @IsISO8601() + @IsNumber() @IsOptional() - public date?: string; + public month?: number; + + @IsNumber() + @IsOptional() + public year?: number; + + @IsNumber() + @IsOptional() + public minYear?: number; + + @IsNumber() + @IsOptional() + public maxYear?: number; } diff --git a/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts b/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts index 5c243a95..8d4c55b5 100644 --- a/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts +++ b/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts @@ -14,6 +14,7 @@ import { } from '../../Common/Utils/dateUtils'; import { ArrayUtils } from '../../Common/Utils/ArrayUtils'; import { TablesExtension } from './TablesExtension'; +import { getMonth, getYear } from 'date-fns'; @Injectable() export class NunjucksTemplates implements ITemplates { @@ -39,9 +40,17 @@ export class NunjucksTemplates implements ITemplates { ); env.addFilter('minutesToHours', minutes => minutesToHours(minutes)); env.addFilter('fullName', obj => formatFullName(obj)); - env.addFilter('date', value => formatDate(value)); + env.addFilter('date', value => + value === 'now' ? new Date() : formatDate(value) + ); env.addFilter('htmlDate', value => formatHtmlDate(value)); env.addFilter('htmlYearMonth', value => formatHtmlDate(value).slice(0, 7)); + env.addFilter('longMonth', (month: number) => + this.translator.translate('common-month-long', { + date: new Date(2023, month, 15) + }) + ); + env.addFilter('year', (date: Date) => getYear(date)); env.addFilter('zip', (left, right) => ArrayUtils.zip(left, right)); env.addFilter('merge', (left, right) => { const result = {}; @@ -94,6 +103,8 @@ export class NunjucksTemplates implements ITemplates { ctx['asset'] = (path: string) => `${assetsRoot}/${path}`; + ctx['now'] = new Date(); + next(); }); diff --git a/server/src/assets/customElements/fairCalendarFiltersForm.js b/server/src/assets/customElements/fairCalendarFiltersForm.js new file mode 100644 index 00000000..6bd10f71 --- /dev/null +++ b/server/src/assets/customElements/fairCalendarFiltersForm.js @@ -0,0 +1,71 @@ +import { buildFormFetchUrl, visit } from '../lib/turbolite'; + +export default class extends HTMLFormElement { + connectedCallback() { + const clipMonth = month => { + if (month < 0) { + month += 12; + + const newYear = +this.year.value - 1; + + if (newYear < +this.minYear.value) { + this.year.options.add(new Option(newYear, newYear)); + this.minYear.value = newYear; + } + + this.year.value = newYear; + } + + if (month > 11) { + month -= 12; + + const newYear = +this.year.value + 1; + + if (newYear > +this.maxYear.value) { + this.year.options.add(new Option(newYear, newYear)); + this.maxYear.value = newYear; + } + + this.year.value = newYear; + } + + return month; + }; + + const doSubmit = async () => { + const url = buildFormFetchUrl(this); + await visit(url, { + targets: [this.dataset.titleTarget, this.dataset.calendarTarget] + }); + }; + + this.previousBtn.addEventListener('click', () => { + this.month.value = clipMonth(+this.month.value - 1); + doSubmit(); + }); + + this.todayBtn.addEventListener('click', () => { + const today = new Date(); + this.month.value = today.getMonth(); + this.year.value = today.getFullYear(); + doSubmit(); + }); + + this.nextBtn.addEventListener('click', () => { + this.month.value = clipMonth(+this.month.value + 1); + doSubmit(); + }); + + this.month.addEventListener('change', () => { + doSubmit(); + }); + + this.year.addEventListener('change', () => { + doSubmit(); + }); + + this.userId.addEventListener('change', () => { + doSubmit(); + }); + } +} diff --git a/server/src/assets/customElements/fullcalendar.js b/server/src/assets/customElements/fullcalendar.js index 6e6b69c8..de910266 100644 --- a/server/src/assets/customElements/fullcalendar.js +++ b/server/src/assets/customElements/fullcalendar.js @@ -19,7 +19,7 @@ export default class extends HTMLElement { showNonCurrentDates: false, selectable: true, weekends: false, - height: 700, + height: this.dataset.height, headerToolbar: false, dayHeaderFormat: { weekday: 'long' }, events, diff --git a/server/src/assets/customElements/index.js b/server/src/assets/customElements/index.js index 5511dc8d..e91a3dbf 100644 --- a/server/src/assets/customElements/index.js +++ b/server/src/assets/customElements/index.js @@ -1,7 +1,11 @@ import fullcalendar from './fullcalendar'; import blobLink from './blobLink'; import clipboard from './clipboard'; +import fairCalendarFiltersForm from './fairCalendarFiltersForm'; customElements.define('pc-fullcalendar', fullcalendar); customElements.define('pc-blob-link', blobLink, { extends: 'a' }); customElements.define('pc-clipboard', clipboard, { extends: 'button' }); +customElements.define('pc-faircalendar-filters-form', fairCalendarFiltersForm, { + extends: 'form' +}); diff --git a/server/src/assets/lib/turbolite.js b/server/src/assets/lib/turbolite.js new file mode 100644 index 00000000..b1c69264 --- /dev/null +++ b/server/src/assets/lib/turbolite.js @@ -0,0 +1,42 @@ +/** + * [Turbo][0] / [htmx][1]-like functionality + * [0]: https://turbo.hotwired.dev/ + * [1]: https://htmx.org/ + */ + +/** + * Fetch a web page, then swap targets with theirs. + * New is NOT processed. + * + * @param {string} url + * @param {{ targets: string[] } options} + * @returns {Promise} + */ +export async function visit(url, options = { targets: ['body'] }) { + const response = await fetch(url); + + // Inspiration: https://stackoverflow.com/a/10585079 + const tmpDoc = document.createElement('html'); + tmpDoc.innerHTML = await response.text(); + + options.targets.forEach(target => { + document.querySelector(target).replaceWith(tmpDoc.querySelector(target)); + }); + + window.history.pushState({}, '', response.url); +} + +/** + * Build an URL suitable for submitting a
    through the Fetch API. + * + * @param {HTMLFormElement} form + * @returns {URL} + */ +export const buildFormFetchUrl = form => { + const data = new FormData(form); + + const url = new URL(form.action); + url.search = new URLSearchParams(data.entries()).toString(); + + return url; +}; diff --git a/server/src/assets/styles/_utilities/index.css b/server/src/assets/styles/_utilities/index.css index 5d395b91..40530e6b 100644 --- a/server/src/assets/styles/_utilities/index.css +++ b/server/src/assets/styles/_utilities/index.css @@ -4,9 +4,11 @@ @import './flex.css'; @import './gap.css'; @import './grid.css'; -@import './padding.css'; +@import './list.css'; +@import './placement.css'; @import './row.css'; @import './shadow.css'; @import './sizing.css'; +@import './spacing.css'; @import './text.css'; @import './z-index.css'; diff --git a/server/src/assets/styles/_utilities/list.css b/server/src/assets/styles/_utilities/list.css new file mode 100644 index 00000000..59f2cd35 --- /dev/null +++ b/server/src/assets/styles/_utilities/list.css @@ -0,0 +1,5 @@ +.pc-raw-list { + list-style-type: none; + margin: 0; + padding: 0; +} diff --git a/server/src/assets/styles/_utilities/padding.css b/server/src/assets/styles/_utilities/padding.css deleted file mode 100644 index adfe8403..00000000 --- a/server/src/assets/styles/_utilities/padding.css +++ /dev/null @@ -1,7 +0,0 @@ -.pc-p { - padding: var(--p); -} - -.pc-p-block { - padding-block: var(--p-block); -} diff --git a/server/src/assets/styles/_utilities/placement.css b/server/src/assets/styles/_utilities/placement.css new file mode 100644 index 00000000..003954a0 --- /dev/null +++ b/server/src/assets/styles/_utilities/placement.css @@ -0,0 +1,4 @@ +.pc-center { + display: grid; + place-items: center; +} diff --git a/server/src/assets/styles/_utilities/sizing.css b/server/src/assets/styles/_utilities/sizing.css index 0e373431..a30d6bb8 100644 --- a/server/src/assets/styles/_utilities/sizing.css +++ b/server/src/assets/styles/_utilities/sizing.css @@ -2,6 +2,10 @@ width: var(--w); } +.pc-w-full { + width: 100%; +} + .pc-h { height: var(--h); } diff --git a/server/src/assets/styles/_utilities.css b/server/src/assets/styles/_utilities/spacing.css similarity index 52% rename from server/src/assets/styles/_utilities.css rename to server/src/assets/styles/_utilities/spacing.css index 62063f22..8091493b 100644 --- a/server/src/assets/styles/_utilities.css +++ b/server/src/assets/styles/_utilities/spacing.css @@ -1,8 +1,3 @@ -.pc-center { - display: grid; - place-items: center; -} - .pc-m { margin: var(--m); } @@ -23,12 +18,10 @@ padding: var(--p); } -.pc-text--center { - text-align: center; +.pc-p-block { + padding-block: var(--p-block); } -.pc-raw-list { - list-style-type: none; - margin: 0; - padding: 0; +.pc-stack > * + * { + margin-top: var(--stack-spacing, calc(2 * var(--w))); } diff --git a/server/src/assets/styles/_utilities/text.css b/server/src/assets/styles/_utilities/text.css index bb2f030a..d366e7e7 100644 --- a/server/src/assets/styles/_utilities/text.css +++ b/server/src/assets/styles/_utilities/text.css @@ -1,3 +1,7 @@ +.pc-text--center { + text-align: center; +} + .pc-bold { font-weight: bold; } diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/_variables.css index 7fd205be..9d2864a3 100644 --- a/server/src/assets/styles/_variables.css +++ b/server/src/assets/styles/_variables.css @@ -25,7 +25,7 @@ --background-error-hover: #b92020; --text-default: #282828; --text-muted: #6e6e6e; - --text-on-muted: #282828; + --text-on-muted: var(--text-default); --text-on-background-action-violet: #ffffff; --text-action-violet: #6c2bd9; --text-error: #ff0000; @@ -65,8 +65,10 @@ :root { /* Colors */ --background-default: #1a1b23; + --background-default-hover: #2a2b36; --background-alt-grey: #121317; --background-muted: #272930; + --background-muted-hover: #33353d; --text-default: #ffffff; --text-muted: #bbbbbb; --border-default: #636363; diff --git a/server/src/assets/styles/main.css b/server/src/assets/styles/main.css index 53ea4eae..a69fbaea 100644 --- a/server/src/assets/styles/main.css +++ b/server/src/assets/styles/main.css @@ -2,6 +2,5 @@ @import './_reset.css'; @import './_defaults.css'; @import './_blocks/index.css'; -@import './_utilities.css'; @import './_utilities/index.css'; @import './_overrides.css'; diff --git a/server/src/templates/pages/faircalendar/index.njk b/server/src/templates/pages/faircalendar/index.njk index ecb72e40..7214e0dd 100644 --- a/server/src/templates/pages/faircalendar/index.njk +++ b/server/src/templates/pages/faircalendar/index.njk @@ -1,37 +1,63 @@ {% extends 'layouts/app.njk' %} +{% import 'macros/icons.njk' as icons %} {% from 'macros/breadcrumb.njk' import breadcrumb %} -{% set title = 'faircalendar-title'|trans %} +{% set title = 'faircalendar-page-title'|trans({ date: date }) %} {% block main %}
    - {{ breadcrumb([{ title: title}]) }} + {{ breadcrumb([{ title: title }]) }}

    {{ title }}

    - -
    -
    +
    + + + + +
    + + + +
    +
    - +
    -
    +
    + + +
    +
    -
    - + - {% table overviewTable, { attr: {class: 'pc-table--center pc-table--no-shadow pc-m', style: '--m: calc(2 * var(--w)) 0'} } %} +
    + {% table overviewTable, { attr: {class: 'pc-table--center pc-table--no-shadow'} } %} - + +
    +
    {% endblock main %} diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index 9b052208..f3acbc20 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -9,6 +9,7 @@ common-no = Non common-table-empty = Aucun élément common-money = {NUMBER($value, style: "currency", currency: "EUR", minimumFractionDigits: 2, maximumFractionDigits: 2)} € common-date = {DATETIME($date, month: "numeric", year: "numeric", day: "numeric")} +common-month-long = {DATETIME($date, month: "long")} site-title = Permacoop @@ -28,6 +29,7 @@ home-pending-leaves-see-all = Voir les demandes de congés dashboard-title = Tableau de bord faircalendar-title = FairCalendar +faircalendar-page-title = FairCalendar {DATETIME($date, month: "long", year: "numeric")} faircalendar-events-add-title = Ajout d'un CRA le {$date} faircalendar-events-edit-title = Édition du CRA du {$date} faircalendar-type-title = Type de CRA @@ -43,8 +45,9 @@ faircalendar-type-option = {$type -> faircalendar-taskId-title = Mission faircalendar-projectId-title = Projet faircalendar-time-title = Temps passé -faircalendar-filters-month-title = Filtrer par mois -faircalendar-filters-userId-title = Filtrer par coopérateur-salarié +faircalendar-filters-month-title = Mois +faircalendar-filters-year-title = Année +faircalendar-filters-userId-title = Coopérateur·ice - salarié·e faircalendar-overview-days = {$days -> [0] 0 [1] 1 jour From 261d276ca6da513a859b19368e2ea94f864368d8 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Fri, 6 Oct 2023 10:03:04 +0200 Subject: [PATCH 32/49] Implement mobile menu v1 --- server/src/assets/customElements/index.js | 2 + server/src/assets/customElements/navToggle.js | 10 +++++ server/src/assets/styles/_blocks/nav.css | 22 +++++++++++ server/src/assets/styles/_layouts/cluster.css | 6 +++ server/src/assets/styles/_layouts/index.css | 3 ++ server/src/assets/styles/_layouts/sidebar.css | 17 +++++++++ server/src/assets/styles/_layouts/stack.css | 3 ++ .../assets/styles/_utilities/placement.css | 4 ++ .../src/assets/styles/_utilities/spacing.css | 4 -- server/src/assets/styles/main.css | 1 + server/src/templates/components/header.njk | 11 +++++- server/src/templates/components/nav.njk | 2 +- server/src/templates/layouts/app.njk | 16 +++----- server/src/templates/macros/icons.njk | 6 +++ .../templates/pages/faircalendar/_filters.njk | 36 ++++++++++++++++++ .../templates/pages/faircalendar/index.njk | 37 +------------------ 16 files changed, 128 insertions(+), 52 deletions(-) create mode 100644 server/src/assets/customElements/navToggle.js create mode 100644 server/src/assets/styles/_layouts/cluster.css create mode 100644 server/src/assets/styles/_layouts/index.css create mode 100644 server/src/assets/styles/_layouts/sidebar.css create mode 100644 server/src/assets/styles/_layouts/stack.css create mode 100644 server/src/templates/pages/faircalendar/_filters.njk diff --git a/server/src/assets/customElements/index.js b/server/src/assets/customElements/index.js index e91a3dbf..f337bda6 100644 --- a/server/src/assets/customElements/index.js +++ b/server/src/assets/customElements/index.js @@ -2,6 +2,7 @@ import fullcalendar from './fullcalendar'; import blobLink from './blobLink'; import clipboard from './clipboard'; import fairCalendarFiltersForm from './fairCalendarFiltersForm'; +import navToggle from './navToggle'; customElements.define('pc-fullcalendar', fullcalendar); customElements.define('pc-blob-link', blobLink, { extends: 'a' }); @@ -9,3 +10,4 @@ customElements.define('pc-clipboard', clipboard, { extends: 'button' }); customElements.define('pc-faircalendar-filters-form', fairCalendarFiltersForm, { extends: 'form' }); +customElements.define('pc-nav-toggle', navToggle, { extends: 'button' }); diff --git a/server/src/assets/customElements/navToggle.js b/server/src/assets/customElements/navToggle.js new file mode 100644 index 00000000..0bbb51fa --- /dev/null +++ b/server/src/assets/customElements/navToggle.js @@ -0,0 +1,10 @@ +export default class extends HTMLButtonElement { + connectedCallback() { + /** @type {HTMLElement} */ + const nav = document.querySelector('[data-nav-toggle-target="nav"]'); + + this.addEventListener('click', () => { + nav.classList.toggle('pc-nav-open'); + }); + } +} diff --git a/server/src/assets/styles/_blocks/nav.css b/server/src/assets/styles/_blocks/nav.css index f0ef8a5f..e603727a 100644 --- a/server/src/assets/styles/_blocks/nav.css +++ b/server/src/assets/styles/_blocks/nav.css @@ -1,5 +1,27 @@ .pc-nav { color: var(--text-muted); + display: none; +} + +#pc-nav-toggle { + background-color: transparent; + border: none; + width: 2rem; + height: 2rem; + cursor: pointer; +} + +.pc-nav-open { + display: block; +} + +@media screen and (min-width: 840px) { + #pc-nav-toggle { + display: none; + } + .pc-nav { + display: block; + } } .pc-nav ul { diff --git a/server/src/assets/styles/_layouts/cluster.css b/server/src/assets/styles/_layouts/cluster.css new file mode 100644 index 00000000..e17552db --- /dev/null +++ b/server/src/assets/styles/_layouts/cluster.css @@ -0,0 +1,6 @@ +.pc-cluster { + display: flex; + flex-wrap: wrap; + justify-content: var(--cluster-justify, flex-start); + align-items: var(--cluster-align, flex-start); +} diff --git a/server/src/assets/styles/_layouts/index.css b/server/src/assets/styles/_layouts/index.css new file mode 100644 index 00000000..17fed00a --- /dev/null +++ b/server/src/assets/styles/_layouts/index.css @@ -0,0 +1,3 @@ +@import './cluster.css'; +@import './sidebar.css'; +@import './stack.css'; diff --git a/server/src/assets/styles/_layouts/sidebar.css b/server/src/assets/styles/_layouts/sidebar.css new file mode 100644 index 00000000..77a9ba19 --- /dev/null +++ b/server/src/assets/styles/_layouts/sidebar.css @@ -0,0 +1,17 @@ +.pc-with-sidebar { + display: flex; + justify-content: flex-start; + align-items: flex-start; + flex-wrap: wrap; +} + +.pc-with-sidebar > :first-child { + flex-basis: var(--sidebar-size, 20rem); + flex-grow: 1; +} + +.pc-with-sidebar > :last-child { + flex-basis: 0; + flex-grow: 999; + min-inline-size: var(--non-sidebar-min-size, 50%); +} diff --git a/server/src/assets/styles/_layouts/stack.css b/server/src/assets/styles/_layouts/stack.css new file mode 100644 index 00000000..db80084f --- /dev/null +++ b/server/src/assets/styles/_layouts/stack.css @@ -0,0 +1,3 @@ +.pc-stack > * + * { + margin-top: var(--stack-spacing, calc(2 * var(--w))); +} diff --git a/server/src/assets/styles/_utilities/placement.css b/server/src/assets/styles/_utilities/placement.css index 003954a0..23bceedc 100644 --- a/server/src/assets/styles/_utilities/placement.css +++ b/server/src/assets/styles/_utilities/placement.css @@ -2,3 +2,7 @@ display: grid; place-items: center; } + +.pc-relative { + position: relative; +} diff --git a/server/src/assets/styles/_utilities/spacing.css b/server/src/assets/styles/_utilities/spacing.css index 8091493b..0a46a701 100644 --- a/server/src/assets/styles/_utilities/spacing.css +++ b/server/src/assets/styles/_utilities/spacing.css @@ -21,7 +21,3 @@ .pc-p-block { padding-block: var(--p-block); } - -.pc-stack > * + * { - margin-top: var(--stack-spacing, calc(2 * var(--w))); -} diff --git a/server/src/assets/styles/main.css b/server/src/assets/styles/main.css index a69fbaea..94070ac4 100644 --- a/server/src/assets/styles/main.css +++ b/server/src/assets/styles/main.css @@ -1,6 +1,7 @@ @import './_variables.css'; @import './_reset.css'; @import './_defaults.css'; +@import './_layouts/index.css'; @import './_blocks/index.css'; @import './_utilities/index.css'; @import './_overrides.css'; diff --git a/server/src/templates/components/header.njk b/server/src/templates/components/header.njk index fed08d90..a2fb5cce 100644 --- a/server/src/templates/components/header.njk +++ b/server/src/templates/components/header.njk @@ -1,6 +1,15 @@ {% import 'macros/icons.njk' as icons %} -
    +
    + + + + Fairness + {{ "site-title"|trans }} + +
    {{ req.user.firstName|first|capitalize }} diff --git a/server/src/templates/components/nav.njk b/server/src/templates/components/nav.njk index ed65393b..620d4ad1 100644 --- a/server/src/templates/components/nav.njk +++ b/server/src/templates/components/nav.njk @@ -1,6 +1,6 @@ {% import 'macros/icons.njk' as icons %} -
    +
  • + diff --git a/server/src/templates/layouts/app.njk b/server/src/templates/layouts/app.njk index 126014b8..cdf6665b 100644 --- a/server/src/templates/layouts/app.njk +++ b/server/src/templates/layouts/app.njk @@ -1,15 +1,17 @@ {% extends 'layouts/_base.njk' %} {% import 'macros/icons.njk' as icons %} -{% block body_attr %}class="pc-relative"{% endblock %} +{% block body_attr %}class="pc-app"{% endblock %} {% block body %} {% include 'components/header.njk' %} -
    - {% include 'components/nav.njk' %} +
    + -
    +
    {% block main %}{% endblock main %}
    diff --git a/server/src/templates/pages/leaves/list.njk b/server/src/templates/pages/leaves/list.njk index 193c0cd9..f491a509 100644 --- a/server/src/templates/pages/leaves/list.njk +++ b/server/src/templates/pages/leaves/list.njk @@ -25,7 +25,7 @@
    -
    diff --git a/server/src/translations/fr-FR.ftl b/server/src/translations/fr-FR.ftl index 40c038ff..ff6666b6 100644 --- a/server/src/translations/fr-FR.ftl +++ b/server/src/translations/fr-FR.ftl @@ -86,41 +86,6 @@ profile-password = Mot de passe people-title = FairRH -users-title = Coopérateur·ices et salarié·es -users-add-title = Ajouter un·e coopérateur·ice-salarié·e -users-edit-title = Mise à jour des informations administratives de {$user} -users-firstName = Prénom -users-lastName = Nom -users-email = Adresse e-mail -users-role = Rôle -users-role-value = {$role -> - [cooperator] Coopérateur·ice - [employee] Salarié·e - [accountant] Comptable - *[other] Autre -} -users-contract = Contrat de travail -users-contract-value = {$contract -> - [cdi] CDI - [cdd] CDD - [ctt] CTT - [apprenticeship] Apprentissage - [professionalization] Professionalisation - *[other] Autre -} -users-workingTime = Temps de travail -users-workingTime-value = {$workingTime -> - [full_time] Temps plein - [part_time] Temps partiel - *[other] Autre -} -users-executivePosition = Statut cadre -users-healthInsurance = Mutuelle -users-annualEarnings = Salaire annuel brut -users-transportFee = Frais de transport -users-sustainableMobilityFee = Forfait mobilité durable -users-joiningDate = Date d'entrée -users-leavingDate = Date de sortie leaves-title = Congés leaves-user = Coopérateur·ice - salarié·e @@ -200,4 +165,41 @@ meal-tickets-num-exceptions = Nb exceptions meal-tickets-add-removal-title = Ajouter une exception meal-tickets-removal-date = Je ne souhaite pas recevoir de ticket restaurant pour la date du : + +users-title = Coopérateur·ices et salarié·es +users-add-title = Ajouter un·e coopérateur·ice-salarié·e +users-edit-title = Mise à jour des informations administratives de {$user} +users-firstName = Prénom +users-lastName = Nom +users-email = Adresse e-mail +users-role = Rôle +users-role-value = {$role -> + [cooperator] Coopérateur·ice + [employee] Salarié·e + [accountant] Comptable + *[other] Autre +} +users-contract = Contrat de travail +users-contract-value = {$contract -> + [cdi] CDI + [cdd] CDD + [ctt] CTT + [apprenticeship] Apprentissage + [professionalization] Professionalisation + *[other] Autre +} +users-workingTime = Temps de travail +users-workingTime-value = {$workingTime -> + [full_time] Temps plein + [part_time] Temps partiel + *[other] Autre +} +users-executivePosition = Statut cadre +users-healthInsurance = Mutuelle +users-annualEarnings = Salaire annuel brut +users-transportFee = Frais de transport +users-sustainableMobilityFee = Forfait mobilité durable +users-joiningDate = Date d'entrée +users-leavingDate = Date de sortie + clipboard-copy = Copier dans le presse papier From b71875f4b077a482e2d8f7244ce9a9dd049fc66e Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Wed, 11 Oct 2023 18:55:24 +0200 Subject: [PATCH 35/49] Implement theme toggler --- server/package-lock.json | 37 +++++++++++ server/package.json | 1 + .../NunjucksTemplates/NunjucksTemplates.ts | 2 + server/src/assets/customElements/index.js | 2 + .../src/assets/customElements/themeToggler.js | 26 ++++++++ server/src/assets/lib/cookie.js | 5 ++ server/src/assets/styles/_blocks/button.css | 13 ++++ server/src/assets/styles/_blocks/icon.css | 6 +- server/src/assets/styles/_blocks/index.css | 1 + server/src/assets/styles/_blocks/table.css | 6 +- server/src/assets/styles/_blocks/theme.css | 7 +++ .../src/assets/styles/_utilities/border.css | 4 ++ .../src/assets/styles/_utilities/sizing.css | 2 +- server/src/assets/styles/_variables.css | 62 +++++++++---------- server/src/main.ts | 2 + server/src/templates/components/header.njk | 47 +++++++------- .../templates/components/theme_toggler.njk | 6 ++ server/src/templates/layouts/_base.njk | 2 +- server/src/templates/macros/icons.njk | 25 ++++++-- 19 files changed, 190 insertions(+), 66 deletions(-) create mode 100644 server/src/assets/customElements/themeToggler.js create mode 100644 server/src/assets/lib/cookie.js create mode 100644 server/src/assets/styles/_blocks/theme.css create mode 100644 server/src/templates/components/theme_toggler.njk diff --git a/server/package-lock.json b/server/package-lock.json index de75832f..1edb3b30 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -27,6 +27,7 @@ "class-transformer": "^0.3.1", "class-validator": "^0.12.2", "connect-pg-simple": "^9.0.0", + "cookie-parser": "^1.4.6", "crypto": "^1.0.1", "date-fns": "^2.8.1", "express-session": "^1.17.3", @@ -4616,6 +4617,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -15134,6 +15155,22 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, + "cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "requires": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + } + } + }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", diff --git a/server/package.json b/server/package.json index 3650af21..4be3685b 100644 --- a/server/package.json +++ b/server/package.json @@ -46,6 +46,7 @@ "class-transformer": "^0.3.1", "class-validator": "^0.12.2", "connect-pg-simple": "^9.0.0", + "cookie-parser": "^1.4.6", "crypto": "^1.0.1", "date-fns": "^2.8.1", "express-session": "^1.17.3", diff --git a/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts b/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts index 8d4c55b5..74eca4fe 100644 --- a/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts +++ b/server/src/Infrastructure/Templates/NunjucksTemplates/NunjucksTemplates.ts @@ -105,6 +105,8 @@ export class NunjucksTemplates implements ITemplates { ctx['now'] = new Date(); + ctx['theme'] = req.cookies.theme; + next(); }); diff --git a/server/src/assets/customElements/index.js b/server/src/assets/customElements/index.js index 68f05dba..fc0b89e8 100644 --- a/server/src/assets/customElements/index.js +++ b/server/src/assets/customElements/index.js @@ -3,6 +3,7 @@ import blobLink from './blobLink'; import clipboardButton from './clipboardButton'; import fairCalendarFiltersForm from './fairCalendarFiltersForm'; import navToggle from './navToggle'; +import themeToggler from './themeToggler'; customElements.define('pc-fullcalendar', fullcalendar); customElements.define('pc-blob-link', blobLink, { extends: 'a' }); @@ -13,3 +14,4 @@ customElements.define('pc-faircalendar-filters-form', fairCalendarFiltersForm, { extends: 'form' }); customElements.define('pc-nav-toggle', navToggle, { extends: 'button' }); +customElements.define('pc-theme-toggler', themeToggler, { extends: 'button' }); diff --git a/server/src/assets/customElements/themeToggler.js b/server/src/assets/customElements/themeToggler.js new file mode 100644 index 00000000..974097dd --- /dev/null +++ b/server/src/assets/customElements/themeToggler.js @@ -0,0 +1,26 @@ +import { createCookie } from '../lib/cookie'; + +export default class extends HTMLButtonElement { + connectedCallback() { + let theme = document.documentElement.dataset.theme; + + if (!theme) { + theme = window.matchMedia('(prefers-color-scheme: dark)').matches + ? 'dark' + : 'light'; + this._setTheme(theme); + } + + this.addEventListener('click', () => { + theme = theme === 'dark' ? 'light' : 'dark'; + this._setTheme(theme); + }); + } + + _setTheme(theme) { + document.documentElement.setAttribute('data-theme', theme); + // Store in a cookie so the server sets next time. + // This will avoid FLOUC (Flashlight of unstyled content) when dark mode is used. + createCookie('theme', theme); + } +} diff --git a/server/src/assets/lib/cookie.js b/server/src/assets/lib/cookie.js new file mode 100644 index 00000000..813c3f40 --- /dev/null +++ b/server/src/assets/lib/cookie.js @@ -0,0 +1,5 @@ +// Adapted from: http://www.quirksmode.org/js/cookies.html + +export function createCookie(name, value) { + document.cookie = name + '=' + value + '; SameSite=Strict; path=/'; +} diff --git a/server/src/assets/styles/_blocks/button.css b/server/src/assets/styles/_blocks/button.css index a2e95a58..d57c0434 100644 --- a/server/src/assets/styles/_blocks/button.css +++ b/server/src/assets/styles/_blocks/button.css @@ -12,6 +12,12 @@ background-color: var(--hover-tint); } +.pc-btn--secondary { + --hover-tint: var(--background-muted-hover); + background-color: var(--background-default); + color: var(--text-action-violet-on-background-default); +} + .pc-btn--error { --hover-tint: var(--background-error-hover); background-color: var(--background-error); @@ -23,3 +29,10 @@ background-color: var(--background-muted); color: var(--text-on-muted); } + +.pc-btn--circle { + border-radius: 50%; + padding: 0; + display: grid; + place-items: center; +} diff --git a/server/src/assets/styles/_blocks/icon.css b/server/src/assets/styles/_blocks/icon.css index 6995d005..f6134beb 100644 --- a/server/src/assets/styles/_blocks/icon.css +++ b/server/src/assets/styles/_blocks/icon.css @@ -12,10 +12,8 @@ color: var(--text-action-violet); } -@media (prefers-color-scheme: dark) { - .pc-icon--action-violet { - color: var(--text-default); - } +[data-theme='dark'] .pc-icon--action-violet { + color: var(--text-default); } .pc-icon--sm { diff --git a/server/src/assets/styles/_blocks/index.css b/server/src/assets/styles/_blocks/index.css index 3482cbb5..f5a3047d 100644 --- a/server/src/assets/styles/_blocks/index.css +++ b/server/src/assets/styles/_blocks/index.css @@ -11,3 +11,4 @@ @import './nav.css'; @import './select-group.css'; @import './table.css'; +@import './theme.css'; diff --git a/server/src/assets/styles/_blocks/table.css b/server/src/assets/styles/_blocks/table.css index 6e8e339a..6b80dccf 100644 --- a/server/src/assets/styles/_blocks/table.css +++ b/server/src/assets/styles/_blocks/table.css @@ -29,10 +29,8 @@ table.pc-table { text-align: center; } -@media (prefers-color-scheme: dark) { - .pc-table thead { - background-color: var(--background-default); - } +[data-theme='dark'] .pc-table thead { + background-color: var(--background-default); } .pc-table th, diff --git a/server/src/assets/styles/_blocks/theme.css b/server/src/assets/styles/_blocks/theme.css new file mode 100644 index 00000000..809afa63 --- /dev/null +++ b/server/src/assets/styles/_blocks/theme.css @@ -0,0 +1,7 @@ +[data-theme='dark'] #theme-dark { + display: none; +} + +[data-theme='light'] #theme-light { + display: none; +} diff --git a/server/src/assets/styles/_utilities/border.css b/server/src/assets/styles/_utilities/border.css index 589f4a0e..acb65d15 100644 --- a/server/src/assets/styles/_utilities/border.css +++ b/server/src/assets/styles/_utilities/border.css @@ -5,3 +5,7 @@ .pc-border-default { border: 1px solid var(--border-default); } + +.pc-border-none { + border: none; +} diff --git a/server/src/assets/styles/_utilities/sizing.css b/server/src/assets/styles/_utilities/sizing.css index a30d6bb8..9f8dc0ad 100644 --- a/server/src/assets/styles/_utilities/sizing.css +++ b/server/src/assets/styles/_utilities/sizing.css @@ -1,5 +1,5 @@ .pc-w { - width: var(--w); + width: var(--wi); } .pc-w-full { diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/_variables.css index 9d2864a3..ff09f473 100644 --- a/server/src/assets/styles/_variables.css +++ b/server/src/assets/styles/_variables.css @@ -28,6 +28,7 @@ --text-on-muted: var(--text-default); --text-on-background-action-violet: #ffffff; --text-action-violet: #6c2bd9; + --text-action-violet-on-background-default: #6c2bd9; --text-error: #ff0000; --text-on-error: #ffffff; /* Borders */ @@ -61,35 +62,34 @@ --event-other-text: rgb(36, 38, 45); } -@media (prefers-color-scheme: dark) { - :root { - /* Colors */ - --background-default: #1a1b23; - --background-default-hover: #2a2b36; - --background-alt-grey: #121317; - --background-muted: #272930; - --background-muted-hover: #33353d; - --text-default: #ffffff; - --text-muted: #bbbbbb; - --border-default: #636363; - /* FairCalendar */ - --event-mission-background: rgb(4, 108, 78); - --event-mission-border: rgb(4, 108, 78); - --event-mission-text: var(--text-default); - --event-dojo-background: rgb(26, 86, 219); - --event-dojo-border: rgb(26, 86, 219); - --event-dojo-text: var(--text-default); - --event-support-background: rgb(81, 69, 205); - --event-support-border: rgb(81, 69, 205); - --event-support-text: var(--text-default); - --event-formationConference-background: rgb(180, 52, 3); - --event-formationConference-border: rgb(180, 52, 3); - --event-formationConference-text: var(--text-default); - --event-other-background: rgb(36, 38, 45); - --event-other-border: rgb(36, 38, 45); - --event-other-text: var(--text-default); - --event-holiday-background: rgb(159, 88, 10); - --event-holiday-border: rgb(159, 88, 10); - --event-holiday-text: var(--text-default); - } +[data-theme='dark'] { + /* Colors */ + --background-default: #1a1b23; + --background-default-hover: #2a2b36; + --background-alt-grey: #121317; + --background-muted: #272930; + --background-muted-hover: #33353d; + --text-default: #ffffff; + --text-muted: #bbbbbb; + --border-default: #636363; + --text-action-violet-on-background-default: #cabffd; + /* FairCalendar */ + --event-mission-background: rgb(4, 108, 78); + --event-mission-border: rgb(4, 108, 78); + --event-mission-text: var(--text-default); + --event-dojo-background: rgb(26, 86, 219); + --event-dojo-border: rgb(26, 86, 219); + --event-dojo-text: var(--text-default); + --event-support-background: rgb(81, 69, 205); + --event-support-border: rgb(81, 69, 205); + --event-support-text: var(--text-default); + --event-formationConference-background: rgb(180, 52, 3); + --event-formationConference-border: rgb(180, 52, 3); + --event-formationConference-text: var(--text-default); + --event-other-background: rgb(36, 38, 45); + --event-other-border: rgb(36, 38, 45); + --event-other-text: var(--text-default); + --event-holiday-background: rgb(159, 88, 10); + --event-holiday-border: rgb(159, 88, 10); + --event-holiday-text: var(--text-default); } diff --git a/server/src/main.ts b/server/src/main.ts index 684616d7..b7d85a62 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -5,6 +5,7 @@ import { NestFactory } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; import * as helmet from 'helmet'; import * as session from 'express-session'; +import * as cookieParser from 'cookie-parser'; import * as connectPgSimple from 'connect-pg-simple'; import { NestExpressApplication } from '@nestjs/platform-express'; import { AppModule } from './app.module'; @@ -22,6 +23,7 @@ async function bootstrap() { }); app.use(helmet()); + app.use(cookieParser()); app.useGlobalPipes( new ValidationPipe({ transform: true, diff --git a/server/src/templates/components/header.njk b/server/src/templates/components/header.njk index c5793f0b..639bd844 100644 --- a/server/src/templates/components/header.njk +++ b/server/src/templates/components/header.njk @@ -10,27 +10,32 @@ {{ "site-title"|trans }} -
    - - {{ req.user.firstName|first|capitalize }} - +
    + {% include 'components/theme_toggler.njk' %} - +
    + + {{ req.user.firstName|first|capitalize }} + + + + +
    +
    -
    diff --git a/server/src/templates/components/theme_toggler.njk b/server/src/templates/components/theme_toggler.njk new file mode 100644 index 00000000..ca1168f0 --- /dev/null +++ b/server/src/templates/components/theme_toggler.njk @@ -0,0 +1,6 @@ +{% import 'macros/icons.njk' as icons %} + + diff --git a/server/src/templates/layouts/_base.njk b/server/src/templates/layouts/_base.njk index 59311506..a5434e96 100644 --- a/server/src/templates/layouts/_base.njk +++ b/server/src/templates/layouts/_base.njk @@ -1,5 +1,5 @@ - + diff --git a/server/src/templates/macros/icons.njk b/server/src/templates/macros/icons.njk index 2d7b4d38..4e17bbb2 100644 --- a/server/src/templates/macros/icons.njk +++ b/server/src/templates/macros/icons.njk @@ -1,11 +1,14 @@ {% from 'macros/attr.njk' import render_attr %} -{% macro _icon(attr=null, paths=[], mode='stroke') %} - {% set attr = attr|default({}) %} +{% macro svg_attr(attr=null, mode='stroke') %} {% set attr = attr|merge({ class: 'pc-icon pc-icon--sm ' + attr.class|default('') }) %} - {% set attr = attr|merge({ 'aria-hidden': 'true', fill: 'none', viewBox: '0 0 24 24' }) %} + {% set attr = attr|merge({ 'aria-hidden': 'true', fill: 'none', viewBox: attr.viewBox|default('0 0 24 24') }) %} {% set attr = attr|merge({ stroke: 'currentColor' } if mode == 'stroke' else { fill: 'currentColor' }) %} - + {{- render_attr(attr) -}} +{% endmacro %} + +{% macro _icon(attr=null, paths=[], mode='stroke') %} + {% for d in paths %} {% endfor %} @@ -71,3 +74,17 @@ {% macro menu(attr=null) %} {{ _icon(attr, mode='fill', paths=["M3 4H21V6H3V4ZM3 11H21V13H3V11ZM3 18H21V20H3V18Z"]) }} {% endmacro %} + +{% macro sun(attr=null) %} + {% set attr = attr|merge({viewBox: '0 0 20 20'}) %} + + + +{% endmacro %} + +{% macro moon(attr=null) %} + {% set attr = attr|merge({viewBox: '0 0 20 20'}) %} + + + +{% endmacro %} From fdeb750208e89e2ef517c9d0533a28e819df4cd8 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Wed, 11 Oct 2023 19:56:09 +0200 Subject: [PATCH 36/49] Clean up CSS --- .../src/assets/styles/_blocks/breadcrumb.css | 21 ----------------- .../src/assets/styles/_utilities/border.css | 11 --------- server/src/assets/styles/_utilities/flex.css | 9 -------- server/src/assets/styles/_utilities/row.css | 12 ---------- .../src/assets/styles/_utilities/shadow.css | 7 ------ .../src/assets/styles/_utilities/sizing.css | 11 --------- .../src/assets/styles/_utilities/spacing.css | 23 ------------------- .../src/assets/styles/_utilities/z-index.css | 3 --- .../styles/{_blocks => components}/badge.css | 0 .../styles/{_blocks => components}/brand.css | 0 .../assets/styles/components/breadcrumb.css | 13 +++++++++++ .../styles/{_blocks => components}/button.css | 4 +++- .../{_blocks/box.css => components/card.css} | 3 +-- .../{_blocks => components}/dropdown.css | 0 .../styles/{_blocks => components}/icon.css | 0 .../styles/{_blocks => components}/index.css | 2 +- .../{_blocks => components}/input-group.css | 0 .../styles/{_blocks => components}/label.css | 0 .../styles/{_blocks => components}/link.css | 0 .../styles/{_blocks => components}/nav.css | 0 .../{_blocks => components}/select-group.css | 0 .../styles/{_blocks => components}/table.css | 0 .../styles/{_blocks => components}/theme.css | 0 .../styles/{_defaults.css => defaults.css} | 4 ---- .../styles/{_layouts => layouts}/app.css | 10 +++++--- server/src/assets/styles/layouts/box.css | 3 +++ .../styles/{_layouts => layouts}/cluster.css | 0 .../{_utilities => layouts}/container.css | 0 .../styles/{_utilities => layouts}/grid.css | 0 .../styles/{_layouts => layouts}/index.css | 3 +++ .../styles/{_layouts => layouts}/sidebar.css | 0 .../styles/{_layouts => layouts}/stack.css | 0 server/src/assets/styles/main.css | 14 +++++------ .../styles/{_overrides.css => overrides.css} | 0 .../assets/styles/{_reset.css => reset.css} | 0 .../{_utilities => utilities}/background.css | 0 .../styles/{_utilities => utilities}/gap.css | 0 .../{_utilities => utilities}/index.css | 7 ------ .../styles/{_utilities => utilities}/list.css | 0 .../{_utilities => utilities}/placement.css | 4 ++++ server/src/assets/styles/utilities/shadow.css | 3 +++ .../src/assets/styles/utilities/spacing.css | 7 ++++++ .../styles/{_utilities => utilities}/text.css | 0 .../styles/{_variables.css => variables.css} | 0 server/src/templates/components/header.njk | 4 ++-- .../templates/components/theme_toggler.njk | 2 +- server/src/templates/macros/breadcrumb.njk | 20 +++++++++++----- server/src/templates/pages/customers/add.njk | 2 +- server/src/templates/pages/customers/edit.njk | 2 +- server/src/templates/pages/customers/list.njk | 6 ++--- .../templates/pages/faircalendar/_filters.njk | 10 ++++---- .../pages/faircalendar/events/add.njk | 2 +- .../pages/faircalendar/events/edit.njk | 6 ++--- .../templates/pages/faircalendar/index.njk | 2 +- server/src/templates/pages/home.njk | 3 +++ .../templates/pages/leave_requests/add.njk | 2 +- .../templates/pages/leave_requests/detail.njk | 8 +++---- .../templates/pages/leave_requests/edit.njk | 2 +- .../templates/pages/leave_requests/list.njk | 6 ++--- server/src/templates/pages/leaves/list.njk | 10 ++++---- server/src/templates/pages/login.njk | 4 ++-- .../src/templates/pages/meal_tickets/add.njk | 2 +- .../src/templates/pages/meal_tickets/list.njk | 6 ++--- .../pages/payroll_elements/index.njk | 8 +++---- server/src/templates/pages/profile/_form.njk | 2 +- server/src/templates/pages/profile/edit.njk | 6 ++--- server/src/templates/pages/projects/add.njk | 2 +- server/src/templates/pages/projects/edit.njk | 2 +- server/src/templates/pages/projects/list.njk | 6 ++--- server/src/templates/pages/tasks/add.njk | 2 +- server/src/templates/pages/tasks/edit.njk | 2 +- server/src/templates/pages/tasks/list.njk | 6 ++--- server/src/templates/pages/users/add.njk | 2 +- server/src/templates/pages/users/edit.njk | 2 +- server/src/templates/pages/users/list.njk | 6 ++--- server/src/templates/tables/cells/actions.njk | 8 +++---- 76 files changed, 135 insertions(+), 192 deletions(-) delete mode 100644 server/src/assets/styles/_blocks/breadcrumb.css delete mode 100644 server/src/assets/styles/_utilities/border.css delete mode 100644 server/src/assets/styles/_utilities/flex.css delete mode 100644 server/src/assets/styles/_utilities/row.css delete mode 100644 server/src/assets/styles/_utilities/shadow.css delete mode 100644 server/src/assets/styles/_utilities/sizing.css delete mode 100644 server/src/assets/styles/_utilities/spacing.css delete mode 100644 server/src/assets/styles/_utilities/z-index.css rename server/src/assets/styles/{_blocks => components}/badge.css (100%) rename server/src/assets/styles/{_blocks => components}/brand.css (100%) create mode 100644 server/src/assets/styles/components/breadcrumb.css rename server/src/assets/styles/{_blocks => components}/button.css (86%) rename server/src/assets/styles/{_blocks/box.css => components/card.css} (58%) rename server/src/assets/styles/{_blocks => components}/dropdown.css (100%) rename server/src/assets/styles/{_blocks => components}/icon.css (100%) rename server/src/assets/styles/{_blocks => components}/index.css (93%) rename server/src/assets/styles/{_blocks => components}/input-group.css (100%) rename server/src/assets/styles/{_blocks => components}/label.css (100%) rename server/src/assets/styles/{_blocks => components}/link.css (100%) rename server/src/assets/styles/{_blocks => components}/nav.css (100%) rename server/src/assets/styles/{_blocks => components}/select-group.css (100%) rename server/src/assets/styles/{_blocks => components}/table.css (100%) rename server/src/assets/styles/{_blocks => components}/theme.css (100%) rename server/src/assets/styles/{_defaults.css => defaults.css} (92%) rename server/src/assets/styles/{_layouts => layouts}/app.css (61%) create mode 100644 server/src/assets/styles/layouts/box.css rename server/src/assets/styles/{_layouts => layouts}/cluster.css (100%) rename server/src/assets/styles/{_utilities => layouts}/container.css (100%) rename server/src/assets/styles/{_utilities => layouts}/grid.css (100%) rename server/src/assets/styles/{_layouts => layouts}/index.css (57%) rename server/src/assets/styles/{_layouts => layouts}/sidebar.css (100%) rename server/src/assets/styles/{_layouts => layouts}/stack.css (100%) rename server/src/assets/styles/{_overrides.css => overrides.css} (100%) rename server/src/assets/styles/{_reset.css => reset.css} (100%) rename server/src/assets/styles/{_utilities => utilities}/background.css (100%) rename server/src/assets/styles/{_utilities => utilities}/gap.css (100%) rename server/src/assets/styles/{_utilities => utilities}/index.css (50%) rename server/src/assets/styles/{_utilities => utilities}/list.css (100%) rename server/src/assets/styles/{_utilities => utilities}/placement.css (74%) create mode 100644 server/src/assets/styles/utilities/shadow.css create mode 100644 server/src/assets/styles/utilities/spacing.css rename server/src/assets/styles/{_utilities => utilities}/text.css (100%) rename server/src/assets/styles/{_variables.css => variables.css} (100%) diff --git a/server/src/assets/styles/_blocks/breadcrumb.css b/server/src/assets/styles/_blocks/breadcrumb.css deleted file mode 100644 index 5a63f9dc..00000000 --- a/server/src/assets/styles/_blocks/breadcrumb.css +++ /dev/null @@ -1,21 +0,0 @@ -nav.pc-breadcrumb[role='navigation'][aria-label] { - color: var(--text-muted); - margin-bottom: calc(4 * var(--v)); -} - -.pc-breadcrumb > ol { - list-style-type: none; - padding: 0; - margin: 0; - display: inline-flex; - align-items: center; -} - -.pc-breadcrumb li:not(:first-child)::before { - content: '/'; - margin-inline: var(--w); -} - -.pc-breadcrumb a { - font-weight: 500; -} diff --git a/server/src/assets/styles/_utilities/border.css b/server/src/assets/styles/_utilities/border.css deleted file mode 100644 index acb65d15..00000000 --- a/server/src/assets/styles/_utilities/border.css +++ /dev/null @@ -1,11 +0,0 @@ -.pc-circle { - border-radius: 50%; -} - -.pc-border-default { - border: 1px solid var(--border-default); -} - -.pc-border-none { - border: none; -} diff --git a/server/src/assets/styles/_utilities/flex.css b/server/src/assets/styles/_utilities/flex.css deleted file mode 100644 index 8bce8515..00000000 --- a/server/src/assets/styles/_utilities/flex.css +++ /dev/null @@ -1,9 +0,0 @@ -.pc-flex-between { - display: flex; - justify-content: space-between; -} - -.pc-flex-end { - display: flex; - justify-content: flex-end; -} diff --git a/server/src/assets/styles/_utilities/row.css b/server/src/assets/styles/_utilities/row.css deleted file mode 100644 index 64bac4f2..00000000 --- a/server/src/assets/styles/_utilities/row.css +++ /dev/null @@ -1,12 +0,0 @@ -.pc-row { - display: flex; - gap: var(--row-gap, calc(2 * var(--w))); -} - -.pc-row--middle { - align-items: center; -} - -.pc-row--between { - justify-content: space-between; -} diff --git a/server/src/assets/styles/_utilities/shadow.css b/server/src/assets/styles/_utilities/shadow.css deleted file mode 100644 index b450b504..00000000 --- a/server/src/assets/styles/_utilities/shadow.css +++ /dev/null @@ -1,7 +0,0 @@ -.pc-shadow { - box-shadow: var(--shadow-default); -} - -.pc-shadow-inner { - box-shadow: var(--shadow-inner); -} diff --git a/server/src/assets/styles/_utilities/sizing.css b/server/src/assets/styles/_utilities/sizing.css deleted file mode 100644 index 9f8dc0ad..00000000 --- a/server/src/assets/styles/_utilities/sizing.css +++ /dev/null @@ -1,11 +0,0 @@ -.pc-w { - width: var(--wi); -} - -.pc-w-full { - width: 100%; -} - -.pc-h { - height: var(--h); -} diff --git a/server/src/assets/styles/_utilities/spacing.css b/server/src/assets/styles/_utilities/spacing.css deleted file mode 100644 index 0a46a701..00000000 --- a/server/src/assets/styles/_utilities/spacing.css +++ /dev/null @@ -1,23 +0,0 @@ -.pc-m { - margin: var(--m); -} - -.pc-mt { - margin-top: var(--mt); -} - -.pc-mb { - margin-bottom: var(--mb); -} - -.pc-ml { - margin-left: var(--ml); -} - -.pc-p { - padding: var(--p); -} - -.pc-p-block { - padding-block: var(--p-block); -} diff --git a/server/src/assets/styles/_utilities/z-index.css b/server/src/assets/styles/_utilities/z-index.css deleted file mode 100644 index b170c834..00000000 --- a/server/src/assets/styles/_utilities/z-index.css +++ /dev/null @@ -1,3 +0,0 @@ -.pc-z-index { - z-index: var(--z); -} diff --git a/server/src/assets/styles/_blocks/badge.css b/server/src/assets/styles/components/badge.css similarity index 100% rename from server/src/assets/styles/_blocks/badge.css rename to server/src/assets/styles/components/badge.css diff --git a/server/src/assets/styles/_blocks/brand.css b/server/src/assets/styles/components/brand.css similarity index 100% rename from server/src/assets/styles/_blocks/brand.css rename to server/src/assets/styles/components/brand.css diff --git a/server/src/assets/styles/components/breadcrumb.css b/server/src/assets/styles/components/breadcrumb.css new file mode 100644 index 00000000..2ad0fe9d --- /dev/null +++ b/server/src/assets/styles/components/breadcrumb.css @@ -0,0 +1,13 @@ +nav.pc-breadcrumb { + color: var(--text-muted); + margin-bottom: calc(4 * var(--w)); +} + +.pc-breadcrumb li:not(:first-child)::before { + content: '/'; + margin-inline: var(--w); +} + +.pc-breadcrumb a { + font-weight: var(--font-weight-md); +} diff --git a/server/src/assets/styles/_blocks/button.css b/server/src/assets/styles/components/button.css similarity index 86% rename from server/src/assets/styles/_blocks/button.css rename to server/src/assets/styles/components/button.css index d57c0434..79a3e059 100644 --- a/server/src/assets/styles/_blocks/button.css +++ b/server/src/assets/styles/components/button.css @@ -13,7 +13,7 @@ } .pc-btn--secondary { - --hover-tint: var(--background-muted-hover); + --hover-tint: var(--background-muted); background-color: var(--background-default); color: var(--text-action-violet-on-background-default); } @@ -33,6 +33,8 @@ .pc-btn--circle { border-radius: 50%; padding: 0; + width: var(--button-size, calc(4 * var(--w))); + height: var(--button-size, calc(4 * var(--w))); display: grid; place-items: center; } diff --git a/server/src/assets/styles/_blocks/box.css b/server/src/assets/styles/components/card.css similarity index 58% rename from server/src/assets/styles/_blocks/box.css rename to server/src/assets/styles/components/card.css index 4d3a64d2..f7344f33 100644 --- a/server/src/assets/styles/_blocks/box.css +++ b/server/src/assets/styles/components/card.css @@ -1,5 +1,4 @@ -.pc-box { +.pc-card { background-color: var(--background-default); box-shadow: var(--shadow-default); - padding: var(--box-padding, calc(3 * var(--w))); } diff --git a/server/src/assets/styles/_blocks/dropdown.css b/server/src/assets/styles/components/dropdown.css similarity index 100% rename from server/src/assets/styles/_blocks/dropdown.css rename to server/src/assets/styles/components/dropdown.css diff --git a/server/src/assets/styles/_blocks/icon.css b/server/src/assets/styles/components/icon.css similarity index 100% rename from server/src/assets/styles/_blocks/icon.css rename to server/src/assets/styles/components/icon.css diff --git a/server/src/assets/styles/_blocks/index.css b/server/src/assets/styles/components/index.css similarity index 93% rename from server/src/assets/styles/_blocks/index.css rename to server/src/assets/styles/components/index.css index f5a3047d..c764181d 100644 --- a/server/src/assets/styles/_blocks/index.css +++ b/server/src/assets/styles/components/index.css @@ -1,8 +1,8 @@ @import './badge.css'; -@import './box.css'; @import './brand.css'; @import './breadcrumb.css'; @import './button.css'; +@import './card.css'; @import './dropdown.css'; @import './icon.css'; @import './input-group.css'; diff --git a/server/src/assets/styles/_blocks/input-group.css b/server/src/assets/styles/components/input-group.css similarity index 100% rename from server/src/assets/styles/_blocks/input-group.css rename to server/src/assets/styles/components/input-group.css diff --git a/server/src/assets/styles/_blocks/label.css b/server/src/assets/styles/components/label.css similarity index 100% rename from server/src/assets/styles/_blocks/label.css rename to server/src/assets/styles/components/label.css diff --git a/server/src/assets/styles/_blocks/link.css b/server/src/assets/styles/components/link.css similarity index 100% rename from server/src/assets/styles/_blocks/link.css rename to server/src/assets/styles/components/link.css diff --git a/server/src/assets/styles/_blocks/nav.css b/server/src/assets/styles/components/nav.css similarity index 100% rename from server/src/assets/styles/_blocks/nav.css rename to server/src/assets/styles/components/nav.css diff --git a/server/src/assets/styles/_blocks/select-group.css b/server/src/assets/styles/components/select-group.css similarity index 100% rename from server/src/assets/styles/_blocks/select-group.css rename to server/src/assets/styles/components/select-group.css diff --git a/server/src/assets/styles/_blocks/table.css b/server/src/assets/styles/components/table.css similarity index 100% rename from server/src/assets/styles/_blocks/table.css rename to server/src/assets/styles/components/table.css diff --git a/server/src/assets/styles/_blocks/theme.css b/server/src/assets/styles/components/theme.css similarity index 100% rename from server/src/assets/styles/_blocks/theme.css rename to server/src/assets/styles/components/theme.css diff --git a/server/src/assets/styles/_defaults.css b/server/src/assets/styles/defaults.css similarity index 92% rename from server/src/assets/styles/_defaults.css rename to server/src/assets/styles/defaults.css index 89adfd83..f8d9bc36 100644 --- a/server/src/assets/styles/_defaults.css +++ b/server/src/assets/styles/defaults.css @@ -24,10 +24,6 @@ h2 { line-height: 2rem; } -main { - overflow-y: auto; -} - p { font-size: 1rem; margin: var(--text-spacing); diff --git a/server/src/assets/styles/_layouts/app.css b/server/src/assets/styles/layouts/app.css similarity index 61% rename from server/src/assets/styles/_layouts/app.css rename to server/src/assets/styles/layouts/app.css index 02015255..d56e8602 100644 --- a/server/src/assets/styles/_layouts/app.css +++ b/server/src/assets/styles/layouts/app.css @@ -1,15 +1,19 @@ body.pc-app { position: relative; + /* Ensure content fills entire screen height */ display: flex; flex-direction: column; - /* Make it fill entire screen height */ min-height: 100vh; } /* Stretch main div and its children to fill entire screen height too */ -body.pc-app > :last-child { +.pc-app > :last-child { flex-grow: 1; } -body.pc-app > :last-child > * { +.pc-app > :last-child > * { align-self: stretch; } + +.pc-app main { + overflow-y: auto; +} diff --git a/server/src/assets/styles/layouts/box.css b/server/src/assets/styles/layouts/box.css new file mode 100644 index 00000000..2853197e --- /dev/null +++ b/server/src/assets/styles/layouts/box.css @@ -0,0 +1,3 @@ +.pc-box { + padding: var(--box-padding, calc(3 * var(--w))); +} diff --git a/server/src/assets/styles/_layouts/cluster.css b/server/src/assets/styles/layouts/cluster.css similarity index 100% rename from server/src/assets/styles/_layouts/cluster.css rename to server/src/assets/styles/layouts/cluster.css diff --git a/server/src/assets/styles/_utilities/container.css b/server/src/assets/styles/layouts/container.css similarity index 100% rename from server/src/assets/styles/_utilities/container.css rename to server/src/assets/styles/layouts/container.css diff --git a/server/src/assets/styles/_utilities/grid.css b/server/src/assets/styles/layouts/grid.css similarity index 100% rename from server/src/assets/styles/_utilities/grid.css rename to server/src/assets/styles/layouts/grid.css diff --git a/server/src/assets/styles/_layouts/index.css b/server/src/assets/styles/layouts/index.css similarity index 57% rename from server/src/assets/styles/_layouts/index.css rename to server/src/assets/styles/layouts/index.css index 31613fb6..ae7f7bb1 100644 --- a/server/src/assets/styles/_layouts/index.css +++ b/server/src/assets/styles/layouts/index.css @@ -1,4 +1,7 @@ @import './app.css'; +@import './box.css'; +@import './container.css'; +@import './grid.css'; @import './cluster.css'; @import './sidebar.css'; @import './stack.css'; diff --git a/server/src/assets/styles/_layouts/sidebar.css b/server/src/assets/styles/layouts/sidebar.css similarity index 100% rename from server/src/assets/styles/_layouts/sidebar.css rename to server/src/assets/styles/layouts/sidebar.css diff --git a/server/src/assets/styles/_layouts/stack.css b/server/src/assets/styles/layouts/stack.css similarity index 100% rename from server/src/assets/styles/_layouts/stack.css rename to server/src/assets/styles/layouts/stack.css diff --git a/server/src/assets/styles/main.css b/server/src/assets/styles/main.css index 94070ac4..786d53ce 100644 --- a/server/src/assets/styles/main.css +++ b/server/src/assets/styles/main.css @@ -1,7 +1,7 @@ -@import './_variables.css'; -@import './_reset.css'; -@import './_defaults.css'; -@import './_layouts/index.css'; -@import './_blocks/index.css'; -@import './_utilities/index.css'; -@import './_overrides.css'; +@import './variables.css'; +@import './reset.css'; +@import './defaults.css'; +@import './layouts/index.css'; +@import './components/index.css'; +@import './utilities/index.css'; +@import './overrides.css'; diff --git a/server/src/assets/styles/_overrides.css b/server/src/assets/styles/overrides.css similarity index 100% rename from server/src/assets/styles/_overrides.css rename to server/src/assets/styles/overrides.css diff --git a/server/src/assets/styles/_reset.css b/server/src/assets/styles/reset.css similarity index 100% rename from server/src/assets/styles/_reset.css rename to server/src/assets/styles/reset.css diff --git a/server/src/assets/styles/_utilities/background.css b/server/src/assets/styles/utilities/background.css similarity index 100% rename from server/src/assets/styles/_utilities/background.css rename to server/src/assets/styles/utilities/background.css diff --git a/server/src/assets/styles/_utilities/gap.css b/server/src/assets/styles/utilities/gap.css similarity index 100% rename from server/src/assets/styles/_utilities/gap.css rename to server/src/assets/styles/utilities/gap.css diff --git a/server/src/assets/styles/_utilities/index.css b/server/src/assets/styles/utilities/index.css similarity index 50% rename from server/src/assets/styles/_utilities/index.css rename to server/src/assets/styles/utilities/index.css index 40530e6b..eba6543a 100644 --- a/server/src/assets/styles/_utilities/index.css +++ b/server/src/assets/styles/utilities/index.css @@ -1,14 +1,7 @@ @import './background.css'; -@import './border.css'; -@import './container.css'; -@import './flex.css'; @import './gap.css'; -@import './grid.css'; @import './list.css'; @import './placement.css'; -@import './row.css'; @import './shadow.css'; -@import './sizing.css'; @import './spacing.css'; @import './text.css'; -@import './z-index.css'; diff --git a/server/src/assets/styles/_utilities/list.css b/server/src/assets/styles/utilities/list.css similarity index 100% rename from server/src/assets/styles/_utilities/list.css rename to server/src/assets/styles/utilities/list.css diff --git a/server/src/assets/styles/_utilities/placement.css b/server/src/assets/styles/utilities/placement.css similarity index 74% rename from server/src/assets/styles/_utilities/placement.css rename to server/src/assets/styles/utilities/placement.css index 23bceedc..a57a0bf4 100644 --- a/server/src/assets/styles/_utilities/placement.css +++ b/server/src/assets/styles/utilities/placement.css @@ -3,6 +3,10 @@ place-items: center; } +.pc-h-full { + height: 100vh; +} + .pc-relative { position: relative; } diff --git a/server/src/assets/styles/utilities/shadow.css b/server/src/assets/styles/utilities/shadow.css new file mode 100644 index 00000000..69e1aee0 --- /dev/null +++ b/server/src/assets/styles/utilities/shadow.css @@ -0,0 +1,3 @@ +.pc-shadow { + box-shadow: var(--shadow-default); +} diff --git a/server/src/assets/styles/utilities/spacing.css b/server/src/assets/styles/utilities/spacing.css new file mode 100644 index 00000000..a4c7b687 --- /dev/null +++ b/server/src/assets/styles/utilities/spacing.css @@ -0,0 +1,7 @@ +.pc-m { + margin: var(--m); +} + +.pc-p { + padding: var(--p); +} diff --git a/server/src/assets/styles/_utilities/text.css b/server/src/assets/styles/utilities/text.css similarity index 100% rename from server/src/assets/styles/_utilities/text.css rename to server/src/assets/styles/utilities/text.css diff --git a/server/src/assets/styles/_variables.css b/server/src/assets/styles/variables.css similarity index 100% rename from server/src/assets/styles/_variables.css rename to server/src/assets/styles/variables.css diff --git a/server/src/templates/components/header.njk b/server/src/templates/components/header.njk index 639bd844..e0df06d7 100644 --- a/server/src/templates/components/header.njk +++ b/server/src/templates/components/header.njk @@ -1,6 +1,6 @@ {% import 'macros/icons.njk' as icons %} -
    +
    @@ -14,7 +14,7 @@ {% include 'components/theme_toggler.njk' %}
    - + {{ req.user.firstName|first|capitalize }} diff --git a/server/src/templates/components/theme_toggler.njk b/server/src/templates/components/theme_toggler.njk index ca1168f0..cbd0cd19 100644 --- a/server/src/templates/components/theme_toggler.njk +++ b/server/src/templates/components/theme_toggler.njk @@ -1,6 +1,6 @@ {% import 'macros/icons.njk' as icons %} -
      -
    1. - +