From 7e1f2efd8888d90b18e8ed2172dcc20d065c9965 Mon Sep 17 00:00:00 2001 From: John Bledsoe <59550+johnbcodes@users.noreply.github.com> Date: Thu, 8 Feb 2024 14:53:33 -0500 Subject: [PATCH 1/2] chore(deps): Update JS depedencies.. include new directive to work around https://github.com/parcel-bundler/watcher/issues/156 --- package-lock.json | 2252 +++++++++++++++++++++++++-------------------- package.json | 11 +- 2 files changed, 1285 insertions(+), 978 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8bd690..f1e4141 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,11 @@ "name": "rust-quote-editor", "version": "0.1.0", "devDependencies": { - "@hotwired/stimulus": "3.2.2", - "@hotwired/turbo": "7.3.0", - "htmx.org": "1.9.9", - "hyperscript.org": "0.9.12", + "htmx.org": "1.9", + "hyperscript.org": "0.9", "npm-run-all": "4.1.5", - "parcel": "2.10.2", - "tailwindcss": "3.3.5" + "parcel": "2.11", + "tailwindcss": "3.4" } }, "node_modules/@alloc/quick-lru": { @@ -65,19 +63,71 @@ "node": ">=6.9.0" } }, - "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/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, - "node_modules/@hotwired/turbo": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@hotwired/turbo/-/turbo-7.3.0.tgz", - "integrity": "sha512-Dcu+NaSvHLT7EjrDrkEmH4qET2ZJZ5IcCWmNXxNQTBwlnE5tBZfN6WxZ842n5cHV52DH/AKNirbPBtcEXDLW4g==", + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">= 14" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/@jridgewell/gen-mapping": { @@ -129,9 +179,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -139,15 +189,15 @@ } }, "node_modules/@lezer/common": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.1.1.tgz", - "integrity": "sha512-aAPB9YbvZHqAW+bIwiuuTDGB4DG0sYNRObGLxud8cW7osw1ZQxfDuTZ8KQiqfZ0QJGcR34CvpTMDXEyo/+Htgg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", + "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==", "dev": true }, "node_modules/@lezer/lr": { - "version": "1.3.14", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.14.tgz", - "integrity": "sha512-z5mY4LStlA3yL7aHT/rqgG614cfcvklS+8oFRFBYrs4YaWLJyKKM4+nN6KopToX0o9Hj6zmH6M5kinOYuy06ug==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz", + "integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==", "dev": true, "dependencies": { "@lezer/common": "^1.0.0" @@ -359,21 +409,21 @@ } }, "node_modules/@parcel/bundler-default": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.10.2.tgz", - "integrity": "sha512-XlVGsScK5PgIFXNJ0Yx/+nHu1RFCuslCbrb8MIs0yqS790yzvyJF2QHX5WAr7Qc5powij/+2tfBHiViauWwVpA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.11.0.tgz", + "integrity": "sha512-ZIs0865Lp871ZK83k5I9L4DeeE26muNMrHa7j8bvls6fKBJKAn8djrhfU4XOLyziU4aAOobcPwXU0+npWqs52g==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/graph": "3.0.2", - "@parcel/plugin": "2.10.2", - "@parcel/rust": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/graph": "3.1.0", + "@parcel/plugin": "2.11.0", + "@parcel/rust": "2.11.0", + "@parcel/utils": "2.11.0", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -381,14 +431,14 @@ } }, "node_modules/@parcel/cache": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.10.2.tgz", - "integrity": "sha512-B69e5n+bBzYoaJdUOviYeUT7N1iXI3IC5G8dAxKNZ9Zgn+pjZ5BwltbfmP47+NTfQ7LqM8Ea4UJxysQsLdwb+Q==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.11.0.tgz", + "integrity": "sha512-RSSkGNjO00lJPyftzaC9eaNVs4jMjPSAm0VJNWQ9JSm2n4A9BzQtTFAt1vhJOzzW1UsQvvBge9DdfkB7a2gIOw==", "dev": true, "dependencies": { - "@parcel/fs": "2.10.2", - "@parcel/logger": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/fs": "2.11.0", + "@parcel/logger": "2.11.0", + "@parcel/utils": "2.11.0", "lmdb": "2.8.5" }, "engines": { @@ -399,13 +449,13 @@ "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.10.2" + "@parcel/core": "^2.11.0" } }, "node_modules/@parcel/codeframe": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.10.2.tgz", - "integrity": "sha512-EZrYSIlVg4qiBLHRRqC/BGN2MLG0SKnw4u7kpviwz63I+v36ghqmHGOomwfn4x13nDL+EgOFz4/+Q7QpbMTKug==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.11.0.tgz", + "integrity": "sha512-YHs9g/i5af/sd/JrWAojU9YFbKffcJ3Tx2EJaK0ME8OJsye91UaI/3lxSUYLmJG9e4WLNJtqci8V5FBMz//ZPg==", "dev": true, "dependencies": { "chalk": "^4.1.0" @@ -489,16 +539,16 @@ } }, "node_modules/@parcel/compressor-raw": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.10.2.tgz", - "integrity": "sha512-zIbtmL7vGfWkvBwD29zVdDosFR1eKHa29SpPOQXYLmDO0EVdwzYcTQq2OrlZM07o759QUqwXJfuAYxwcBNRTYg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.11.0.tgz", + "integrity": "sha512-RArhBPRTCfz77soX2IECH09NUd76UBWujXiPRcXGPIHK+C3L1cRuzsNcA39QeSb3thz3b99JcozMJ1nkC2Bsgw==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2" + "@parcel/plugin": "2.11.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -506,72 +556,72 @@ } }, "node_modules/@parcel/config-default": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.10.2.tgz", - "integrity": "sha512-BGn7G5MT6VXpnI5Rj8fzHT1ij0YElge3l2KVGSOJ5crho2Fmz7UKmm8kJ9kdcLrzHWOIH07T100YoQuAwKVQaA==", - "dev": true, - "dependencies": { - "@parcel/bundler-default": "2.10.2", - "@parcel/compressor-raw": "2.10.2", - "@parcel/namer-default": "2.10.2", - "@parcel/optimizer-css": "2.10.2", - "@parcel/optimizer-htmlnano": "2.10.2", - "@parcel/optimizer-image": "2.10.2", - "@parcel/optimizer-svgo": "2.10.2", - "@parcel/optimizer-swc": "2.10.2", - "@parcel/packager-css": "2.10.2", - "@parcel/packager-html": "2.10.2", - "@parcel/packager-js": "2.10.2", - "@parcel/packager-raw": "2.10.2", - "@parcel/packager-svg": "2.10.2", - "@parcel/packager-wasm": "2.10.2", - "@parcel/reporter-dev-server": "2.10.2", - "@parcel/resolver-default": "2.10.2", - "@parcel/runtime-browser-hmr": "2.10.2", - "@parcel/runtime-js": "2.10.2", - "@parcel/runtime-react-refresh": "2.10.2", - "@parcel/runtime-service-worker": "2.10.2", - "@parcel/transformer-babel": "2.10.2", - "@parcel/transformer-css": "2.10.2", - "@parcel/transformer-html": "2.10.2", - "@parcel/transformer-image": "2.10.2", - "@parcel/transformer-js": "2.10.2", - "@parcel/transformer-json": "2.10.2", - "@parcel/transformer-postcss": "2.10.2", - "@parcel/transformer-posthtml": "2.10.2", - "@parcel/transformer-raw": "2.10.2", - "@parcel/transformer-react-refresh-wrap": "2.10.2", - "@parcel/transformer-svg": "2.10.2" + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.11.0.tgz", + "integrity": "sha512-1e2+qcZkm5/0f4eI20p/DemcYiSxq9d/eyjpTXA7PulJaHbL1wonwUAuy3mvnAvDnLOJmAk/obDVgX1ZfxMGtg==", + "dev": true, + "dependencies": { + "@parcel/bundler-default": "2.11.0", + "@parcel/compressor-raw": "2.11.0", + "@parcel/namer-default": "2.11.0", + "@parcel/optimizer-css": "2.11.0", + "@parcel/optimizer-htmlnano": "2.11.0", + "@parcel/optimizer-image": "2.11.0", + "@parcel/optimizer-svgo": "2.11.0", + "@parcel/optimizer-swc": "2.11.0", + "@parcel/packager-css": "2.11.0", + "@parcel/packager-html": "2.11.0", + "@parcel/packager-js": "2.11.0", + "@parcel/packager-raw": "2.11.0", + "@parcel/packager-svg": "2.11.0", + "@parcel/packager-wasm": "2.11.0", + "@parcel/reporter-dev-server": "2.11.0", + "@parcel/resolver-default": "2.11.0", + "@parcel/runtime-browser-hmr": "2.11.0", + "@parcel/runtime-js": "2.11.0", + "@parcel/runtime-react-refresh": "2.11.0", + "@parcel/runtime-service-worker": "2.11.0", + "@parcel/transformer-babel": "2.11.0", + "@parcel/transformer-css": "2.11.0", + "@parcel/transformer-html": "2.11.0", + "@parcel/transformer-image": "2.11.0", + "@parcel/transformer-js": "2.11.0", + "@parcel/transformer-json": "2.11.0", + "@parcel/transformer-postcss": "2.11.0", + "@parcel/transformer-posthtml": "2.11.0", + "@parcel/transformer-raw": "2.11.0", + "@parcel/transformer-react-refresh-wrap": "2.11.0", + "@parcel/transformer-svg": "2.11.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.10.2" + "@parcel/core": "^2.11.0" } }, "node_modules/@parcel/core": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.10.2.tgz", - "integrity": "sha512-c6hh13oYk9w5creiQ9yCz9GLQ17ZRMonULhJ46J0yoFArynVhNTJ9B5xVst7rS/chOTY8jU0jSdJuxQCR4fjkg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.11.0.tgz", + "integrity": "sha512-Npe0S6hVaqWEwRL+HI7gtOYOaoE5bJQZTgUDhsDoppWbau51jOlRYOZTXuvRK/jxXnze4/S1sdM24xBYAQ5qkw==", "dev": true, "dependencies": { "@mischnic/json-sourcemap": "^0.1.0", - "@parcel/cache": "2.10.2", - "@parcel/diagnostic": "2.10.2", - "@parcel/events": "2.10.2", - "@parcel/fs": "2.10.2", - "@parcel/graph": "3.0.2", - "@parcel/logger": "2.10.2", - "@parcel/package-manager": "2.10.2", - "@parcel/plugin": "2.10.2", - "@parcel/profiler": "2.10.2", - "@parcel/rust": "2.10.2", + "@parcel/cache": "2.11.0", + "@parcel/diagnostic": "2.11.0", + "@parcel/events": "2.11.0", + "@parcel/fs": "2.11.0", + "@parcel/graph": "3.1.0", + "@parcel/logger": "2.11.0", + "@parcel/package-manager": "2.11.0", + "@parcel/plugin": "2.11.0", + "@parcel/profiler": "2.11.0", + "@parcel/rust": "2.11.0", "@parcel/source-map": "^2.1.1", - "@parcel/types": "2.10.2", - "@parcel/utils": "2.10.2", - "@parcel/workers": "2.10.2", + "@parcel/types": "2.11.0", + "@parcel/utils": "2.11.0", + "@parcel/workers": "2.11.0", "abortcontroller-polyfill": "^1.1.9", "base-x": "^3.0.8", "browserslist": "^4.6.6", @@ -579,7 +629,7 @@ "dotenv": "^7.0.0", "dotenv-expand": "^5.1.0", "json5": "^2.2.0", - "msgpackr": "^1.5.4", + "msgpackr": "^1.9.9", "nullthrows": "^1.1.1", "semver": "^7.5.2" }, @@ -591,10 +641,22 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/core/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/@parcel/core/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -607,9 +669,9 @@ } }, "node_modules/@parcel/diagnostic": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.10.2.tgz", - "integrity": "sha512-FwtphyiV/TJEiYIRYXBOloXp7XhTW37ifRSLr7RdLbDVyn/P9q/7l0+ORlnOL+WuKwbDQtY+dXYLh/ijTsq7qQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.11.0.tgz", + "integrity": "sha512-4dJmOXVL5YGGQRRsQosQbSRONBcboB71mSwaeaEgz3pPdq9QXVPLACkGe/jTXSqa3OnAHu3g5vQLpE1g5xqBqw==", "dev": true, "dependencies": { "@mischnic/json-sourcemap": "^0.1.0", @@ -624,9 +686,9 @@ } }, "node_modules/@parcel/events": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.10.2.tgz", - "integrity": "sha512-Dp8Oqh5UvSuIASfiHP8jrEtdtzzmTKiOG/RkSL3mtp2tK3mu6dZLJZbcdJXrvBTg7smtRiznkrIOJCawALC7AQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.11.0.tgz", + "integrity": "sha512-K6SOjOrQsz1GdNl2qKBktq7KJ3Q3yxK8WXdmQYo10wG39dr051xtMb38aqieTp4eVhL8Yaq2iJgGkdr11fuBnA==", "dev": true, "engines": { "node": ">= 12.0.0" @@ -637,16 +699,16 @@ } }, "node_modules/@parcel/fs": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.10.2.tgz", - "integrity": "sha512-80SXdFGDJtil9tTbWrYiZRfQ5ehMAT/dq6eY4EYcFg+MvSiwBL/4GfYMfqXn6AamuSVeQlsFCPpunFLNl9YDDA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.11.0.tgz", + "integrity": "sha512-zWckdnnovdrgdFX4QYuQV4bbKCsh6IYCkmwaB4yp47rhw1MP0lkBINLt4yFPHBxWXOpElCfxjL+z69c9xJQRBQ==", "dev": true, "dependencies": { - "@parcel/rust": "2.10.2", - "@parcel/types": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/rust": "2.11.0", + "@parcel/types": "2.11.0", + "@parcel/utils": "2.11.0", "@parcel/watcher": "^2.0.7", - "@parcel/workers": "2.10.2" + "@parcel/workers": "2.11.0" }, "engines": { "node": ">= 12.0.0" @@ -656,13 +718,13 @@ "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.10.2" + "@parcel/core": "^2.11.0" } }, "node_modules/@parcel/graph": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-3.0.2.tgz", - "integrity": "sha512-cPxCN3+QF+5l4BJ0wnLeb3DPJarWQoD3W984CfuEYy/8Zgo2oayd31soZzkevyTYtp7H4tJKo+I79i2TJdNq5Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-3.1.0.tgz", + "integrity": "sha512-d1dTW5C7A52HgDtoXlyvlET1ypSlmIxSIZOJ1xp3R9L9hgo3h1u3jHNyaoTe/WPkGVe2QnFxh0h+UibVJhu9vg==", "dev": true, "dependencies": { "nullthrows": "^1.1.1" @@ -676,13 +738,13 @@ } }, "node_modules/@parcel/logger": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.10.2.tgz", - "integrity": "sha512-5lufBuBnXDs3hjAaptmeEAxpH0eHe0+2hJvlVv5lE/RwHR7vDjh+FDwzPfCLWNM3TQhPQdZPdHcDsuA539GHcw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.11.0.tgz", + "integrity": "sha512-HtMEdCq3LKnvv4T2CIskcqlf2gpBvHMm3pkeUFB/hc/7hW/hE1k6/HA2VOQvc0tBsaMpmEx7PCrfrH56usQSyA==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/events": "2.10.2" + "@parcel/diagnostic": "2.11.0", + "@parcel/events": "2.11.0" }, "engines": { "node": ">= 12.0.0" @@ -693,9 +755,9 @@ } }, "node_modules/@parcel/markdown-ansi": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.10.2.tgz", - "integrity": "sha512-uZrysHjJ+0vbQNK2bhKy8yoVso8KnoW6O/SW8MiGQ4lpDJdqHShkW08wZUKr4sjl7h/WVFdNsDdgvi2/ANwoRQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.11.0.tgz", + "integrity": "sha512-YA60EWbXi6cLOIzcwRC2wijotPauOGQbUi0vSbu0O6/mjQ68kWCMGz0hwZjDRQcPypQVJEIvTgMymLbvumxwhg==", "dev": true, "dependencies": { "chalk": "^4.1.0" @@ -779,18 +841,18 @@ } }, "node_modules/@parcel/namer-default": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.10.2.tgz", - "integrity": "sha512-wjn3MCus0w9IOjCtQsp5fgb8hgITyxMr0OPF9cBVAhVJI1X9vvd4RurHuLJ3MjvlCqrP1en09yg3ME7VO1kPuA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.11.0.tgz", + "integrity": "sha512-DEwBSKSClg4DA2xAWimYkw9bFi7MFb9TdT7/TYZStMTsfYHPWOyyjGR7aVr3Ra4wNb+XX6g4rR41yp3HD6KO7A==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -798,16 +860,16 @@ } }, "node_modules/@parcel/node-resolver-core": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-3.1.2.tgz", - "integrity": "sha512-xvIBgYBRQGmCkfwK/yxVSDtPEvWDVH9poQcGpKHT1jqstYju5crXro0acni5nYF0hWZu7Kttrp9G9fXJQWBksw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-3.2.0.tgz", + "integrity": "sha512-XJRSxCkNbGFWjfmwFdcQZ/qlzWZd35qLtvLz2va8euGL7M5OMEQOv7dsvEhl0R+CC2zcnfFzZwxk78q6ezs8AQ==", "dev": true, "dependencies": { "@mischnic/json-sourcemap": "^0.1.0", - "@parcel/diagnostic": "2.10.2", - "@parcel/fs": "2.10.2", - "@parcel/rust": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/fs": "2.11.0", + "@parcel/rust": "2.11.0", + "@parcel/utils": "2.11.0", "nullthrows": "^1.1.1", "semver": "^7.5.2" }, @@ -819,10 +881,22 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/node-resolver-core/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/@parcel/node-resolver-core/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -835,22 +909,22 @@ } }, "node_modules/@parcel/optimizer-css": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.10.2.tgz", - "integrity": "sha512-05H/Ng90TErSFZkNaUwi7gNCf2gLWi3/w07oIzHu1wjRjjKjZidqaQqZtHTEYoO9ffmhK14Xwh9q4IpOTa0sbQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.11.0.tgz", + "integrity": "sha512-bV97PRxshHV3dMwOpLRgcP1QNhrVWh6VVDfm2gmWULpvsjoykcPS6vrCFksY5CpQsSvNHqJBzQjWS8FubUI76w==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.10.2", + "@parcel/utils": "2.11.0", "browserslist": "^4.6.6", - "lightningcss": "^1.16.1", + "lightningcss": "^1.22.1", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -858,12 +932,12 @@ } }, "node_modules/@parcel/optimizer-htmlnano": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.10.2.tgz", - "integrity": "sha512-9Sg2xLsfX7CPLd1AO3uVa/Kh9EROKVNHMnmNxlzmO2+LEOU/M1OHalvt4bhC7I+cNFPLN5BePdBv3QMYpO0yyA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.11.0.tgz", + "integrity": "sha512-c20pz4EFF5DNFmqYgptlIj49eT6xjGLkDTdHH3RRzxKovuSXWfYSPs3GED3ZsjVuQyjNQif+/MAk9547F7hrdQ==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", + "@parcel/plugin": "2.11.0", "htmlnano": "^2.0.0", "nullthrows": "^1.1.1", "posthtml": "^0.16.5", @@ -871,7 +945,7 @@ }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -947,43 +1021,43 @@ } }, "node_modules/@parcel/optimizer-image": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.10.2.tgz", - "integrity": "sha512-X8q7mvWJEIXsEMYHYKbwIRUJvI0W41YWCEW7Ohmn0SSi+KuiO8BW5JEPKs7HboO9bX+i6Yxa/T1h9HgRXhdUug==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.11.0.tgz", + "integrity": "sha512-jCaJww5QFG2GuNzYW8nlSW+Ea+Cv47TRnOPJNquFIajgfTLJ5ddsWbaNal0GQsL8yNiCBKWd1AV4W0RH9tG0Jg==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", - "@parcel/rust": "2.10.2", - "@parcel/utils": "2.10.2", - "@parcel/workers": "2.10.2" + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", + "@parcel/rust": "2.11.0", + "@parcel/utils": "2.11.0", + "@parcel/workers": "2.11.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.10.2" + "@parcel/core": "^2.11.0" } }, "node_modules/@parcel/optimizer-svgo": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.10.2.tgz", - "integrity": "sha512-Ws+xd6nbetMCZHmRj54tIF8wYuu/JwkEvn5BotLE69l3naf2ELtsQ+PHg9G5jUa+PnSNMHhykIhBOqjxhTeq/w==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.11.0.tgz", + "integrity": "sha512-TQpvfBhjV2IsuFHXUolbDS6XWB3DDR2rYTlqlA8LMmuOY7jQd9Bnkl4JnapzWm/bRuzRlzdGjjVCPGL8iShFvA==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0", "svgo": "^2.4.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1059,21 +1133,21 @@ } }, "node_modules/@parcel/optimizer-swc": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-swc/-/optimizer-swc-2.10.2.tgz", - "integrity": "sha512-/4yMgMgLvF4yCHh0QnZlTUTpKobuFK/lNhB1i5yrtiipRaYcS+OgtakB83grfK+x1KwTbYjzXZBILwqu6GKJDQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-swc/-/optimizer-swc-2.11.0.tgz", + "integrity": "sha512-ftf42F3JyZxJb6nnLlgNGyNQ273YOla4dFGH/tWC8iTwObHUpWe7cMbCGcrSJBvAlsLkZfLpFNAXFxUgxdKyHQ==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.10.2", + "@parcel/utils": "2.11.0", "@swc/core": "^1.3.36", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1081,18 +1155,18 @@ } }, "node_modules/@parcel/package-manager": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.10.2.tgz", - "integrity": "sha512-c91YYsIxjX3YhMvtPT7v2MpDOn/Qyw13bi1+0Ftd2JNjUZPlm8+xKizlmgvdi75dgs7dGIUVpvrGLU9LoKthCA==", - "dev": true, - "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/fs": "2.10.2", - "@parcel/logger": "2.10.2", - "@parcel/node-resolver-core": "3.1.2", - "@parcel/types": "2.10.2", - "@parcel/utils": "2.10.2", - "@parcel/workers": "2.10.2", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.11.0.tgz", + "integrity": "sha512-QzdsrUYlAwIzb8by7WJjqYnbR1MoMKWbtE1MXUeYsZbFusV8B6pOH+lwqNJKS/BFtddZMRPYFueZS2N2fwzjig==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.11.0", + "@parcel/fs": "2.11.0", + "@parcel/logger": "2.11.0", + "@parcel/node-resolver-core": "3.2.0", + "@parcel/types": "2.11.0", + "@parcel/utils": "2.11.0", + "@parcel/workers": "2.11.0", "semver": "^7.5.2" }, "engines": { @@ -1103,13 +1177,25 @@ "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.10.2" + "@parcel/core": "^2.11.0" + } + }, + "node_modules/@parcel/package-manager/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/@parcel/package-manager/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1122,20 +1208,20 @@ } }, "node_modules/@parcel/packager-css": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.10.2.tgz", - "integrity": "sha512-+X4dV7mBdOhXSHeg5gAkk0Qju6A1oezYIancqDC17zoFzbHUfD13nHNDOXrEfMNFVWy93lB8vLJwchH54MDMwQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.11.0.tgz", + "integrity": "sha512-AyIxsp4eL8c22vp2oO2hSRnr3hSVNkARNZc9DG6uXxCc2Is5tUEX0I4PwxWnAx0EI44l+3zX/o414zT8yV9wwQ==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.10.2", + "@parcel/utils": "2.11.0", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1143,20 +1229,20 @@ } }, "node_modules/@parcel/packager-html": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.10.2.tgz", - "integrity": "sha512-GonfLzuzEkelJde89sq9P9LowLJrFNkuEt33nRokc1Q5TPNOWfTYb6difjuVIMr/j0c4nWlOzUrkGJsyo++F7w==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.11.0.tgz", + "integrity": "sha512-ho5AQ70naTV8IqkKIbKtK+jsXQ5TJfFgtBvmJlyB3YydRMbIc+3g4G0xgIvf15V4uCMw9Md0Sv1W65nQXHPQoA==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/types": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/plugin": "2.11.0", + "@parcel/types": "2.11.0", + "@parcel/utils": "2.11.0", "nullthrows": "^1.1.1", "posthtml": "^0.16.5" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1164,23 +1250,23 @@ } }, "node_modules/@parcel/packager-js": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.10.2.tgz", - "integrity": "sha512-SgKJqIvMt+UJM0x3F21yBVsgdHbTnOnBrNJ7VoY3nujQX5fa+pxTf0emWuX1vSUDbBaJOmO/pC9rKwWP5enqfQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.11.0.tgz", + "integrity": "sha512-SxjCsd0xQfg5H73YtVJj9VOpr9s0rwMsSoeykjkatbkEla9NsZajsUkd/bfYf+/0WvEKOrB8oUBo15HkGOgKug==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", - "@parcel/rust": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", + "@parcel/rust": "2.11.0", "@parcel/source-map": "^2.1.1", - "@parcel/types": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/types": "2.11.0", + "@parcel/utils": "2.11.0", "globals": "^13.2.0", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1188,16 +1274,16 @@ } }, "node_modules/@parcel/packager-raw": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.10.2.tgz", - "integrity": "sha512-+/O2DeMIB9d+1+zCPOkaf2aTl2rN5TFod/UcMzG/HGFlDVqhkV9xgfwV4rV+Vso5TlyHA4p53BFgvGWQBQJAQw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.11.0.tgz", + "integrity": "sha512-2/0JQ8DZrz7cVNXwD6OYoUUtSSnlr4dsz8ZkpFDKsBJhvMHtC78Sq+1EDixDGOMiUcalSEjNsoHtkpq9uNh+Xw==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2" + "@parcel/plugin": "2.11.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1205,19 +1291,19 @@ } }, "node_modules/@parcel/packager-svg": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.10.2.tgz", - "integrity": "sha512-eQx3VJpuuDcen+DcLxlPn95txlnbpEH8TES+Ezym/LFyD8oQQfok/VFHy/iGoG4r1CtH0/c7lFUJE8+LZdwYmQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.11.0.tgz", + "integrity": "sha512-2wQBkzLwcaWFGWz8TP+bgsXgiueWPzrjKsWugWdDfq0FbXh8XVeR/599qnus3RFHZy4cH6L6yq/7zxcljtxK8A==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/types": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/plugin": "2.11.0", + "@parcel/types": "2.11.0", + "@parcel/utils": "2.11.0", "posthtml": "^0.16.4" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1225,16 +1311,16 @@ } }, "node_modules/@parcel/packager-wasm": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.10.2.tgz", - "integrity": "sha512-Y/UyyOePb3WmWy2WtmXn4QLLrb7wjWL/ZhVgvhFiQft4lCbdGBGz1BiKEzhFkkN2IGdX06XZolmKCQieAM6zlQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.11.0.tgz", + "integrity": "sha512-tTy4EbDXeeiZ0oB7L2FWaHSD1mbmYZP6R5HXqkvc5dECGUKPU5Jz6ek2C5AM+HfQdQLKXPQ/Xw3eJnI/AmctVg==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2" + "@parcel/plugin": "2.11.0" }, "engines": { "node": ">=12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1242,12 +1328,12 @@ } }, "node_modules/@parcel/plugin": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.10.2.tgz", - "integrity": "sha512-1u+GJhuqqlYjMAQLBbMExfFCbsbtuSAm6wXmMmTse5cBpFqxgsMumMeztAhcTy0oMnMhbZg2AKZV0XVSMrIgng==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.11.0.tgz", + "integrity": "sha512-9npuKBlhnPn7oeUpLJGecceg16GkXbvzbr6MNSZiHhkx3IBeITHQXlZnp2zAjUOFreNsYOfifwEF2S4KsARfBQ==", "dev": true, "dependencies": { - "@parcel/types": "2.10.2" + "@parcel/types": "2.11.0" }, "engines": { "node": ">= 12.0.0" @@ -1258,13 +1344,13 @@ } }, "node_modules/@parcel/profiler": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/profiler/-/profiler-2.10.2.tgz", - "integrity": "sha512-YQugGhf12u83O0RJLWbhkPV772nePPxNZjvFJmV++7buPUpgJW2m1lVOrut/s/8ZZIPqcxJe8dyxSSOtvdG7OQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/profiler/-/profiler-2.11.0.tgz", + "integrity": "sha512-s10SS09prOdwnaAcjK8M5zO8o+zPJJW5oOqXPNdf6KH4NGD/ue7iOk2xM8QLw6ulSwxE7NDt++lyfW3AXgCZwg==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/events": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/events": "2.11.0", "chrome-trace-event": "^1.0.2" }, "engines": { @@ -1276,20 +1362,21 @@ } }, "node_modules/@parcel/reporter-cli": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.10.2.tgz", - "integrity": "sha512-6/cLuiGfMh1ny8ULNOXJkugIvJRVo4tV4XA3vJXH96SYqFSfiWxtHqb6MAVndBy8MezEAv0EsLqc7yR7ygdZJw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.11.0.tgz", + "integrity": "sha512-hY0iO0f+LifgJHDUIjGQJnxLFSkk2jlbfy+kIaft5oI3/IM+UljecfGO+14XH8mYlqRXXPsT09TJe8ZKQzp4ZQ==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/types": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/plugin": "2.11.0", + "@parcel/types": "2.11.0", + "@parcel/utils": "2.11.0", "chalk": "^4.1.0", + "cli-progress": "^3.12.0", "term-size": "^2.2.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1367,17 +1454,17 @@ } }, "node_modules/@parcel/reporter-dev-server": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.10.2.tgz", - "integrity": "sha512-mLEcZFPpw0ixlvbT846NwmPEVv1ej7H5dwCQ3r1Ca1nQjyXkmQMM06rdb5M+/gk12WVEDOuienWqBL44Xsz3NA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.11.0.tgz", + "integrity": "sha512-T4ue1+oLFNdcd9maw8QWQuxzOS2kX2jOrSvYKwYd9oGnqiAr1rpiHYYKJhHng+PF5ybwWkj8dUJfGh2NoQysJA==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2" + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1385,19 +1472,19 @@ } }, "node_modules/@parcel/reporter-tracer": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/reporter-tracer/-/reporter-tracer-2.10.2.tgz", - "integrity": "sha512-oreu3vIdN5u9ONSNhqypcK3nR91NoreR4B4vwD/1Rqod1ud2Vb9awJZv7QIrkdnEMmGcr5DQ/R872s7XYWeZnA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-tracer/-/reporter-tracer-2.11.0.tgz", + "integrity": "sha512-33q4ftO26OPWHkUpEm0bzzSjW2kHEh6q/JFePwf8W6APTQVruj4mV46+Fh6rxX42ixs92K/QoiE0gYgWZQVDHA==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0", "chrome-trace-event": "^1.0.3", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1405,17 +1492,17 @@ } }, "node_modules/@parcel/resolver-default": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.10.2.tgz", - "integrity": "sha512-ENEq8f4wRQlU7p3tCelXWK6xIsL+57q9hQ+b4eRJOEctjfN1/BguxZDh+P+fIlJ1lkqiX4UB/PUkK97uSI5XTQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.11.0.tgz", + "integrity": "sha512-suZNN2lE5W48LPTwAbG7gnj1IeubkCVEm0XspWXcXUtCzglimNJ8PVVBGx171o5CqDpdbGF3AqHjG9N3uOwXag==", "dev": true, "dependencies": { - "@parcel/node-resolver-core": "3.1.2", - "@parcel/plugin": "2.10.2" + "@parcel/node-resolver-core": "3.2.0", + "@parcel/plugin": "2.11.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1423,17 +1510,17 @@ } }, "node_modules/@parcel/runtime-browser-hmr": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.10.2.tgz", - "integrity": "sha512-ABlCzDYI16lAZLTTL2g3JZasU/dWuSzRGK5paC6JhIJJwQwPeTwu4PaUoEPKeyk0iE9PzVuXjkBbGuSLXQFmmA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.11.0.tgz", + "integrity": "sha512-uVwNBtoLMrlPHLvRS05BVhLseduMOpZT36yiIjS0YSBJcC6/otI9AY7ZiDPYmrB5xTqM0R+D554JhPaJHCuocw==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2" + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1441,19 +1528,19 @@ } }, "node_modules/@parcel/runtime-js": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.10.2.tgz", - "integrity": "sha512-a6TaMVg1Xgy+WJJ0a3sC/Taw5hkN4hmLnz00jg7G6LwoGbBpvjJn8pm4eovkMFJz13RCjmS9q0K+qZnvXh1WYA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.11.0.tgz", + "integrity": "sha512-fH3nJoexINz7s4cDzp0Vjsx0k1pMYSa5ch38LbbNqCKTermy0pS0zZuvgfLfHFFP+AMRpFQenrF7h7N3bgDmHw==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1461,19 +1548,19 @@ } }, "node_modules/@parcel/runtime-react-refresh": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.10.2.tgz", - "integrity": "sha512-9xW3g4FH9iizHWscHD2yEWJOCfYkIYMbWsZoj0EOMILqrRd1OZxHH8FbLYBQKT6swRbZI2mM19veVVBBfxco/Q==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.11.0.tgz", + "integrity": "sha512-Kfnc7gLjhoephLMnjABrkIkzVfzPrpJlxiJFIleY2Fm57YhmCfKsEYxm3lHOutNaYl1VArW0LKClPH/VHG9vfQ==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0", "react-error-overlay": "6.0.9", "react-refresh": "^0.9.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1481,18 +1568,18 @@ } }, "node_modules/@parcel/runtime-service-worker": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.10.2.tgz", - "integrity": "sha512-XY1GrY4r+zu0b/pZiTflZHdk9+I3XoxpExgPcZzep5hnq2UdyXbS4yDhmen7pTcqay5U9NmRw/62YrKL+yPang==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.11.0.tgz", + "integrity": "sha512-c8MaSpSbXIKuN5sA/g4UsrsH1BtBZ6Em+eSxt9AYbdPtWrW+qwCioNVZj9lugBRUzDMjVfJz0yK59nS42hABvw==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1500,9 +1587,9 @@ } }, "node_modules/@parcel/rust": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/rust/-/rust-2.10.2.tgz", - "integrity": "sha512-v/Cyf3iXlzSc6vgvPiEZzqdKAZ1jJ/aZX7y1YSupDh3RoqJI2bZ93kAOyEi+S7P3kshJkQM0px3YveJFOAMUOA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/rust/-/rust-2.11.0.tgz", + "integrity": "sha512-UkLWdHOD8Md2YmJDPsqd3yIs9chhdl/ATfV/B/xdPKGmqtNouYpDCRlq+WxMt3mLoYgHEg9UwrWLTebo2rr2iQ==", "dev": true, "engines": { "node": ">= 12.0.0" @@ -1525,15 +1612,15 @@ } }, "node_modules/@parcel/transformer-babel": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.10.2.tgz", - "integrity": "sha512-lmuksSzEBdPL1nVTznsQi5hQ+4mJ7GP+jvOv/Tvx3MjnzIu1G6Fs5MvNpAwBRXmG/F1+0aw/Wa8J38HYfN05dA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.11.0.tgz", + "integrity": "sha512-WKGblnp7r426VG+cpeQzc6dj/30EoUaYwyl4OEaigQSJizyuPWTBWTz6FUw+ih1/sg37h+D1BIh9C2FsVzpzbw==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.10.2", + "@parcel/utils": "2.11.0", "browserslist": "^4.6.6", "json5": "^2.2.0", "nullthrows": "^1.1.1", @@ -1541,17 +1628,29 @@ }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/transformer-babel/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/@parcel/transformer-babel/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1564,22 +1663,22 @@ } }, "node_modules/@parcel/transformer-css": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.10.2.tgz", - "integrity": "sha512-WxKe1YherQrX0vEfxAsBALEIsztGStmfXF0GAMeynE4q/w1iHQdTzu29tqLrJY7x532Ric8TxnwO8zR0r89DJg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.11.0.tgz", + "integrity": "sha512-nFmBulF/ErNoafO87JbVrBavjBMNwE/kahbCRVxc2Mvlphz4F4lBW4eDRS5l4xBqFJaNkHr9R55ehLBBilF4Jw==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.10.2", + "@parcel/utils": "2.11.0", "browserslist": "^4.6.6", - "lightningcss": "^1.16.1", + "lightningcss": "^1.22.1", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1587,14 +1686,14 @@ } }, "node_modules/@parcel/transformer-html": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.10.2.tgz", - "integrity": "sha512-Zkg1HHdYp14ecdtNF+s4d/e1lr8/PAQgBTYhyEVLVC1N7uivjjZ9XClxZlHuZImbQvX3q3PgZS+PocIizhY4rQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.11.0.tgz", + "integrity": "sha512-90vp7mbvvfqPr9XIINpMcELtywj56f1bxfOkLQgWU1bm22H0FT3i5dqdac++2My0IGDvMwhAEjQfbn4pA579NQ==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", - "@parcel/rust": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", + "@parcel/rust": "2.11.0", "nullthrows": "^1.1.1", "posthtml": "^0.16.5", "posthtml-parser": "^0.10.1", @@ -1604,17 +1703,29 @@ }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/transformer-html/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/@parcel/transformer-html/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1627,36 +1738,36 @@ } }, "node_modules/@parcel/transformer-image": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.10.2.tgz", - "integrity": "sha512-sR2kTsPykYRujKR7ISn0d6Fhem1pMQoqm0cFTrtC9Te5pfIjZ72NfM9clP7jPK660Gd2DYudhUa48y+qKBfCAw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.11.0.tgz", + "integrity": "sha512-QiZj18UHf3lVFsi65Vz8YbS3ydx9Pe9x8ktMxE1oh9qpznN8lD7gE/Z9DxuTZB84EZ9pKytKwcv5WGXP25xIFg==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2", - "@parcel/workers": "2.10.2", + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0", + "@parcel/workers": "2.11.0", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "peerDependencies": { - "@parcel/core": "^2.10.2" + "@parcel/core": "^2.11.0" } }, "node_modules/@parcel/transformer-js": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.10.2.tgz", - "integrity": "sha512-qcVLyikhSVf3oHhzReECkKdPU5uHVH4L0TC5O9ahlsq2IUTqR8Swq+9wUgUN0S2aYFTWreH05bQwBCNrLzF/eQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.11.0.tgz", + "integrity": "sha512-G1sv0n8/fJqHqwUs0iVnVdmRY0Kh8kWaDkuWcU/GJBHMGhUnLXKdNwxX2Av9UdBL14bU1nTINfr9qOfnQotXWg==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", - "@parcel/rust": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", + "@parcel/rust": "2.11.0", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.10.2", - "@parcel/workers": "2.10.2", + "@parcel/utils": "2.11.0", + "@parcel/workers": "2.11.0", "@swc/helpers": "^0.5.0", "browserslist": "^4.6.6", "nullthrows": "^1.1.1", @@ -1665,20 +1776,32 @@ }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.10.2" + "@parcel/core": "^2.11.0" + } + }, + "node_modules/@parcel/transformer-js/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/@parcel/transformer-js/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1691,17 +1814,17 @@ } }, "node_modules/@parcel/transformer-json": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.10.2.tgz", - "integrity": "sha512-iVgwuaLNqH3jgoBzMds63zd9FULvYb/s/5Hq9JZJ6pCZrOQoPruurgAW8A/t2IE4CSFkDDNoFvRpjsq1WBsSvA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.11.0.tgz", + "integrity": "sha512-Wt/wgSBaRWmPL4gpvjkV0bCBRxFOtsuLNzsm8vYA5poxTFhuLY+AoyQ8S2+xXU4VxwBfdppfIr2Ny3SwGs8xbQ==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", + "@parcel/plugin": "2.11.0", "json5": "^2.2.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1709,15 +1832,15 @@ } }, "node_modules/@parcel/transformer-postcss": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.10.2.tgz", - "integrity": "sha512-2/ehCZgj5TOmsAIeGiLwrm6gO/M+X4fZ/O71MhpmXd8zr08j25T0VdSdw5UyopsBvtPYM7DI/FJCviZc7AigCg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.11.0.tgz", + "integrity": "sha512-Ugy8XHBaUptGotsvwzq7gPCvkCopTIqqZ0JZ40Jmy9slGms8wnx06pNHA1Be/RcJwkJ2TbSu+7ncZdgmP5x5GQ==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", - "@parcel/rust": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", + "@parcel/rust": "2.11.0", + "@parcel/utils": "2.11.0", "clone": "^2.1.1", "nullthrows": "^1.1.1", "postcss-value-parser": "^4.2.0", @@ -1725,17 +1848,29 @@ }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/transformer-postcss/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/@parcel/transformer-postcss/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1748,13 +1883,13 @@ } }, "node_modules/@parcel/transformer-posthtml": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.10.2.tgz", - "integrity": "sha512-0jvqqXfrLqPYBD62aWIMldDnZ9hO/esX6TGKNhAO+85ljeaS2+QZ5XLLb8uPJq8UXB4olhsoEGyGtJSByigndg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.11.0.tgz", + "integrity": "sha512-dMK4p1RRAoIJEjK/Wz9GOLqwHqdD/VQDhMPk+6sUKp5zf2MhSohUstpp5gKsSZivCM3PS2f8k9rgroacJ/ReuA==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0", "nullthrows": "^1.1.1", "posthtml": "^0.16.5", "posthtml-parser": "^0.10.1", @@ -1763,17 +1898,29 @@ }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/transformer-posthtml/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/@parcel/transformer-posthtml/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1786,16 +1933,16 @@ } }, "node_modules/@parcel/transformer-raw": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.10.2.tgz", - "integrity": "sha512-h6SoIZ3u+Lq8z8SEEAVsHg4IQbUtkBWCln5SG4qfjGiclUDDA2hcG7grsP06Wb6/U7oEc8n0ksTtaG4dekYIxw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.11.0.tgz", + "integrity": "sha512-2ltp3TgS+cxEqSM1vk5gDtJrYx4KMuRRtbSgSvkdldyOgPhflnLU3/HRz72hXSNGqYOV0/JN0+ocsfPnqR00ug==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2" + "@parcel/plugin": "2.11.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1803,18 +1950,18 @@ } }, "node_modules/@parcel/transformer-react-refresh-wrap": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.10.2.tgz", - "integrity": "sha512-1jpzaEbKwJnDUmF8Kgf3/XvT9BnUWIQ7FWkg5EL5kEx6tq2KLKdzD17nFigNj8fr2V+faX0Qa63h+e3OOpnMAA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.11.0.tgz", + "integrity": "sha512-6pY0CdIgIpXC6XpsDWizf+zLgiuEsJ106HjWLwF7/R72BrvDhLPZ6jRu4UTrnd6bM89KahPw9fZZzjKoA5Efcw==", "dev": true, "dependencies": { - "@parcel/plugin": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/plugin": "2.11.0", + "@parcel/utils": "2.11.0", "react-refresh": "^0.9.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", @@ -1822,14 +1969,14 @@ } }, "node_modules/@parcel/transformer-svg": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.10.2.tgz", - "integrity": "sha512-SsCjiM9LZwGne3LUn+GuwhyqklAnr7CER6D0ozdpw+tPOeODsXZXNSktvtpE1Qbia61c/zdlU0yOEuhkeXz29w==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.11.0.tgz", + "integrity": "sha512-GrTNi04OoQSXsyrB7FqQPeYREscEXFhIBPkyQ0q7WDG/yYynWljiA0kwITCtMjPfv2EDVks292dvM3EcnERRIA==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/plugin": "2.10.2", - "@parcel/rust": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/plugin": "2.11.0", + "@parcel/rust": "2.11.0", "nullthrows": "^1.1.1", "posthtml": "^0.16.5", "posthtml-parser": "^0.10.1", @@ -1838,17 +1985,29 @@ }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.10.2" + "parcel": "^2.11.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/transformer-svg/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/@parcel/transformer-svg/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1861,31 +2020,31 @@ } }, "node_modules/@parcel/types": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.10.2.tgz", - "integrity": "sha512-fwHJu03ROcc4/Kr/00VfOQUD6aV+6FBLN5bDW1+Xblgrpkb1MSUGTWRuz0YH5X6xhkVigC1llCIR2uHSwA+YBg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.11.0.tgz", + "integrity": "sha512-lN5XlfV9b1s2rli8q1LqsLtu+D4ZwNI3sKmNcL/3tohSfQcF2EgF+MaiANGo9VzXOzoWFHt4dqWjO4OcdyC5tg==", "dev": true, "dependencies": { - "@parcel/cache": "2.10.2", - "@parcel/diagnostic": "2.10.2", - "@parcel/fs": "2.10.2", - "@parcel/package-manager": "2.10.2", + "@parcel/cache": "2.11.0", + "@parcel/diagnostic": "2.11.0", + "@parcel/fs": "2.11.0", + "@parcel/package-manager": "2.11.0", "@parcel/source-map": "^2.1.1", - "@parcel/workers": "2.10.2", + "@parcel/workers": "2.11.0", "utility-types": "^3.10.0" } }, "node_modules/@parcel/utils": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.10.2.tgz", - "integrity": "sha512-XLUhTh0UkPB5n8r7agX9iIz9f+3JsBIVsmqltsJYX7n/GAa6EQtqrIYyZu8cEFeZlZw3zaf7wTmf9xJppdlj7Q==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.11.0.tgz", + "integrity": "sha512-AcL70cXlIyE7eQdvjQbYxegN5l+skqvlJllxTWg4YkIZe9p8Gmv74jLAeLWh5F+IGl5WRn0TSy9JhNJjIMQGwQ==", "dev": true, "dependencies": { - "@parcel/codeframe": "2.10.2", - "@parcel/diagnostic": "2.10.2", - "@parcel/logger": "2.10.2", - "@parcel/markdown-ansi": "2.10.2", - "@parcel/rust": "2.10.2", + "@parcel/codeframe": "2.11.0", + "@parcel/diagnostic": "2.11.0", + "@parcel/logger": "2.11.0", + "@parcel/markdown-ansi": "2.11.0", + "@parcel/rust": "2.11.0", "@parcel/source-map": "^2.1.1", "chalk": "^4.1.0", "nullthrows": "^1.1.1" @@ -1969,271 +2128,17 @@ } }, "node_modules/@parcel/watcher": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.3.0.tgz", - "integrity": "sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.1.0.tgz", + "integrity": "sha512-8s8yYjd19pDSsBpbkOHnT6Z2+UJSuLQx61pCFM0s5wSRvKCEMDjd/cHY3/GI1szHIWbpXpsJdg3V6ISGGx9xDw==", "dev": true, "hasInstallScript": true, "dependencies": { - "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.3.0", - "@parcel/watcher-darwin-arm64": "2.3.0", - "@parcel/watcher-darwin-x64": "2.3.0", - "@parcel/watcher-freebsd-x64": "2.3.0", - "@parcel/watcher-linux-arm-glibc": "2.3.0", - "@parcel/watcher-linux-arm64-glibc": "2.3.0", - "@parcel/watcher-linux-arm64-musl": "2.3.0", - "@parcel/watcher-linux-x64-glibc": "2.3.0", - "@parcel/watcher-linux-x64-musl": "2.3.0", - "@parcel/watcher-win32-arm64": "2.3.0", - "@parcel/watcher-win32-ia32": "2.3.0", - "@parcel/watcher-win32-x64": "2.3.0" - } - }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.3.0.tgz", - "integrity": "sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.3.0.tgz", - "integrity": "sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.3.0.tgz", - "integrity": "sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.3.0.tgz", - "integrity": "sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.3.0.tgz", - "integrity": "sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.3.0.tgz", - "integrity": "sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.3.0.tgz", - "integrity": "sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.3.0.tgz", - "integrity": "sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.3.0.tgz", - "integrity": "sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.3.0.tgz", - "integrity": "sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.3.0.tgz", - "integrity": "sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.3.0.tgz", - "integrity": "sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], "engines": { "node": ">= 10.0.0" }, @@ -2243,16 +2148,16 @@ } }, "node_modules/@parcel/workers": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.10.2.tgz", - "integrity": "sha512-LvifdeORXKGGyhwOwnYxn1AsJ5u6Ihk2RJUxsVA4WYEjz2PSsmLAUDdp48ovssSMnTb9P2g4RrbEG1mJjYtBGA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.11.0.tgz", + "integrity": "sha512-wjybqdSy6Nk0N9iBGsFcp7739W2zvx0WGfVxPVShqhz46pIkPOiFF/iSn+kFu5EmMKTRWeUif42+a6rRZ7pCnQ==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.10.2", - "@parcel/logger": "2.10.2", - "@parcel/profiler": "2.10.2", - "@parcel/types": "2.10.2", - "@parcel/utils": "2.10.2", + "@parcel/diagnostic": "2.11.0", + "@parcel/logger": "2.11.0", + "@parcel/profiler": "2.11.0", + "@parcel/types": "2.11.0", + "@parcel/utils": "2.11.0", "nullthrows": "^1.1.1" }, "engines": { @@ -2263,13 +2168,23 @@ "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.10.2" + "@parcel/core": "^2.11.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" } }, "node_modules/@swc/core": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.100.tgz", - "integrity": "sha512-7dKgTyxJjlrMwFZYb1auj3Xq0D8ZBe+5oeIgfMlRU05doXZypYJe0LAk0yjj3WdbwYzpF+T1PLxwTWizI0pckw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.0.tgz", + "integrity": "sha512-wc5DMI5BJftnK0Fyx9SNJKkA0+BZSJQx8430yutWmsILkHMBD3Yd9GhlMaxasab9RhgKqZp7Ht30hUYO5ZDvQg==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -2284,15 +2199,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.3.100", - "@swc/core-darwin-x64": "1.3.100", - "@swc/core-linux-arm64-gnu": "1.3.100", - "@swc/core-linux-arm64-musl": "1.3.100", - "@swc/core-linux-x64-gnu": "1.3.100", - "@swc/core-linux-x64-musl": "1.3.100", - "@swc/core-win32-arm64-msvc": "1.3.100", - "@swc/core-win32-ia32-msvc": "1.3.100", - "@swc/core-win32-x64-msvc": "1.3.100" + "@swc/core-darwin-arm64": "1.4.0", + "@swc/core-darwin-x64": "1.4.0", + "@swc/core-linux-arm-gnueabihf": "1.4.0", + "@swc/core-linux-arm64-gnu": "1.4.0", + "@swc/core-linux-arm64-musl": "1.4.0", + "@swc/core-linux-x64-gnu": "1.4.0", + "@swc/core-linux-x64-musl": "1.4.0", + "@swc/core-win32-arm64-msvc": "1.4.0", + "@swc/core-win32-ia32-msvc": "1.4.0", + "@swc/core-win32-x64-msvc": "1.4.0" }, "peerDependencies": { "@swc/helpers": "^0.5.0" @@ -2304,9 +2220,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.100.tgz", - "integrity": "sha512-XVWFsKe6ei+SsDbwmsuRkYck1SXRpO60Hioa4hoLwR8fxbA9eVp6enZtMxzVVMBi8ej5seZ4HZQeAWepbukiBw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.0.tgz", + "integrity": "sha512-UTJ/Vz+s7Pagef6HmufWt6Rs0aUu+EJF4Pzuwvr7JQQ5b1DZeAAUeUtkUTFx/PvCbM8Xfw4XdKBUZfrIKCfW8A==", "cpu": [ "arm64" ], @@ -2320,9 +2236,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.100.tgz", - "integrity": "sha512-KF/MXrnH1nakm1wbt4XV8FS7kvqD9TGmVxeJ0U4bbvxXMvzeYUurzg3AJUTXYmXDhH/VXOYJE5N5RkwZZPs5iA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.0.tgz", + "integrity": "sha512-f8v58u2GsGak8EtZFN9guXqE0Ep10Suny6xriaW2d8FGqESPyNrnBzli3aqkSeQk5gGqu2zJ7WiiKp3XoUOidA==", "cpu": [ "x64" ], @@ -2335,10 +2251,26 @@ "node": ">=10" } }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.0.tgz", + "integrity": "sha512-q2KAkBzmPcTnRij/Y1fgHCKAGevUX/H4uUESrw1J5gmUg9Qip6onKV80lTumA1/aooGJ18LOsB31qdbwmZk9OA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.100.tgz", - "integrity": "sha512-p8hikNnAEJrw5vHCtKiFT4hdlQxk1V7vqPmvUDgL/qe2menQDK/i12tbz7/3BEQ4UqUPnvwpmVn2d19RdEMNxw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.0.tgz", + "integrity": "sha512-SknGu96W0mzHtLHWm+62fk5+Omp9fMPFO7AWyGFmz2tr8EgRRXtTSrBUnWhAbgcalnhen48GsvtMdxf1KNputg==", "cpu": [ "arm64" ], @@ -2352,9 +2284,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.100.tgz", - "integrity": "sha512-BWx/0EeY89WC4q3AaIaBSGfQxkYxIlS3mX19dwy2FWJs/O+fMvF9oLk/CyJPOZzbp+1DjGeeoGFuDYpiNO91JA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.0.tgz", + "integrity": "sha512-/k3TDvpBRMDNskHooNN1KqwUhcwkfBlIYxRTnJvsfT2C7My4pffR+4KXmt0IKynlTTbCdlU/4jgX4801FSuliw==", "cpu": [ "arm64" ], @@ -2368,9 +2300,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.100.tgz", - "integrity": "sha512-XUdGu3dxAkjsahLYnm8WijPfKebo+jHgHphDxaW0ovI6sTdmEGFDew7QzKZRlbYL2jRkUuuKuDGvD6lO5frmhA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.0.tgz", + "integrity": "sha512-GYsTMvNt5+WTVlwwQzOOWsPMw6P/F41u5PGHWmfev8Nd4QJ1h3rWPySKk4mV42IJwH9MgQCVSl3ygwNqwl6kFg==", "cpu": [ "x64" ], @@ -2384,9 +2316,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.100.tgz", - "integrity": "sha512-PhoXKf+f0OaNW/GCuXjJ0/KfK9EJX7z2gko+7nVnEA0p3aaPtbP6cq1Ubbl6CMoPL+Ci3gZ7nYumDqXNc3CtLQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.0.tgz", + "integrity": "sha512-jGVPdM/VwF7kK/uYRW5N6FwzKf/FnDjGIR3RPvQokjYJy7Auk+3Oj21C0Jev7sIT9RYnO/TrFEoEozKeD/z2Qw==", "cpu": [ "x64" ], @@ -2400,9 +2332,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.100.tgz", - "integrity": "sha512-PwLADZN6F9cXn4Jw52FeP/MCLVHm8vwouZZSOoOScDtihjY495SSjdPnlosMaRSR4wJQssGwiD/4MbpgQPqbAw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.0.tgz", + "integrity": "sha512-biHYm1AronEKlt47O/H8sSOBM2BKXMmWT+ApvlxUw50m1RGNnVnE0bgY7tylFuuSiWyXsQPJbmUV708JqORXVg==", "cpu": [ "arm64" ], @@ -2416,9 +2348,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.100.tgz", - "integrity": "sha512-0f6nicKSLlDKlyPRl2JEmkpBV4aeDfRQg6n8mPqgL7bliZIcDahG0ej+HxgNjZfS3e0yjDxsNRa6sAqWU2Z60A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.0.tgz", + "integrity": "sha512-TL5L2tFQb19kJwv6+elToGBj74QXCn9j+hZfwQatvZEJRA5rDK16eH6oAE751dGUArhnWlW3Vj65hViPvTuycw==", "cpu": [ "ia32" ], @@ -2432,9 +2364,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.100.tgz", - "integrity": "sha512-b7J0rPoMkRTa3XyUGt8PwCaIBuYWsL2DqbirrQKRESzgCvif5iNpqaM6kjIjI/5y5q1Ycv564CB51YDpiS8EtQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.0.tgz", + "integrity": "sha512-e2xVezU7XZ2Stzn4i7TOQe2Kn84oYdG0M3A7XI7oTdcpsKCcKwgiMoroiAhqCv+iN20KNqhnWwJiUiTj/qN5AA==", "cpu": [ "x64" ], @@ -2448,15 +2380,15 @@ } }, "node_modules/@swc/counter": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", - "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", "dev": true }, "node_modules/@swc/helpers": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.3.tgz", - "integrity": "sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.6.tgz", + "integrity": "sha512-aYX01Ke9hunpoCexYAgQucEpARGQ5w/cqHFrIR+e9gdKb1QWTsVJuTJ2ozQzIAxLyRQe/m+2RqzkyOOGiMKRQA==", "dev": true, "dependencies": { "tslib": "^2.4.0" @@ -2484,9 +2416,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2495,6 +2427,15 @@ "node": ">=0.4.0" } }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -2539,30 +2480,34 @@ "dev": true }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -2573,9 +2518,9 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", + "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", "dev": true, "engines": { "node": ">= 0.4" @@ -2637,9 +2582,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", "dev": true, "funding": [ { @@ -2656,8 +2601,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -2675,14 +2620,18 @@ "dev": true }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", + "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", "dev": true, "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.3", + "set-function-length": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2707,9 +2656,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001566", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", - "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", + "version": "1.0.30001584", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", + "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", "dev": true, "funding": [ { @@ -2788,6 +2737,18 @@ "node": ">=6.0" } }, + "node_modules/cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dev": true, + "dependencies": { + "string-width": "^4.2.3" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -3029,14 +2990,15 @@ "peer": true }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", + "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.2", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -3162,10 +3124,22 @@ "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/electron-to-chromium": { - "version": "1.4.603", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.603.tgz", - "integrity": "sha512-Dvo5OGjnl7AZTU632dFJtWj0uJK835eeOVQIuRcmBmsFsTNn3cL05FqOyHAfGQDIoHfLhyJ1Tya3PJ0ceMz54g==", + "version": "1.4.657", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.657.tgz", + "integrity": "sha512-On2ymeleg6QbRuDk7wNgDdXtNqlJLM2w4Agx1D/RiTmItiL+a9oq5p7HUa2ZtkAtGBe/kil2dq/7rPfkbe0r5w==", + "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": { @@ -3242,6 +3216,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", @@ -3274,9 +3257,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -3320,9 +3303,9 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3349,12 +3332,81 @@ "is-callable": "^1.1.3" } }, - "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/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/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/foreground-child/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/foreground-child/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/foreground-child/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/foreground-child/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/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3406,16 +3458,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3430,13 +3486,13 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.1.tgz", + "integrity": "sha512-KmuibvwbWaM4BHcBRYwJfZ1JxyJeBwB8ct9YYu67SvYdbEIlcQ2e56dHxfbobqW38GXo8/zDFqJeGtHiVbWyQw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -3446,20 +3502,22 @@ } }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -3477,10 +3535,34 @@ "node": ">=10.13.0" } }, + "node_modules/glob/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/glob/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3580,12 +3662,12 @@ } }, "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==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -3679,9 +3761,9 @@ } }, "node_modules/htmx.org": { - "version": "1.9.9", - "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-1.9.9.tgz", - "integrity": "sha512-PDEZU1me7UGLzQk98LyfLvwFgdtn9mrCVMmAxv1/UjshUnxsc+rouu+Ot2QfFZxsY4mBCoOed5nK7m9Nj2Tu7g==", + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-1.9.10.tgz", + "integrity": "sha512-UgchasltTCrTuU2DQLom3ohHrBvwr7OqpwyAVJ9VxtNBng4XKkVsqrv0Qr3srqvM9ZNI3f1MmvVQQqK7KW/bTA==", "dev": true }, "node_modules/hyperscript.org": { @@ -3713,29 +3795,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", + "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" }, @@ -3744,14 +3810,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3851,6 +3919,15 @@ "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", @@ -3964,12 +4041,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -4002,6 +4079,24 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jiti": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", @@ -4054,9 +4149,9 @@ } }, "node_modules/lightningcss": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.22.1.tgz", - "integrity": "sha512-Fy45PhibiNXkm0cK5FJCbfO8Y6jUpD/YcHf/BtuI+jvYYqSXKF4muk61jjE8YxCR9y+hDYIWSzHTc+bwhDE6rQ==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.23.0.tgz", + "integrity": "sha512-SEArWKMHhqn/0QzOtclIwH5pXIYQOUEkF8DgICd/105O+GCgd7jxjNod/QPnBCSWvpRHQBGVz5fQ9uScby03zA==", "dev": true, "dependencies": { "detect-libc": "^1.0.3" @@ -4069,21 +4164,21 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-darwin-arm64": "1.22.1", - "lightningcss-darwin-x64": "1.22.1", - "lightningcss-freebsd-x64": "1.22.1", - "lightningcss-linux-arm-gnueabihf": "1.22.1", - "lightningcss-linux-arm64-gnu": "1.22.1", - "lightningcss-linux-arm64-musl": "1.22.1", - "lightningcss-linux-x64-gnu": "1.22.1", - "lightningcss-linux-x64-musl": "1.22.1", - "lightningcss-win32-x64-msvc": "1.22.1" + "lightningcss-darwin-arm64": "1.23.0", + "lightningcss-darwin-x64": "1.23.0", + "lightningcss-freebsd-x64": "1.23.0", + "lightningcss-linux-arm-gnueabihf": "1.23.0", + "lightningcss-linux-arm64-gnu": "1.23.0", + "lightningcss-linux-arm64-musl": "1.23.0", + "lightningcss-linux-x64-gnu": "1.23.0", + "lightningcss-linux-x64-musl": "1.23.0", + "lightningcss-win32-x64-msvc": "1.23.0" } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.22.1.tgz", - "integrity": "sha512-ldvElu+R0QimNTjsKpaZkUv3zf+uefzLy/R1R19jtgOfSRM+zjUCUgDhfEDRmVqJtMwYsdhMI2aJtJChPC6Osg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.23.0.tgz", + "integrity": "sha512-kl4Pk3Q2lnE6AJ7Qaij47KNEfY2/UXRZBT/zqGA24B8qwkgllr/j7rclKOf1axcslNXvvUdztjo4Xqh39Yq1aA==", "cpu": [ "arm64" ], @@ -4101,9 +4196,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.22.1.tgz", - "integrity": "sha512-5p2rnlVTv6Gpw4PlTLq925nTVh+HFh4MpegX8dPDYJae+NFVjQ67gY7O6iHIzQjLipDiYejFF0yHrhjU3XgLBQ==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.23.0.tgz", + "integrity": "sha512-KeRFCNoYfDdcolcFXvokVw+PXCapd2yHS1Diko1z1BhRz/nQuD5XyZmxjWdhmhN/zj5sH8YvWsp0/lPLVzqKpg==", "cpu": [ "x64" ], @@ -4121,9 +4216,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.22.1.tgz", - "integrity": "sha512-1FaBtcFrZqB2hkFbAxY//Pnp8koThvyB6AhjbdVqKD4/pu13Rl91fKt2N9qyeQPUt3xy7ORUvSO+dPk3J6EjXg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.23.0.tgz", + "integrity": "sha512-xhnhf0bWPuZxcqknvMDRFFo2TInrmQRWZGB0f6YoAsZX8Y+epfjHeeOIGCfAmgF0DgZxHwYc8mIR5tQU9/+ROA==", "cpu": [ "x64" ], @@ -4141,9 +4236,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.22.1.tgz", - "integrity": "sha512-6rub98tYGfE5I5j0BP8t/2d4BZyu1S7Iz9vUkm0H26snAFHYxLfj3RbQn0xHHIePSetjLnhcg3QlfwUAkD/FYg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.23.0.tgz", + "integrity": "sha512-fBamf/bULvmWft9uuX+bZske236pUZEoUlaHNBjnueaCTJ/xd8eXgb0cEc7S5o0Nn6kxlauMBnqJpF70Bgq3zg==", "cpu": [ "arm" ], @@ -4161,9 +4256,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.22.1.tgz", - "integrity": "sha512-nYO5qGtb/1kkTZu3FeTiM+2B2TAb7m2DkLCTgQIs2bk2o9aEs7I96fwySKcoHWQAiQDGR9sMux9vkV4KQXqPaQ==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.23.0.tgz", + "integrity": "sha512-RS7sY77yVLOmZD6xW2uEHByYHhQi5JYWmgVumYY85BfNoVI3DupXSlzbw+b45A9NnVKq45+oXkiN6ouMMtTwfg==", "cpu": [ "arm64" ], @@ -4181,9 +4276,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.22.1.tgz", - "integrity": "sha512-MCV6RuRpzXbunvzwY644iz8cw4oQxvW7oer9xPkdadYqlEyiJJ6wl7FyJOH7Q6ZYH4yjGAUCvxDBxPbnDu9ZVg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.23.0.tgz", + "integrity": "sha512-cU00LGb6GUXCwof6ACgSMKo3q7XYbsyTj0WsKHLi1nw7pV0NCq8nFTn6ZRBYLoKiV8t+jWl0Hv8KkgymmK5L5g==", "cpu": [ "arm64" ], @@ -4201,9 +4296,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.22.1.tgz", - "integrity": "sha512-RjNgpdM20VUXgV7us/VmlO3Vn2ZRiDnc3/bUxCVvySZWPiVPprpqW/QDWuzkGa+NCUf6saAM5CLsZLSxncXJwg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.23.0.tgz", + "integrity": "sha512-q4jdx5+5NfB0/qMbXbOmuC6oo7caPnFghJbIAV90cXZqgV8Am3miZhC4p+sQVdacqxfd+3nrle4C8icR3p1AYw==", "cpu": [ "x64" ], @@ -4221,9 +4316,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.22.1.tgz", - "integrity": "sha512-ZgO4C7Rd6Hv/5MnyY2KxOYmIlzk4rplVolDt3NbkNR8DndnyX0Q5IR4acJWNTBICQ21j3zySzKbcJaiJpk/4YA==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.23.0.tgz", + "integrity": "sha512-G9Ri3qpmF4qef2CV/80dADHKXRAQeQXpQTLx7AiQrBYQHqBjB75oxqj06FCIe5g4hNCqLPnM9fsO4CyiT1sFSQ==", "cpu": [ "x64" ], @@ -4241,9 +4336,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.22.1.tgz", - "integrity": "sha512-4pozV4eyD0MDET41ZLHAeBo+H04Nm2UEYIk5w/ts40231dRFV7E0cjwbnZvSoc1DXFgecAhiC0L16ruv/ZDCpg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.23.0.tgz", + "integrity": "sha512-1rcBDJLU+obPPJM6qR5fgBUiCdZwZLafZM5f9kwjFLkb/UBNIzmae39uCSmh71nzPCTXZqHbvwu23OWnWEz+eg==", "cpu": [ "x64" ], @@ -4335,15 +4430,12 @@ } }, "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==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": "14 || >=16.14" } }, "node_modules/markdown-it-deflist": { @@ -4403,10 +4495,19 @@ "node": "*" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/msgpackr": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.0.tgz", - "integrity": "sha512-rVQ5YAQDoZKZLX+h8tNq7FiHrPJoeGHViz3U4wIcykhAEpwF/nH2Vbk8dQxmpX5JavkI8C7pt4bnkJ02ZmRoUw==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.1.tgz", + "integrity": "sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==", "dev": true, "optionalDependencies": { "msgpackr-extract": "^3.0.2" @@ -4482,11 +4583,22 @@ "dev": true }, "node_modules/node-addon-api": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", - "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", "dev": true }, + "node_modules/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-gyp-build-optional-packages": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz", @@ -4634,15 +4746,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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/ordered-binary": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.1.tgz", @@ -4650,22 +4753,22 @@ "dev": true }, "node_modules/parcel": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.10.2.tgz", - "integrity": "sha512-wRvsK9v12Nt2/EIjLp/uvxd3UeRSN9DRoSofDn21Ot+rEw4e98ODvbdSHi6dYr82s4oo6mF823ACmOp1hXd4wg==", - "dev": true, - "dependencies": { - "@parcel/config-default": "2.10.2", - "@parcel/core": "2.10.2", - "@parcel/diagnostic": "2.10.2", - "@parcel/events": "2.10.2", - "@parcel/fs": "2.10.2", - "@parcel/logger": "2.10.2", - "@parcel/package-manager": "2.10.2", - "@parcel/reporter-cli": "2.10.2", - "@parcel/reporter-dev-server": "2.10.2", - "@parcel/reporter-tracer": "2.10.2", - "@parcel/utils": "2.10.2", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.11.0.tgz", + "integrity": "sha512-H/RI1/DmuOkL8RuG/EpNPvtzrbF+7jA/R56ydEEm+lqFbYktKB4COR7JXdHkZXRgbSJyimrFB8d0r9+SaRnj0Q==", + "dev": true, + "dependencies": { + "@parcel/config-default": "2.11.0", + "@parcel/core": "2.11.0", + "@parcel/diagnostic": "2.11.0", + "@parcel/events": "2.11.0", + "@parcel/fs": "2.11.0", + "@parcel/logger": "2.11.0", + "@parcel/package-manager": "2.11.0", + "@parcel/reporter-cli": "2.11.0", + "@parcel/reporter-dev-server": "2.11.0", + "@parcel/reporter-tracer": "2.11.0", + "@parcel/utils": "2.11.0", "chalk": "^4.1.0", "commander": "^7.0.0", "get-port": "^4.2.0" @@ -4781,15 +4884,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -4805,6 +4899,22 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "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": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -4863,9 +4973,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.34", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.34.tgz", + "integrity": "sha512-4eLTO36woPSocqZ1zIrFD2K1v6wH7pY1uBh0JIM2KKfrVtGvPFiAku6aNOP0W1Wr9qwnaCsF0Z+CrVnryB2A8Q==", "dev": true, "funding": [ { @@ -4990,9 +5100,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -5231,13 +5341,13 @@ } }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -5269,15 +5379,18 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", + "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5292,15 +5405,16 @@ } }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", "dev": true, "dependencies": { "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -5364,6 +5478,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5403,9 +5529,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", + "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -5443,6 +5569,35 @@ "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/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.padend": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.5.tgz", @@ -5505,6 +5660,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -5515,14 +5695,14 @@ } }, "node_modules/sucrase": { - "version": "3.34.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", - "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", - "glob": "7.1.6", + "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", @@ -5533,7 +5713,7 @@ "sucrase-node": "bin/sucrase-node" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/sucrase/node_modules/commander": { @@ -5570,9 +5750,9 @@ } }, "node_modules/svgo": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.5.tgz", - "integrity": "sha512-HQKHEo73pMNOlDlBcLgZRcHW2+1wo7bFYayAXkGN0l/2+h68KjlfZyMRhdhaGvoHV2eApOovl12zoFz42sT6rQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", + "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", "dev": true, "optional": true, "peer": true, @@ -5580,9 +5760,9 @@ "@trysound/sax": "0.2.0", "commander": "^7.2.0", "css-select": "^5.1.0", - "css-tree": "^2.2.1", + "css-tree": "^2.3.1", "css-what": "^6.1.0", - "csso": "5.0.5", + "csso": "^5.0.5", "picocolors": "^1.0.0" }, "bin": { @@ -5597,9 +5777,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz", - "integrity": "sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", "dev": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -5646,9 +5826,9 @@ } }, "node_modules/terser": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.25.0.tgz", - "integrity": "sha512-we0I9SIsfvNUMP77zC9HG+MylwYYsGFSBG8qm+13oud2Yh+O104y614FRbyjpxys16jZwot72Fpi827YvGzuqg==", + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", + "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -5849,9 +6029,9 @@ "dev": true }, "node_modules/utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", "dev": true, "engines": { "node": ">= 4" @@ -5902,16 +6082,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -5920,12 +6100,136 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 908a578..849e377 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,13 @@ "parcel:prephtml": "cp ui/src/base.html ui/target/build/" }, "devDependencies": { - "htmx.org": "1.9.9", - "hyperscript.org": "0.9.12", + "htmx.org": "1.9", + "hyperscript.org": "0.9", "npm-run-all": "4.1.5", - "parcel": "2.10.2", - "tailwindcss": "3.3.5" + "parcel": "2.11", + "tailwindcss": "3.4" + }, + "overrides": { + "@parcel/watcher": "2.1.0" } } From e7b4fe85f8385daedbcf5b99e35887f87b2154e7 Mon Sep 17 00:00:00 2001 From: John Bledsoe <59550+johnbcodes@users.noreply.github.com> Date: Thu, 8 Feb 2024 15:05:22 -0500 Subject: [PATCH 2/2] feat: Switch from axum to Rocket for better ergonomics and correctness with blocking/sync libraries --- Cargo.lock | 1337 ++++++++++++++++------------- Cargo.toml | 15 +- Dockerfile | 10 +- README.md | 15 +- Rocket.toml | 13 + docker-compose.yml | 4 +- fly.toml | 6 +- src/assets.rs | 74 +- src/currency.rs | 2 +- src/error.rs | 17 +- src/forms.rs | 56 ++ src/line_item_dates/controller.rs | 268 +++--- src/line_item_dates/model.rs | 67 +- src/line_item_dates/query.rs | 55 +- src/line_item_dates/view.rs | 148 +++- src/line_items/controller.rs | 290 +++---- src/line_items/model.rs | 97 ++- src/line_items/query.rs | 67 +- src/line_items/view.rs | 237 ++++- src/main.rs | 150 +--- src/quotes/controller.rs | 288 +++---- src/quotes/model.rs | 53 +- src/quotes/query.rs | 52 +- src/quotes/view.rs | 129 ++- src/rocket_ext.rs | 12 + ui/src/app.js | 13 - 26 files changed, 2000 insertions(+), 1475 deletions(-) create mode 100644 Rocket.toml create mode 100644 src/forms.rs create mode 100644 src/rocket_ext.rs diff --git a/Cargo.lock b/Cargo.lock index c7d817b..4c53b06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,111 +27,64 @@ dependencies = [ ] [[package]] -name = "alloc-no-stdlib" -version = "2.0.4" +name = "anyhow" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] -name = "alloc-stdlib" -version = "0.2.2" +name = "async-stream" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" dependencies = [ - "alloc-no-stdlib", + "async-stream-impl", + "futures-core", + "pin-project-lite", ] [[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "async-compression" -version = "0.4.5" +name = "async-stream-impl" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "brotli", - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", - "zstd", - "zstd-safe", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn", ] [[package]] -name = "autocfg" -version = "1.1.0" +name = "atomic" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" [[package]] -name = "axum" -version = "0.7.2" +name = "atomic" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202651474fe73c62d9e0a56c6133f7a0ff1dc1c8cf7a5b03381af2a26553ac9d" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" dependencies = [ - "async-trait", - "axum-core", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tower", - "tower-layer", - "tower-service", + "bytemuck", ] [[package]] -name = "axum-core" -version = "0.4.1" +name = "autocfg" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77cb22c689c44d4c07b0ab44ebc25d69d8ae601a2f28fb8d672d344178fa17aa" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper", - "tower-layer", - "tower-service", -] +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" @@ -149,10 +102,10 @@ dependencies = [ ] [[package]] -name = "base64" -version = "0.21.5" +name = "binascii" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" [[package]] name = "bit-set" @@ -177,9 +130,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "block-buffer" @@ -191,25 +144,16 @@ dependencies = [ ] [[package]] -name = "brotli" -version = "3.4.0" +name = "bumpalo" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] -name = "brotli-decompressor" -version = "2.5.1" +name = "bytemuck" +version = "1.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] +checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" [[package]] name = "bytes" @@ -223,7 +167,6 @@ version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ - "jobserver", "libc", ] @@ -234,21 +177,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cpufeatures" -version = "0.2.11" +name = "cookie" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "3cd91cf61412820176e137621345ee43b3f4423e589e7ae4e50d601d93e35ef8" dependencies = [ - "libc", + "percent-encoding", + "time", + "version_check", ] [[package]] -name = "crc32fast" -version = "1.3.2" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ - "cfg-if", + "libc", ] [[package]] @@ -273,14 +218,47 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", "serde", ] +[[package]] +name = "devise" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6eacefd3f541c66fc61433d65e54e0e46e0a029a819a7dbbc7a7b489e8a85f8" +dependencies = [ + "devise_codegen", + "devise_core", +] + +[[package]] +name = "devise_codegen" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8cf4b8dd484ede80fd5c547592c46c3745a617c8af278e2b72bea86b2dfed6" +dependencies = [ + "devise_core", + "quote", +] + +[[package]] +name = "devise_core" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" +dependencies = [ + "bitflags 2.4.2", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + [[package]] name = "diesel" version = "2.1.4" @@ -302,7 +280,7 @@ dependencies = [ "diesel_table_macro_syntax", "proc-macro2", "quote", - "syn 2.0.39", + "syn", ] [[package]] @@ -322,7 +300,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.39", + "syn", ] [[package]] @@ -337,42 +315,56 @@ dependencies = [ [[package]] name = "dirs" -version = "4.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys 0.48.0", ] -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "fancy-regex" version = "0.11.0" @@ -384,13 +376,23 @@ dependencies = [ ] [[package]] -name = "flate2" -version = "1.0.28" +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "figment" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "2b6e5bc7bd59d60d0d45a6ccab6cf0f4ce28698fb4e81e750ddf229c9b824026" dependencies = [ - "crc32fast", - "miniz_oxide", + "atomic 0.6.0", + "pear", + "serde", + "toml 0.8.10", + "uncased", + "version_check", ] [[package]] @@ -400,54 +402,83 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "form_urlencoded" -version = "1.2.1" +name = "futures" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ - "percent-encoding", + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", ] [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", + "futures-sink", ] [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -460,13 +491,15 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -475,11 +508,17 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "h2" -version = "0.4.0" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d308f63daf4181410c242d34c11f928dcb3aa105852019e043c9d1f4e4368a" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -502,42 +541,15 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "hotwire-turbo" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972770143869a967800e948386ccce0e9b5f20782cf27c08e47f9a542ea11113" -dependencies = [ - "html-escape", -] - -[[package]] -name = "hotwire-turbo-axum" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a1b2d42218d1e6ca790ea278ae32bea7508f9ff3d3dda83543ab9ac8de4e1" -dependencies = [ - "axum", -] - -[[package]] -name = "html-escape" -version = "0.2.13" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" -dependencies = [ - "utf8-width", -] +checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" [[package]] name = "http" -version = "1.0.0" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -546,33 +558,15 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.0" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "futures-util", "http", - "http-body", "pin-project-lite", ] -[[package]] -name = "http-range-header" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ce4ef31cda248bbdb6e6820603b82dfcd9e833db65a43e997a0ccec777d11fe" - [[package]] name = "httparse" version = "1.8.0" @@ -587,12 +581,13 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.0.1" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f9214f3e703236b221f1a9cd88ec8b4adfa5296de01ab96216361f4692f56" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", + "futures-core", "futures-util", "h2", "http", @@ -601,97 +596,63 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "tokio", -] - -[[package]] -name = "hyper-util" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca339002caeb0d159cc6e023dff48e199f081e42fa039895c7c6f38b37f2e9d" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", + "want", ] -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" dependencies = [ "equivalent", "hashbrown", + "serde", ] [[package]] -name = "iri-string" -version = "0.7.0" +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + +[[package]] +name = "is-terminal" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21859b667d66a4c1dacd9df0863b3efb65785474255face87f5bca39dd8407c0" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ - "memchr", - "serde", + "hermit-abi", + "rustix", + "windows-sys 0.52.0", ] [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] -name = "jobserver" -version = "0.1.27" +name = "js-sys" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ - "libc", + "wasm-bindgen", ] [[package]] @@ -702,9 +663,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libredox" @@ -712,7 +673,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall", ] @@ -728,6 +689,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + [[package]] name = "lock_api" version = "0.4.11" @@ -744,6 +711,21 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + [[package]] name = "markup" version = "0.15.0" @@ -761,7 +743,7 @@ checksum = "9ab6ee21fd1855134cacf2f41afdf45f1bc456c7d7f6165d763b4647062dd2be" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn", ] [[package]] @@ -773,17 +755,11 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "migrations_internals" @@ -792,7 +768,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f23f71580015254b020e856feac3df5878c2c7a8812297edd6c0a485ac9dada" dependencies = [ "serde", - "toml", + "toml 0.7.8", ] [[package]] @@ -824,9 +800,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -839,22 +815,48 @@ checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] -name = "nu-ansi-term" -version = "0.46.0" +name = "multer" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "log", + "memchr", + "mime", + "spin", + "tokio", + "tokio-util", + "version_check", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num_cpus" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ @@ -864,9 +866,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -877,6 +879,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "overload" version = "0.1.1" @@ -903,35 +911,38 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project" -version = "1.1.3" +name = "pear" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "4ccca0f6c17acc81df8e242ed473ec144cbf5c98037e69aa6d144780aad103c8" dependencies = [ - "pin-project-internal", + "inlinable_string", + "pear_codegen", + "yansi", ] [[package]] -name = "pin-project-internal" -version = "1.1.3" +name = "pear_codegen" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "2e22670e8eb757cff11d6c199ca7b987f352f0346e0be4dd23869ec72cb53c77" dependencies = [ "proc-macro2", + "proc-macro2-diagnostics", "quote", - "syn 2.0.39", + "syn", ] +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -946,9 +957,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "powerfmt" @@ -963,43 +974,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "proc-macro2" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", + "unicode-ident", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "proc-macro2-diagnostics" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", + "syn", "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" -dependencies = [ - "unicode-ident", + "yansi", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1065,15 +1065,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ref-cast" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.5", "regex-syntax 0.8.2", ] @@ -1088,9 +1108,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -1109,11 +1129,117 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rocket" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e7bb57ccb26670d73b6a47396c83139447b9e7878cab627fdfe9ea8da489150" +dependencies = [ + "async-stream", + "async-trait", + "atomic 0.5.3", + "binascii", + "bytes", + "either", + "figment", + "futures", + "indexmap", + "log", + "memchr", + "multer", + "num_cpus", + "parking_lot", + "pin-project-lite", + "rand", + "ref-cast", + "rocket_codegen", + "rocket_http", + "serde", + "state", + "tempfile", + "time", + "tokio", + "tokio-stream", + "tokio-util", + "ubyte", + "version_check", + "yansi", +] + +[[package]] +name = "rocket_codegen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2238066abf75f21be6cd7dc1a09d5414a671f4246e384e49fe3f8a4936bd04c" +dependencies = [ + "devise", + "glob", + "indexmap", + "proc-macro2", + "quote", + "rocket_http", + "syn", + "unicode-xid", + "version_check", +] + +[[package]] +name = "rocket_http" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a1663694d059fe5f943ea5481363e48050acedd241d46deb2e27f71110389e" +dependencies = [ + "cookie", + "either", + "futures", + "http", + "hyper", + "indexmap", + "log", + "memchr", + "pear", + "percent-encoding", + "pin-project-lite", + "ref-cast", + "serde", + "smallvec", + "stable-pattern", + "state", + "time", + "tokio", + "uncased", +] + +[[package]] +name = "rocket_sync_db_pools" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83f32721ed79509adac4328e97f817a8f55a47c4b64799f6fd6cc3adb6e42ff" +dependencies = [ + "diesel", + "r2d2", + "rocket", + "rocket_sync_db_pools_codegen", + "serde", + "tokio", + "version_check", +] + +[[package]] +name = "rocket_sync_db_pools_codegen" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc890925dc79370c28eb15c9957677093fdb7e8c44966d189f38cedb995ee68" +dependencies = [ + "devise", + "quote", +] + [[package]] name = "rust-embed" -version = "8.0.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40" +checksum = "a82c0bbc10308ed323529fd3c1dce8badda635aa319a5ff0e6466f33b8101e3f" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -1122,23 +1248,23 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.0.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3d8c6fd84090ae348e63a84336b112b5c3918b3bf0493a581f7bd8ee623c29" +checksum = "6227c01b1783cdfee1bcf844eb44594cd16ec71c35305bf1c9fb5aade2735e16" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", "shellexpand", - "syn 2.0.39", + "syn", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.0.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada" +checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665" dependencies = [ "sha2", "walkdir", @@ -1149,29 +1275,20 @@ name = "rust-quote-editor" version = "0.1.0" dependencies = [ "anyhow", - "axum", "currency_rs", "diesel", "diesel_migrations", - "dotenvy", - "hotwire-turbo", - "hotwire-turbo-axum", "itertools", "libsqlite3-sys", "markup", "mime_guess", "once_cell", "regex", + "rocket", + "rocket_sync_db_pools", "rust-embed", - "serde", - "serde_json", "time", - "tokio", - "tower-http", - "tracing", - "tracing-subscriber", "ulid", - "validator", ] [[package]] @@ -1180,6 +1297,19 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -1188,9 +1318,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "same-file" @@ -1210,6 +1340,12 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -1218,63 +1354,41 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", "serde", ] -[[package]] -name = "serde_path_to_error" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" -dependencies = [ - "itoa", - "serde", -] - [[package]] name = "serde_spanned" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", "serde", ] @@ -1300,9 +1414,9 @@ dependencies = [ [[package]] name = "shellexpand" -version = "2.1.2" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" dependencies = [ "dirs", ] @@ -1327,9 +1441,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" @@ -1338,25 +1452,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] -name = "syn" -version = "1.0.109" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable-pattern" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "memchr", +] + +[[package]] +name = "state" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" +dependencies = [ + "loom", ] [[package]] name = "syn" -version = "2.0.39" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -1364,29 +1491,35 @@ dependencies = [ ] [[package]] -name = "sync_wrapper" -version = "0.1.2" +name = "tempfile" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn", ] [[package]] @@ -1401,12 +1534,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -1421,45 +1555,30 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.34.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", - "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1470,7 +1589,18 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] @@ -1496,7 +1626,19 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.4", ] [[package]] @@ -1522,57 +1664,18 @@ dependencies = [ ] [[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.5.0" +name = "toml_edit" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e12e6351354851911bdf8c2b8f2ab15050c567d70a8b9a37ae7b8301a4080d" +checksum = "0c9ffdf896f8daaabf9b66ba8e77ea1ed5ed0f72821b398aba62352e95062951" dependencies = [ - "async-compression", - "base64", - "bitflags 2.4.1", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "http-range-header", - "httpdate", - "iri-string", - "mime", - "mime_guess", - "percent-encoding", - "pin-project-lite", - "tokio", - "tokio-util", - "tower", - "tower-layer", - "tower-service", - "tracing", - "uuid", + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - [[package]] name = "tower-service" version = "0.3.2" @@ -1585,7 +1688,6 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1599,7 +1701,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn", ] [[package]] @@ -1641,35 +1743,56 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ubyte" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" +dependencies = [ + "serde", +] + [[package]] name = "ulid" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e37c4b6cbcc59a8dcd09a6429fbc7890286bcbb79215cea7b38a3c4c0921d93" +checksum = "34778c17965aa2a08913b57e1f34db9b4a63f5de31768b55bf20d2795f921259" dependencies = [ + "getrandom", "rand", + "web-time", ] [[package]] -name = "unicase" -version = "2.7.0" +name = "uncased" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" dependencies = [ + "serde", "version_check", ] [[package]] -name = "unicode-bidi" -version = "0.3.14" +name = "unicase" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] [[package]] name = "unicode-ident" @@ -1678,116 +1801,118 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-normalization" -version = "0.1.22" +name = "unicode-xid" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] -name = "url" -version = "2.5.0" +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna 0.5.0", - "percent-encoding", -] +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] -name = "utf8-width" -version = "0.1.7" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] -name = "uuid" -version = "1.6.1" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ - "getrandom", + "same-file", + "winapi-util", ] [[package]] -name = "validator" -version = "0.16.1" +name = "want" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b92f40481c04ff1f4f61f304d61793c7b56ff76ac1469f1beb199b1445b253bd" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "idna 0.4.0", - "lazy_static", - "regex", - "serde", - "serde_derive", - "serde_json", - "url", - "validator_derive", + "try-lock", ] [[package]] -name = "validator_derive" -version = "0.16.0" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc44ca3088bb3ba384d9aecf40c6a23a676ce23e09bdaca2073d99c207f864af" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ - "if_chain", - "lazy_static", - "proc-macro-error", - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", - "validator_types", + "cfg-if", + "wasm-bindgen-macro", ] [[package]] -name = "validator_types" -version = "0.16.0" +name = "wasm-bindgen-backend" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "111abfe30072511849c5910134e8baf8dc05de4c0e5903d681cbd5c9c4d611e3" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ + "bumpalo", + "log", + "once_cell", "proc-macro2", - "syn 1.0.109", + "quote", + "syn", + "wasm-bindgen-shared", ] [[package]] -name = "valuable" -version = "0.1.0" +name = "wasm-bindgen-macro" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] [[package]] -name = "vcpkg" -version = "0.2.15" +name = "wasm-bindgen-macro-support" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] [[package]] -name = "version_check" -version = "0.9.4" +name = "wasm-bindgen-shared" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] -name = "walkdir" -version = "2.4.0" +name = "web-time" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "2ee269d72cc29bf77a2c4bc689cc750fb39f5cbd493d2205bbb3f5c7779cf7b0" dependencies = [ - "same-file", - "winapi-util", + "js-sys", + "wasm-bindgen", ] -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "winapi" version = "0.3.9" @@ -1819,13 +1944,31 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -1834,13 +1977,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -1849,30 +2007,60 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -1880,44 +2068,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "windows_x86_64_gnullvm" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] -name = "winnow" -version = "0.5.26" +name = "windows_x86_64_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67b5f0a4e7a27a64c651977932b9dc5667ca7fc31ac44b03ed37a0cf42fdfff" -dependencies = [ - "memchr", -] +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] -name = "zstd" -version = "0.13.0" +name = "windows_x86_64_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" -dependencies = [ - "zstd-safe", -] +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] -name = "zstd-safe" -version = "7.0.0" +name = "winnow" +version = "0.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +checksum = "5389a154b01683d28c77f8f68f49dea75f0a4da32557a58f68ee51ebba472d29" dependencies = [ - "zstd-sys", + "memchr", ] [[package]] -name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +name = "yansi" +version = "1.0.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" dependencies = [ - "cc", - "pkg-config", + "is-terminal", ] diff --git a/Cargo.toml b/Cargo.toml index 1d8972b..e5a3955 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,26 +14,17 @@ lto = true [dependencies] anyhow = "1.0" -axum = "0.7" currency_rs = { git = "https://github.com/johnbcodes/currency_rs", branch = "feature/db-diesel2-sqlite", version = "1.1", features = [ "db-diesel2-sqlite" ] } -diesel = { version = "2.1", features = ["r2d2", "sqlite", "time"] } +diesel = { version = "2.1", features = ["sqlite", "time"] } diesel_migrations = "2.1" -dotenvy = "0.15" -hotwire-turbo = "0.1" -hotwire-turbo-axum = "0.1" itertools = "0.12" libsqlite3-sys = { version = "0.27", features = ["bundled"] } markup = "0.15" mime_guess = "2" once_cell = "1" regex = "1" +rocket = "0.5" +rocket_sync_db_pools = { version = "0.1", features = ["diesel_sqlite_pool"]} rust-embed = { version = "8", features = ["interpolate-folder-path"] } -serde = { version = "1", features = ["derive"] } -serde_json = "1" time = { version = "0.3", features = ["formatting", "macros", "parsing", "serde"] } -tokio = { version = "1", features = ["full"] } -tower-http = { version = "0.5", features = ["full"] } -tracing = "0.1" -tracing-subscriber = { version = "0.3", features = ["env-filter"] } ulid = "1.1" -validator = { version = "0.16", features = ["derive"] } diff --git a/Dockerfile b/Dockerfile index 1193757..84d9500 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,10 +15,11 @@ RUN USER=root cargo new --bin app WORKDIR /app # copy over infrequently changing files -COPY package.json package-lock.json Cargo.lock Cargo.toml ./ -# copy your source tree, ordered again by infrequent to frequently changed files COPY tailwind.config.js ./ COPY build.rs ./ +COPY Rocket.toml ./ +COPY package.json package-lock.json Cargo.lock Cargo.toml ./ +# copy your source tree, ordered again by infrequent to frequently changed files COPY ./migrations ./migrations COPY ./ui ./ui COPY ./src ./src @@ -38,7 +39,7 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \ ## Deploy locally FROM debug as dev -ENV DATABASE_URL=sqlite://data/demo.db +ENV ROCKET_PROFILE=docker EXPOSE 8080 @@ -65,9 +66,10 @@ WORKDIR / RUN mkdir data +COPY --from=release /app/Rocket.toml . COPY --from=release /usr/local/cargo/bin/demo . -ENV DATABASE_URL=sqlite://data/demo.db +ENV ROCKET_PROFILE=docker EXPOSE 8080 diff --git a/README.md b/README.md index 0c12e21..a53c922 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ > Rust implementation of the quote editor from [Turbo Rails Tutorial](https://www.hotrails.dev/turbo-rails). +### TODO +* Group queries in run block where possible + ### Motivation and caveats The main motivation is learning to develop web applications with Rust and JavaScript combined. It now includes @@ -9,7 +12,7 @@ the following stack: * [htmx](https://htmx.org/) * [hyperscript](https://hyperscript.org/) -* [Axum](https://github.com/tokio-rs/axum) +* [Rocket](https://rocket.rs/) * [Diesel](https://diesel.rs/) * [markup.rs](https://github.com/utkarshkukreti/markup.rs) * Custom Rust / NPM build integration @@ -18,6 +21,7 @@ the following stack: In the past it included these technologies: * [Hotwire Turbo](https://turbo.hotwired.dev/) +* [Axum](https://github.com/tokio-rs/axum) * [Rusqlite](https://github.com/rusqlite/rusqlite) Some features of the tutorial were intentionally left out and possibly will be worked on in the future: @@ -29,11 +33,9 @@ Additionally, there were some other features and integral parts of Rails that ha * The look and feel deviates from [demo](https://www.hotrails.dev/quotes) because the author has made some UI enhancements that are not in the tutorial * Viewports less than tablet sizing -* Proper validation error messages ("to_sentence" on ValidationErrors struct for flash message) -* Only add border color to fields with errors * Labels for input fields * Delete confirmation -* Probably a few others +* ...probably a few others ## Getting Started @@ -62,7 +64,7 @@ Additionally, there were some other features and integral parts of Rails that ha * Create volume with `docker volume create db-data` * Build with `docker build -t rust-quote-editor .` -* Run with `docker run -itd -e "DATABASE_URL=sqlite:///data/demo.db" -p 8080:8080 -v db-data:/data rust-quote-editor` +* Run with `docker run -itd -p 8080:8080 -v db-data:/data rust-quote-editor` #### Docker Compose @@ -78,12 +80,11 @@ Additionally, there were some other features and integral parts of Rails that ha * Update `primary_region` property in `fly.toml` * `fly volumes create -s 1 -r ` * Update `mounts.source` property in `fly.toml` with -* `fly secrets set DATABASE_URL=/data/demo.db` * `docker build -t registry.fly.io/: --target deploy .` * `fly deploy --image registry.fly.io/:` ## Automated deployment of new versions with GitHub [action](.github/workflows/deploy.yml) -* [Set up](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions) your `FLY_API_TOKEN` secret in your repository +* [Set up](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions) your `FLY_API_TOKEN` [secret](https://fly.io/docs/reference/deploy-tokens/) in your repository * Tag release with a tag name starting with 'v' * Example: `git tag -a v2 -m "My new release!" && git push --tags` diff --git a/Rocket.toml b/Rocket.toml new file mode 100644 index 0000000..6a1380a --- /dev/null +++ b/Rocket.toml @@ -0,0 +1,13 @@ +[default] +log_level = "debug" + +[default.databases.demo] +url = "data/demo.db" +timeout = 10 + +[docker] +address = "0.0.0.0" + +[docker.databases.demo] +url = "/data/demo.db" +timeout = 10 diff --git a/docker-compose.yml b/docker-compose.yml index 30a9347..95e3338 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,10 +4,8 @@ services: web.app: build: target: dev - environment: - - DATABASE_URL=/data/demo.db ports: - - "8080:8080" + - "8000:8000" volumes: - db-data:/data diff --git a/fly.toml b/fly.toml index 20d1c85..8c6d656 100644 --- a/fly.toml +++ b/fly.toml @@ -8,11 +8,11 @@ kill_timeout = 5 PORT = "8080" [mounts] -source = "jbc_ah_data" +source = "jbc_qe_data" destination = "/data" [[services]] -internal_port = 8080 +internal_port = 8000 protocol = "tcp" [services.concurrency] @@ -31,6 +31,6 @@ port = 443 [[services.tcp_checks]] grace_period = "1s" interval = "15s" -port = "8080" +port = "8000" restart_limit = 6 timeout = "2s" diff --git a/src/assets.rs b/src/assets.rs index 209c9c8..a2c6086 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -1,54 +1,48 @@ -use axum::{ - body::Body, - http::{header, StatusCode, Uri}, - response::{IntoResponse, Response}, +use rocket::{ + fairing::AdHoc, + http::{ContentType, Header}, + response::Responder, }; use rust_embed::RustEmbed; -use tracing::info; +use std::borrow::Cow; +use std::ffi::OsStr; +use std::path::PathBuf; #[derive(RustEmbed)] #[folder = "$CARGO_MANIFEST_DIR/ui/target/public/"] -pub(crate) struct Assets; - -pub(crate) struct StaticFile(pub(crate) T); +pub(crate) struct Asset; + +#[derive(Responder)] +#[response(status = 200)] +struct AssetResponse { + content: Cow<'static, [u8]>, + content_type: ContentType, + max_age: Header<'static>, +} #[cfg(debug_assertions)] const MAX_AGE: &str = "max-age=120"; #[cfg(not(debug_assertions))] const MAX_AGE: &str = "max-age=31536000"; -impl IntoResponse for StaticFile -where - T: Into, -{ - fn into_response(self) -> Response { - let path = self.0.into(); - - match Assets::get(path.as_str()) { - Some(content) => { - info!("Retrieving asset with path: {path}"); - let body = Body::from(content.data); - let mime = mime_guess::from_path(path).first_or_octet_stream(); - Response::builder() - .header(header::CONTENT_TYPE, mime.as_ref()) - .header(header::CACHE_CONTROL, MAX_AGE) - .body(body) - .unwrap() - } - None => Response::builder() - .status(StatusCode::NOT_FOUND) - .body(Body::from("Not Found")) - .unwrap(), - } - } +pub(crate) fn stage() -> AdHoc { + AdHoc::on_ignite("Assets Stage", |rocket| async { + rocket.mount("/dist", routes![asset_handler]) + }) } -pub(crate) async fn asset_handler(uri: Uri) -> impl IntoResponse { - let mut path = uri.path().trim_start_matches('/').to_string(); - - if path.starts_with("dist/") { - path = path.replace("dist/", ""); - } - - StaticFile(path) +#[get("/")] +fn asset_handler(file: PathBuf) -> Option { + let filename = file.display().to_string(); + let asset = Asset::get(&filename)?; + let content_type = file + .extension() + .and_then(OsStr::to_str) + .and_then(ContentType::from_extension) + .unwrap_or(ContentType::Bytes); + Some(AssetResponse { + content: asset.data, + content_type, + max_age: Header::new("Cache-Control", MAX_AGE), + }) } diff --git a/src/currency.rs b/src/currency.rs index a2fcc61..d4667e7 100644 --- a/src/currency.rs +++ b/src/currency.rs @@ -2,4 +2,4 @@ use once_cell::sync::Lazy; use regex::Regex; pub(crate) static FORM_CURRENCY_REGEX: Lazy = - Lazy::new(|| Regex::new(r"^\d*(\.\d{2})?$").unwrap()); + Lazy::new(|| Regex::new(r"^\d+(\.\d{2})?$").unwrap()); diff --git a/src/error.rs b/src/error.rs index 092af7b..67a5977 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,19 +1,14 @@ -use axum::{ - http::StatusCode, - response::{IntoResponse, Response}, +use rocket::{ + response::{Debug, Responder, Result}, + Request, }; // Make our own error that wraps `anyhow::Error`. pub(crate) struct AppError(anyhow::Error); -// Tell axum how to convert `AppError` into a response. -impl IntoResponse for AppError { - fn into_response(self) -> Response { - ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("Something went wrong: {}", self.0), - ) - .into_response() +impl<'r> Responder<'r, 'r> for AppError { + fn respond_to(self, request: &Request<'_>) -> Result<'r> { + Debug(self.0).respond_to(request) } } diff --git a/src/forms.rs b/src/forms.rs new file mode 100644 index 0000000..bfd9c3f --- /dev/null +++ b/src/forms.rs @@ -0,0 +1,56 @@ +use crate::{currency::FORM_CURRENCY_REGEX, time::DATE_REGEX}; +use once_cell::sync::Lazy; +use regex::Regex; +use rocket::form::{Contextual, Form}; + +pub(crate) static QUANTITY_REGEX: Lazy = Lazy::new(|| Regex::new(r"^\d+$").unwrap()); + +pub(crate) fn css_for_field<'b, T>( + form: &Form>, + field: &'b str, + default_class: &'b str, + error_class: &'b str, +) -> String { + if form.context.exact_field_errors(field).count() == 0 { + default_class.to_string() + } else { + format!("{} {}", default_class, error_class) + } +} + +pub(crate) fn validate_date<'v>(date: &str) -> rocket::form::Result<'v, ()> { + if date.is_empty() { + Err(rocket::form::Error::validation("Please enter a date"))?; + } + if !DATE_REGEX.is_match(date) { + Err(rocket::form::Error::validation("Please enter a valid date"))?; + } + + Ok(()) +} + +pub(crate) fn validate_amount<'v>(amount: &str) -> rocket::form::Result<'v, ()> { + if amount.is_empty() { + Err(rocket::form::Error::validation("Please enter an amount"))?; + } + if !FORM_CURRENCY_REGEX.is_match(amount) { + Err(rocket::form::Error::validation( + "Please enter a valid amount", + ))?; + } + + Ok(()) +} + +pub(crate) fn validate_quantity<'v>(quantity: &str) -> rocket::form::Result<'v, ()> { + if quantity.is_empty() { + Err(rocket::form::Error::validation("Please enter a quantity"))?; + } + if !QUANTITY_REGEX.is_match(quantity) { + Err(rocket::form::Error::validation( + "Please enter a valid quantity", + ))?; + } + + Ok(()) +} diff --git a/src/line_item_dates/controller.rs b/src/line_item_dates/controller.rs index 2939d6d..fe78c5e 100644 --- a/src/line_item_dates/controller.rs +++ b/src/line_item_dates/controller.rs @@ -1,179 +1,163 @@ use crate::{ line_item_dates::{ self, - model::{DeleteForm, LineItemDateForm, LineItemDatePresenter}, - view::{Create, Destroy, EditForm, LineItemDateInfo, NewForm, Update}, + model::{DeleteForm, EditLineItemDateForm, LineItemDatePresenter, NewLineItemDateForm}, + view::*, }, line_items::{self, model::LineItemPresenter}, - quotes, Result, + quotes, + rocket_ext::HtmxResponder, + Db, Result, }; -use axum::{ - extract::{Path, State}, - response::{Html, IntoResponse}, +use rocket::{ + fairing::AdHoc, + form::{Contextual, Form}, + http::Header, + response::content::RawHtml, }; -use diesel::prelude::SqliteConnection; -use diesel::r2d2::{ConnectionManager, Pool}; -use std::time::Instant; -use tracing::info; -use validator::Validate; -pub(crate) async fn line_item_date( - State(pool): State>>, - Path(id): Path, -) -> Result { - let start = Instant::now(); - let record = line_item_dates::query::read(&pool, id).await?; - let duration = start.elapsed().as_micros(); - info!("lid - read duration: {duration} μs"); +pub(crate) fn stage() -> AdHoc { + AdHoc::on_ignite("LineItemDate Stage", |rocket| async { + rocket.mount( + "/line_item_dates", + routes![line_item_date, new, create, edit, update, delete], + ) + }) +} + +#[get("/")] +async fn line_item_date(db: Db, id: String) -> Result> { + let record = db + .run(move |conn| { + let quote = line_item_dates::query::read(conn, &id)?; + Result::Ok(quote) + }) + .await?; let template = LineItemDateInfo { line_item_date: &record.into(), }; - Ok(Html(template.to_string())) + Ok(RawHtml(template.to_string())) } -pub(crate) async fn new( - State(pool): State>>, - Path(quote_id): Path, -) -> Result { - let start = Instant::now(); - let quote = quotes::query::read(&pool, quote_id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - let line_item_date = LineItemDatePresenter::from_quote_with_total(quote); - let duration = start.elapsed().as_micros(); - info!("lid - read duration: {duration} μs"); - Ok(Html( - NewForm { - dom_id: &line_item_date.dom_id(), - line_item_date: &line_item_date, - error_message: None, - } - .to_string(), - )) +#[get("/new/")] +pub(crate) async fn new(quote_id: &str) -> Result> { + let template = NewForm { quote_id }; + let html = template.to_string(); + Ok(RawHtml(html)) } +#[post("/create", data = "
")] pub(crate) async fn create( - State(pool): State>>, - axum::Form(form): axum::Form, -) -> Result { - let result = form.validate(); - match result { - Ok(_) => { - let start = Instant::now(); - let line_item_date = line_item_dates::query::insert(&pool, &form).await?; - let duration = start.elapsed().as_micros(); - info!("lid - insert duration: {duration} μs"); - Ok(Html( - Create { - line_item_date: &line_item_date.into(), - line_items: &Vec::new(), - message: "Date was successfully created.", - } - .to_string(), - ) - .into_response()) + db: Db, + form: Form>, +) -> Result { + print!("Form:\n{form:?}"); + match form.value { + Some(ref lid_form) => { + let lid_form = lid_form.clone(); + let line_item_date = db + .run(move |conn| { + let record = line_item_dates::query::insert(conn, &lid_form)?; + Result::Ok(record) + }) + .await?; + + let content = Create { + line_item_date: &line_item_date.into(), + line_items: &Vec::new(), + message: "Date was successfully created.", + } + .to_string(); + + Ok(HtmxResponder::Ok(content)) } - Err(errors) => { - info!("ValidationErrors:\n{:?}", errors); - let error_message = String::from("Test"); - let line_item_date: &LineItemDatePresenter = &form.into(); - Ok(Html( - NewForm { - dom_id: &line_item_date.dom_id(), - line_item_date, - error_message: Some(error_message), - } - .to_string(), - ) - .into_response()) + None => { + let template = NewFormWithErrors { form: &form }; + let content = template.to_string(); + Ok(HtmxResponder::Retarget { + content, + retarget: Header::new("HX-Retarget", "#line_item_date_new".to_string()), + reswap: Header::new("HX-Reswap", "outerhtml".to_string()), + }) } } } -pub(crate) async fn edit( - State(pool): State>>, - Path(id): Path, -) -> Result { - let start = Instant::now(); - let record = line_item_dates::query::read(&pool, id).await?; - let duration = start.elapsed().as_micros(); - info!("lid - read duration: {duration} μs"); +#[get("/edit/")] +pub(crate) async fn edit(db: Db, id: String) -> Result> { + let record = db + .run(move |conn| { + let quote = line_item_dates::query::read(conn, &id)?; + Result::Ok(quote) + }) + .await?; + let line_item_date: &LineItemDatePresenter = &record.into(); - Ok(Html( - EditForm { - dom_id: &line_item_date.edit_dom_id(), - line_item_date, - error_message: None, - } - .to_string(), - )) + let template = EditForm { line_item_date }; + let html = template.to_string(); + Ok(RawHtml(html)) } +#[post("/update", data = "")] pub(crate) async fn update( - State(pool): State>>, - axum::Form(form): axum::Form, -) -> Result { - let result = form.validate(); - match result { - Ok(_) => { - let start = Instant::now(); - let line_item_date = line_item_dates::query::update(&pool, &form).await?; - let duration = start.elapsed().as_micros(); - info!("lid - update duration: {duration} μs"); - let start = Instant::now(); - let line_items = line_items::query::all_for_line_item_date(&pool, &line_item_date.id) - .await? - .into_iter() - .map(|record| record.into()) - .collect::>(); - let duration = start.elapsed().as_micros(); - info!("li - read all duration: {duration} μs"); - Ok(Html( - Update { - line_item_date: &line_item_date.into(), - line_items: &line_items, - message: "Date was successfully updated.", - } - .to_string(), - ) - .into_response()) + db: Db, + form: Form>, +) -> Result> { + print!("Form:\n{form:?}"); + match form.value { + Some(ref lid_form) => { + let lid_form = lid_form.clone(); + let line_item_date = db + .run(move |conn| { + let record = line_item_dates::query::update(conn, &lid_form)?; + Result::Ok(record) + }) + .await?; + + let lid_id = line_item_date.id.clone(); + let line_items = db + .run(move |conn| { + let line_items = line_items::query::all_for_line_item_date(conn, &lid_id)? + .into_iter() + .map(|record| record.into()) + .collect::>(); + Result::Ok(line_items) + }) + .await?; + + let content = Update { + line_item_date: &line_item_date.into(), + line_items: &line_items, + message: "Date was successfully updated.", + } + .to_string(); + + Ok(RawHtml(content)) } - Err(errors) => { - info!("ValidationErrors:\n{:?}", errors); - let error_message = String::from("Test"); - let line_item_date: &LineItemDatePresenter = &form.into(); - Ok(Html( - EditForm { - dom_id: &line_item_date.edit_dom_id(), - line_item_date, - error_message: Some(error_message), - } - .to_string(), - ) - .into_response()) + None => { + let template = EditFormWithErrors { form: &form }; + let content = template.to_string(); + Ok(RawHtml(content)) } } } -pub(crate) async fn delete( - State(pool): State>>, - axum::Form(form): axum::Form, -) -> Result { - let start = Instant::now(); - let line_item_date = line_item_dates::query::delete(&pool, &form.id).await?; - let duration = start.elapsed().as_micros(); - info!("lid - delete duration: {duration} μs"); - let start = Instant::now(); - let quote = quotes::query::read(&pool, &line_item_date.quote_id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - Ok(Html( +#[post("/delete", data = "")] +async fn delete(db: Db, form: Form) -> Result> { + let quote = db + .run(move |conn| { + let line_item_date = line_item_dates::query::delete(conn, &form.id)?; + let quote = quotes::query::read(conn, &line_item_date.quote_id)?; + Result::Ok(quote) + }) + .await?; + + Ok(RawHtml( Destroy { quote: "e.into(), message: "Date was successfully destroyed.", } .to_string(), - ) - .into_response()) + )) } diff --git a/src/line_item_dates/model.rs b/src/line_item_dates/model.rs index ddcf5e7..dd008f3 100644 --- a/src/line_item_dates/model.rs +++ b/src/line_item_dates/model.rs @@ -1,13 +1,12 @@ use crate::{ + forms::validate_date, quotes::model::QuoteWithTotal, schema::line_item_dates, - time::{long_form, parse_date, short_form, DATE_REGEX}, + time::{long_form, parse_date, short_form}, }; use diesel::prelude::*; -use serde::Deserialize; use time::{Date, OffsetDateTime}; use ulid::Ulid; -use validator::Validate; #[derive(Debug, Insertable, Queryable)] pub struct LineItemDate { @@ -18,11 +17,11 @@ pub struct LineItemDate { pub updated_at: OffsetDateTime, } -impl From<&LineItemDateForm> for LineItemDate { - fn from(value: &LineItemDateForm) -> Self { +impl From<&EditLineItemDateForm> for LineItemDate { + fn from(value: &EditLineItemDateForm) -> Self { let date = parse_date(&value.date); LineItemDate { - id: value.id.clone().unwrap_or(Ulid::new().to_string()), + id: value.id.clone(), quote_id: value.quote_id.clone(), date, created_at: OffsetDateTime::now_utc(), @@ -31,14 +30,35 @@ impl From<&LineItemDateForm> for LineItemDate { } } -#[derive(Debug, Deserialize, Validate)] -pub(crate) struct LineItemDateForm { - #[validate(length(min = 1, message = "can't be blank"))] - pub(crate) id: Option, - #[validate(length(min = 1, message = "can't be blank"))] - pub(crate) quote_id: String, - #[validate(regex(path = "DATE_REGEX"))] - pub(crate) date: String, +impl From<&NewLineItemDateForm> for LineItemDate { + fn from(value: &NewLineItemDateForm) -> Self { + let date = parse_date(&value.date); + LineItemDate { + id: Ulid::new().to_string(), + quote_id: value.quote_id.clone(), + date, + created_at: OffsetDateTime::now_utc(), + updated_at: OffsetDateTime::now_utc(), + } + } +} + +#[derive(Clone, Debug, FromForm)] +pub struct EditLineItemDateForm { + #[field(validate = len(1..))] + pub id: String, + #[field(validate = len(1..))] + pub quote_id: String, + #[field(validate = validate_date())] + pub date: String, +} + +#[derive(Clone, Debug, FromForm)] +pub struct NewLineItemDateForm { + #[field(validate = len(1..))] + pub quote_id: String, + #[field(validate = validate_date())] + pub date: String, } #[derive(Debug, Default)] @@ -96,18 +116,29 @@ impl From for LineItemDatePresenter { } } -impl From for LineItemDatePresenter { - fn from(value: LineItemDateForm) -> Self { +impl From for LineItemDatePresenter { + fn from(value: EditLineItemDateForm) -> Self { + let date = parse_date(&value.date); + LineItemDatePresenter { + id: Some(value.id), + quote_id: value.quote_id, + date: Some(date), + } + } +} + +impl From for LineItemDatePresenter { + fn from(value: NewLineItemDateForm) -> Self { let date = parse_date(&value.date); LineItemDatePresenter { - id: value.id, + id: None, quote_id: value.quote_id, date: Some(date), } } } -#[derive(Debug, Deserialize)] +#[derive(Debug, FromForm)] pub(crate) struct DeleteForm { pub(crate) id: String, } diff --git a/src/line_item_dates/query.rs b/src/line_item_dates/query.rs index e8ae1e2..158708b 100644 --- a/src/line_item_dates/query.rs +++ b/src/line_item_dates/query.rs @@ -1,33 +1,23 @@ use crate::{ - line_item_dates::model::{LineItemDate, LineItemDateForm}, + line_item_dates::model::{EditLineItemDateForm, LineItemDate, NewLineItemDateForm}, line_items, schema::line_item_dates, Result, }; use diesel::prelude::*; -use diesel::r2d2::{ConnectionManager, Pool, PooledConnection}; -pub(crate) async fn all>( - pool: &Pool>, +pub(crate) fn all>( + connection: &mut SqliteConnection, id: S, ) -> Result> { - let mut connection = pool.get()?; let records = line_item_dates::table .filter(line_item_dates::quote_id.eq(&id.as_ref())) - .get_results(&mut connection)?; + .get_results(connection)?; Ok(records) } -pub(crate) async fn read>( - pool: &Pool>, - id: S, -) -> Result { - let mut connection = pool.get()?; - read_from_connection(&mut connection, id) -} - -fn read_from_connection>( - connection: &mut PooledConnection>, +pub(crate) fn read>( + connection: &mut SqliteConnection, id: S, ) -> Result { let record = line_item_dates::table @@ -36,45 +26,41 @@ fn read_from_connection>( Ok(record) } -pub(crate) async fn insert( - pool: &Pool>, - form: &LineItemDateForm, +pub(crate) fn insert( + connection: &mut SqliteConnection, + form: &NewLineItemDateForm, ) -> Result { let record: LineItemDate = form.into(); - let mut connection = pool.get()?; diesel::dsl::insert_into(line_item_dates::table) .values(&record) - .execute(&mut connection)?; + .execute(connection)?; Ok(record) } -pub(crate) async fn update( - pool: &Pool>, - form: &LineItemDateForm, +pub(crate) fn update( + connection: &mut SqliteConnection, + form: &EditLineItemDateForm, ) -> Result { let record: LineItemDate = form.into(); - let mut connection = pool.get()?; diesel::dsl::update(line_item_dates::table) .set(( line_item_dates::date.eq(&record.date), line_item_dates::updated_at.eq(&record.updated_at), )) .filter(line_item_dates::id.eq(&record.id)) - .execute(&mut connection)?; + .execute(connection)?; - read_from_connection(&mut connection, &record.id) + read(connection, &record.id) } -pub(crate) async fn delete>( - pool: &Pool>, +pub(crate) fn delete>( + connection: &mut SqliteConnection, id: S, ) -> Result { - let mut connection = pool.get()?; - - let record = read_from_connection(&mut connection, &id)?; + let record = read(connection, &id)?; _ = connection.transaction::<_, _, _>(|tx| { line_items::query::delete_all_for_date(tx, &id)?; @@ -88,10 +74,7 @@ pub(crate) async fn delete>( Ok(record) } -pub(crate) fn delete_all_for_quote>( - tx: &mut PooledConnection>, - id: S, -) -> Result { +pub(crate) fn delete_all_for_quote>(tx: &mut SqliteConnection, id: S) -> Result { line_items::query::delete_all_for_quote(tx, &id)?; _ = diesel::dsl::delete(line_item_dates::table) diff --git a/src/line_item_dates/view.rs b/src/line_item_dates/view.rs index e9e6e22..306635c 100644 --- a/src/line_item_dates/view.rs +++ b/src/line_item_dates/view.rs @@ -1,9 +1,11 @@ use crate::{ + forms::css_for_field, layout::Flash, - line_item_dates::model::LineItemDatePresenter, + line_item_dates::model::{EditLineItemDateForm, LineItemDatePresenter, NewLineItemDateForm}, line_items::{model::LineItemPresenter, view::LineItem}, quotes::{model::QuotePresenter, view::SwapFooter}, }; +use rocket::form::{Contextual, Form}; markup::define! { LineItemDate<'a>(line_item_date: &'a LineItemDatePresenter, line_items: &'a Vec) { @@ -73,34 +75,32 @@ markup::define! { } } - EditForm<'a>(dom_id: &'a String, line_item_date: &'a LineItemDatePresenter, error_message: Option) { - div[id = dom_id] { - form[id = {format!("form_{}", dom_id)}, + EditForm<'a>(line_item_date: &'a LineItemDatePresenter) { + div[id = line_item_date.edit_dom_id()] { + form[id = {format!("form_{}", &line_item_date.edit_dom_id())}, "hx-post" = "/line_item_dates/update", "hx-target" = {format!("#{}", &line_item_date.dom_id())}, "hx-swap" = "outerHTML", class = "flex flex-wrap justify-between items-center gap-2 mt-8 mb-1.5", autocomplete = "off", + novalidate, "accept-charset" = "UTF-8"] { - @let form_input_class = if error_message.is_some() { "form-input border-primary" } else { "form-input" }; - @if let Some(message) = error_message { - div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { @message } - } - @if let Some(id) = &line_item_date.id { - input[id = "line_item_date_id", - name = "id", - "type" = "hidden", - value = id] {} - } + + input[id = "id", + name = "id", + disabled, + "type" = "hidden", + value = &line_item_date.id.clone().unwrap()] {} input[id = "quote_id", name = "quote_id", + disabled, "type" = "hidden", value = &line_item_date.quote_id] {} div[class = "[flex:1]"] { label[class = "visually-hidden", "for" = "line_item_date_date"] { "Date" } input[id = "line_item_date_date", name = "date", - class = form_input_class, + class = "form-input", autofocus = "autofocus", required, "type" = "date", @@ -120,38 +120,130 @@ markup::define! { } } - NewForm<'a>(dom_id: &'a String, line_item_date: &'a LineItemDatePresenter, error_message: Option) { - div[id = dom_id] { + EditFormWithErrors<'a, 'r>(form: &'a Form>) { + @let context = &form.context; + @let id = context.field_value("id").unwrap_or(""); + @let quote_id = context.field_value("quote_id").unwrap_or(""); + @let date = context.field_value("date").unwrap_or(""); + @let dom_id = format!("line_item_date_{}", &id); + @let edit_dom_id = format!("edit_line_item_date_{}", &id); + div[id = &dom_id] { + form[id = {format!("form_{}", &edit_dom_id)}, + "hx-post" = "/line_item_dates/update", + "hx-target" = {format!("#{}", &dom_id)}, + "hx-swap" = "outerHTML", + class = "flex flex-wrap justify-between items-center gap-2 mt-8 mb-1.5", + autocomplete = "off", + novalidate, + "accept-charset" = "UTF-8"] { + + @let messages = context.errors().map(|item| item.to_string()).collect::>(); + div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { + @for message in messages { + p { @message } + } + } + + input[id = "id", + name = "id", + "type" = "hidden", + value = &id] {} + input[id = "quote_id", + name = "quote_id", + "type" = "hidden", + value = "e_id] {} + div[class = "[flex:1]"] { + label[class = "visually-hidden", "for" = "line_item_date_date"] { "Date" } + input[id = "line_item_date_date", + name = "date", + class = css_for_field(form, "date", "form-input", "border-primary"), + autofocus = "autofocus", + required, + "type" = "date", + value = &date] {} + } + a[class = "button button-light", + "hx-get" = {format!("/line_item_dates/{}", id)}, + "hx-target" = {format!("#{}", edit_dom_id)}, + "hx-trigger" = "click", + "hx-swap" = "outerHTML"] { "Cancel" } + input[name = "commit", + "type" = "submit", + value = "Update date", + class = "button button-secondary", + "_" = "on click add { pointer-events: none }"] {} + } + } + } + + NewForm<'a>(quote_id: &'a str) { + div[id = "line_item_date_new"] { form[id = "form_new", "hx-post" = "/line_item_dates/create", "hx-target" = "#line_item_dates", "hx-swap" = "afterbegin", class = "flex flex-wrap justify-between items-center gap-2 mt-8 mb-1.5", autocomplete = "off", + novalidate, "accept-charset" = "UTF-8"] { - @let form_input_class = if error_message.is_some() { "form-input border-primary" } else { "form-input" }; - @if let Some(message) = error_message { - div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { @message } + + input[id = "quote_id", + name = "quote_id", + "type" = "hidden", + value = "e_id] {} + div[class = "[flex:1]"] { + label[class = "visually-hidden", "for" = "line_item_date_date"] { "Date" } + input[id = "line_item_date_date", + name = "date", + class = "form-input", + autofocus = "autofocus", + required, + "type" = "date"] {} } - @if let Some(id) = &line_item_date.id { - input[id = "line_item_date_id", - name = "id", - "type" = "hidden", - value = id] {} + a[class = "button button-light", + "_" = "on click remove #form_new"] { "Cancel" } + input[name = "commit", + "type" = "submit", + value = "Create date", + class = "button button-secondary", + "_" = "on click add { pointer-events: none }"] {} + } + } + } + + NewFormWithErrors<'a, 'r>(form: &'a Form>) { + @let quote_id = form.context.field_value("quote_id").unwrap_or(""); + @let date = form.context.field_value("date").unwrap_or(""); + div[id = "line_item_date_new"] { + form[id = "form_new", + "hx-post" = "/line_item_dates/create", + "hx-target" = "#line_item_dates", + "hx-swap" = "afterbegin", + class = "flex flex-wrap justify-between items-center gap-2 mt-8 mb-1.5", + autocomplete = "off", + novalidate, + "accept-charset" = "UTF-8"] { + + @let messages = form.context.errors().map(|item| item.to_string()).collect::>(); + div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { + @for message in messages { + p { @message } + } } + input[id = "quote_id", name = "quote_id", "type" = "hidden", - value = &line_item_date.quote_id] {} + value = "e_id] {} div[class = "[flex:1]"] { label[class = "visually-hidden", "for" = "line_item_date_date"] { "Date" } input[id = "line_item_date_date", name = "date", - class = form_input_class, + class = css_for_field(form, "date", "form-input", "border-primary"), autofocus = "autofocus", required, "type" = "date", - value = line_item_date.date_short_form()] {} + value = &date] {} } a[class = "button button-light", "_" = "on click remove #form_new"] { "Cancel" } diff --git a/src/line_items/controller.rs b/src/line_items/controller.rs index 08c638a..90bc4b0 100644 --- a/src/line_items/controller.rs +++ b/src/line_items/controller.rs @@ -2,191 +2,187 @@ use crate::{ line_item_dates, line_items::{ self, - model::{DeleteForm, LineItemForm, LineItemPresenter}, - view::{Create, Destroy, EditForm, LineItem, NewForm, Update}, + model::{DeleteForm, EditLineItemForm, LineItemPresenter, NewLineItemForm}, + view::*, }, - quotes, Result, + quotes, + rocket_ext::HtmxResponder, + Db, Result, }; -use axum::{ - extract::{Path, State}, - response::{Html, IntoResponse}, +use rocket::{ + fairing::AdHoc, + form::{Contextual, Form}, + http::Header, + response::content::RawHtml, }; -use diesel::prelude::SqliteConnection; -use diesel::r2d2::{ConnectionManager, Pool}; -use std::time::Instant; -use tracing::info; -use validator::Validate; - -pub(crate) async fn line_item( - State(pool): State>>, - Path(id): Path, -) -> Result { - let start = Instant::now(); - let line_item = line_items::query::read(&pool, id).await?; - let duration = start.elapsed().as_micros(); - info!("li - read duration: {duration} μs"); + +pub(crate) fn stage() -> AdHoc { + AdHoc::on_ignite("LineItem Stage", |rocket| async { + rocket.mount( + "/line_items", + routes![line_item, new, create, edit, update, delete], + ) + }) +} + +#[get("/")] +async fn line_item(db: Db, id: String) -> Result> { + let line_item = db + .run(move |conn| { + let line_item = line_items::query::read(conn, id)?; + Result::Ok(line_item) + }) + .await?; let template = LineItem { line_item: &line_item.into(), }; - Ok(Html(template.to_string())) + Ok(RawHtml(template.to_string())) } -pub(crate) async fn new( - State(pool): State>>, - Path(line_item_date_id): Path, -) -> Result { - let start = Instant::now(); - let quote = quotes::query::from_line_item_date_id(&pool, &line_item_date_id).await?; - let duration = start.elapsed().as_micros(); - info!("lid - read duration: {duration} μs"); - Ok(Html( +#[get("/new/")] +async fn new(db: Db, line_item_date_id: String) -> Result> { + let lid_id = line_item_date_id.clone(); + let quote = db + .run(move |conn| { + let quote = quotes::query::from_line_item_date_id(conn, &lid_id)?; + Result::Ok(quote) + }) + .await?; + + Ok(RawHtml( NewForm { line_item: &LineItemPresenter::from_line_item_date(line_item_date_id), quote: "e.into(), - error_message: None, } .to_string(), )) } -pub(crate) async fn create( - State(pool): State>>, - axum::Form(form): axum::Form, -) -> Result { - let result = form.validate(); - match result { - Ok(_) => { - let start = Instant::now(); - let line_item = line_items::query::insert(&pool, &form).await?; - let duration = start.elapsed().as_micros(); - info!("li - insert duration: {duration} μs"); - let start = Instant::now(); - let quote = quotes::query::read(&pool, &form.quote_id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - Ok(Html( - Create { - line_item: &line_item.into(), - quote: "e.into(), - message: "Item was successfully created.", - } - .to_string(), - ) - .into_response()) +#[post("/create", data = "")] +async fn create(db: Db, form: Form>) -> Result { + print!("Form:\n{form:?}"); + match form.value { + Some(ref li_form) => { + let quote_id = li_form.quote_id.clone(); + let li_form = li_form.clone(); + let line_item = db + .run(move |conn| { + let line_item = line_items::query::insert(conn, &li_form)?; + Result::Ok(line_item) + }) + .await?; + + let quote = db + .run(move |conn| { + let quote = quotes::query::read(conn, "e_id)?; + Result::Ok(quote) + }) + .await?; + + let content = Create { + line_item: &line_item.into(), + quote: "e.into(), + message: "Item was successfully created.", + } + .to_string(); + + Ok(HtmxResponder::Ok(content)) } - Err(errors) => { - info!("ValidationErrors:\n{:?}", errors); - let start = Instant::now(); - let quote = quotes::query::read(&pool, &form.quote_id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - let error_message = String::from("Test"); - Ok(Html( - NewForm { - line_item: &form.into(), - quote: "e.into(), - error_message: Some(error_message), - } - .to_string(), - ) - .into_response()) + None => { + let template = NewFormWithErrors { form: &form }; + let content = template.to_string(); + let line_item_date_id = form.context.field_value("line_item_date_id").unwrap_or(""); + let retarget = format!("#line_item_date_{}_line_item_new", line_item_date_id); + Ok(HtmxResponder::Retarget { + content, + retarget: Header::new("HX-Retarget", retarget), + reswap: Header::new("HX-Reswap", "outerhtml".to_string()), + }) } } } -pub(crate) async fn edit( - State(pool): State>>, - Path(id): Path, -) -> Result { - let start = Instant::now(); - let line_item = line_items::query::read(&pool, id).await?; - let duration = start.elapsed().as_micros(); - info!("li - read duration: {duration} μs"); - let start = Instant::now(); - let line_item_date = line_item_dates::query::read(&pool, &line_item.line_item_date_id).await?; - let duration = start.elapsed().as_micros(); - info!("lid - read duration: {duration} μs"); - let start = Instant::now(); - let quote = quotes::query::read(&pool, &line_item_date.quote_id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - Ok(Html( +#[get("/edit/")] +async fn edit<'a>(db: Db, id: String) -> Result> { + let line_item = db + .run(move |conn| { + let line_item = line_items::query::read(conn, id)?; + Result::Ok(line_item) + }) + .await?; + + let lid_id = line_item.line_item_date_id.clone(); + let quote = db + .run(move |conn| { + let line_item_date = line_item_dates::query::read(conn, &lid_id)?; + let quote = quotes::query::read(conn, &line_item_date.quote_id)?; + Result::Ok(quote) + }) + .await?; + + Ok(RawHtml( EditForm { line_item: &line_item.into(), quote: "e.into(), - error_message: None, } .to_string(), )) } -pub(crate) async fn update( - State(pool): State>>, - axum::Form(form): axum::Form, -) -> Result { - let result = form.validate(); - match result { - Ok(_) => { - let start = Instant::now(); - let line_item = line_items::query::update(&pool, &form).await?; - let duration = start.elapsed().as_micros(); - info!("li - update duration: {duration} μs"); - let start = Instant::now(); - let quote = - quotes::query::from_line_item_date_id(&pool, &form.line_item_date_id).await?; - info!("Quote total after update: {}", quote.total); - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - Ok(Html( - Update { - line_item: &line_item.into(), - quote: "e.into(), - message: "Item was successfully updated.", - } - .to_string(), - ) - .into_response()) +#[post("/update", data = "")] +async fn update(db: Db, form: Form>) -> Result> { + print!("Form:\n{form:?}"); + match form.value { + Some(ref li_form) => { + let quote_id = li_form.quote_id.clone(); + let li_form = li_form.clone(); + let line_item = db + .run(move |conn| { + let line_item = line_items::query::update(conn, &li_form)?; + Result::Ok(line_item) + }) + .await?; + + let quote = db + .run(move |conn| { + let quote = quotes::query::read(conn, "e_id)?; + Result::Ok(quote) + }) + .await?; + + let content = Update { + line_item: &line_item.into(), + quote: "e.into(), + message: "Item was successfully updated.", + } + .to_string(); + + Ok(RawHtml(content)) } - Err(errors) => { - info!("ValidationErrors:\n{:?}", errors); - let start = Instant::now(); - let quote = - quotes::query::from_line_item_date_id(&pool, &form.line_item_date_id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - let error_message = String::from("Test"); - Ok(Html( - EditForm { - line_item: &form.into(), - quote: "e.into(), - error_message: Some(error_message), - } - .to_string(), - ) - .into_response()) + None => { + let template = EditFormWithErrors { form: &form }; + let content = template.to_string(); + Ok(RawHtml(content)) } } } -pub(crate) async fn delete( - State(pool): State>>, - axum::Form(form): axum::Form, -) -> Result { - let start = Instant::now(); - let line_item = line_items::query::delete(&pool, &form.id).await?; - let duration = start.elapsed().as_micros(); - info!("li - delete duration: {duration} μs"); - let start = Instant::now(); - let quote = quotes::query::from_line_item_date_id(&pool, &line_item.line_item_date_id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - Ok(Html( +#[post("/delete", data = "")] +async fn delete(db: Db, form: Form) -> Result> { + let quote = db + .run(move |conn| { + let line_item = line_items::query::delete(conn, &form.id)?; + let quote = quotes::query::from_line_item_date_id(conn, &line_item.line_item_date_id)?; + Result::Ok(quote) + }) + .await?; + + Ok(RawHtml( Destroy { quote: "e.into(), message: "Item was successfully destroyed.", } .to_string(), - ) - .into_response()) + )) } diff --git a/src/line_items/model.rs b/src/line_items/model.rs index 289554b..f3667a0 100644 --- a/src/line_items/model.rs +++ b/src/line_items/model.rs @@ -1,11 +1,11 @@ -use crate::currency::FORM_CURRENCY_REGEX; -use crate::schema::line_items; +use crate::{ + forms::{validate_amount, validate_quantity}, + schema::line_items, +}; use currency_rs::Currency; use diesel::prelude::*; -use serde::Deserialize; use time::OffsetDateTime; use ulid::Ulid; -use validator::Validate; #[derive(Debug, Insertable, Queryable, Selectable)] pub(crate) struct LineItem { @@ -19,8 +19,9 @@ pub(crate) struct LineItem { pub(crate) updated_at: OffsetDateTime, } -impl From<&LineItemForm> for LineItem { - fn from(value: &LineItemForm) -> Self { +// FIXME: Should be TryFrom due to potential bad parse from quantity +impl From<&EditLineItemForm> for LineItem { + fn from(value: &EditLineItemForm) -> Self { let description = value.description.clone().unwrap_or(String::from("")); let description = if description.is_empty() { None @@ -28,11 +29,11 @@ impl From<&LineItemForm> for LineItem { Some(description) }; LineItem { - id: value.id.clone().unwrap_or(Ulid::new().to_string()), + id: value.id.clone(), line_item_date_id: value.line_item_date_id.clone(), name: value.name.clone(), description, - quantity: value.quantity, + quantity: value.quantity.parse::().unwrap_or(0), unit_price: Currency::new_string(value.unit_price.as_str(), None) .unwrap_or(Currency::new_float(0f64, None)), created_at: OffsetDateTime::now_utc(), @@ -41,19 +42,58 @@ impl From<&LineItemForm> for LineItem { } } -#[derive(Debug, Deserialize, Validate)] -pub(crate) struct LineItemForm { - #[validate(length(min = 1, message = "can't be blank"))] - pub(crate) id: Option, - #[validate(length(min = 1, message = "can't be blank"))] +// FIXME: Should be TryFrom due to potential bad parse from quantity +impl From<&NewLineItemForm> for LineItem { + fn from(value: &NewLineItemForm) -> Self { + let description = value.description.clone().unwrap_or(String::from("")); + let description = if description.is_empty() { + None + } else { + Some(description) + }; + LineItem { + id: Ulid::new().to_string(), + line_item_date_id: value.line_item_date_id.clone(), + name: value.name.clone(), + description, + quantity: value.quantity.parse::().unwrap_or(0), + unit_price: Currency::new_string(value.unit_price.as_str(), None) + .unwrap_or(Currency::new_float(0f64, None)), + created_at: OffsetDateTime::now_utc(), + updated_at: OffsetDateTime::now_utc(), + } + } +} + +#[derive(Clone, Debug, FromForm)] +pub struct EditLineItemForm { + #[field(validate = len(1..))] + pub(crate) id: String, + #[field(validate = len(1..))] pub(crate) line_item_date_id: String, - #[validate(length(min = 1, message = "can't be blank"))] + #[field(validate = len(1..))] pub(crate) quote_id: String, - #[validate(length(min = 1, message = "can't be blank"))] + #[field(validate = len(1..).or_else(msg!("Please enter a name")))] pub(crate) name: String, pub(crate) description: Option, - pub(crate) quantity: i32, - #[validate(regex(path = "FORM_CURRENCY_REGEX"))] + #[field(validate = validate_quantity())] + pub(crate) quantity: String, + #[field(validate = validate_amount())] + pub(crate) unit_price: String, +} + +#[derive(Clone, Debug, FromForm)] +pub struct NewLineItemForm { + #[field(validate = len(1..))] + pub(crate) line_item_date_id: String, + #[field(validate = len(1..))] + pub(crate) quote_id: String, + #[field(validate = len(1..).or_else(msg!("Please enter a name")))] + pub(crate) name: String, + pub(crate) description: Option, + #[field(validate = validate_quantity())] + pub(crate) quantity: String, + #[field(validate = validate_amount())] pub(crate) unit_price: String, } @@ -107,12 +147,27 @@ impl From for LineItemPresenter { } } -impl From for LineItemPresenter { - fn from(value: LineItemForm) -> Self { +impl From for LineItemPresenter { + fn from(value: EditLineItemForm) -> Self { + let unit_price = Currency::new_string(value.unit_price.as_str(), None) + .unwrap_or(Currency::new_float(0f64, None)); + LineItemPresenter { + id: Some(value.id), + line_item_date_id: value.line_item_date_id, + name: value.name, + description: value.description.unwrap_or(String::from("")), + quantity: value.quantity.to_string(), + unit_price, + } + } +} + +impl From for LineItemPresenter { + fn from(value: NewLineItemForm) -> Self { let unit_price = Currency::new_string(value.unit_price.as_str(), None) .unwrap_or(Currency::new_float(0f64, None)); LineItemPresenter { - id: value.id, + id: None, line_item_date_id: value.line_item_date_id, name: value.name, description: value.description.unwrap_or(String::from("")), @@ -122,7 +177,7 @@ impl From for LineItemPresenter { } } -#[derive(Debug, Deserialize)] +#[derive(Debug, FromForm)] pub(crate) struct DeleteForm { pub(crate) id: String, } diff --git a/src/line_items/query.rs b/src/line_items/query.rs index 04f2d5f..4424024 100644 --- a/src/line_items/query.rs +++ b/src/line_items/query.rs @@ -1,75 +1,59 @@ use crate::{ - line_items::model::{LineItem, LineItemForm}, + line_items::model::{EditLineItemForm, LineItem, NewLineItemForm}, schema::{line_item_dates, line_items}, Result, }; use diesel::prelude::*; -use diesel::r2d2::{ConnectionManager, Pool, PooledConnection}; -pub(crate) async fn all_for_quote>( - pool: &Pool>, +pub(crate) fn all_for_quote>( + connection: &mut SqliteConnection, quote_id: S, ) -> Result> { - let mut connection = pool.get()?; let records = line_items::table .inner_join(line_item_dates::table) .select(LineItem::as_select()) .filter(line_item_dates::quote_id.eq("e_id.as_ref())) - .get_results(&mut connection)?; + .get_results(connection)?; Ok(records) } -pub(crate) async fn all_for_line_item_date>( - pool: &Pool>, +pub(crate) fn all_for_line_item_date>( + connection: &mut SqliteConnection, line_item_date_id: S, ) -> Result> { - let mut connection = pool.get()?; let records = line_items::table .filter(line_items::line_item_date_id.eq(&line_item_date_id.as_ref())) - .get_results(&mut connection)?; + .get_results(connection)?; Ok(records) } -pub(crate) async fn read>( - pool: &Pool>, - id: S, -) -> Result { - let mut connection = pool.get()?; - read_from_connection(&mut connection, id) -} - -fn read_from_connection>( - connection: &mut PooledConnection>, - id: S, -) -> Result { +pub(crate) fn read>(connection: &mut SqliteConnection, id: S) -> Result { let record = line_items::table .filter(line_items::id.eq(&id.as_ref())) .get_result(connection)?; Ok(record) } -pub(crate) async fn insert( - pool: &Pool>, - form: &LineItemForm, +pub(crate) fn insert( + connection: &mut SqliteConnection, + form: &NewLineItemForm, ) -> Result { let record: LineItem = form.into(); - let mut connection = pool.get()?; diesel::dsl::insert_into(line_items::table) .values(&record) - .execute(&mut connection)?; + .execute(connection)?; Ok(record) } -pub(crate) async fn update( - pool: &Pool>, - form: &LineItemForm, +pub(crate) fn update( + connection: &mut SqliteConnection, + form: &EditLineItemForm, ) -> Result { let record: LineItem = form.into(); - let mut connection = pool.get()?; diesel::dsl::update(line_items::table) .set(( line_items::name.eq(&record.name), @@ -79,27 +63,23 @@ pub(crate) async fn update( line_items::updated_at.eq(&record.updated_at), )) .filter(line_items::id.eq(&record.id)) - .execute(&mut connection)?; + .execute(connection)?; - read_from_connection(&mut connection, &record.id) + read(connection, &record.id) } -pub(crate) async fn delete>( - pool: &Pool>, - id: S, -) -> Result { - let mut connection = pool.get()?; - let record = read_from_connection(&mut connection, &id)?; +pub(crate) fn delete>(connection: &mut SqliteConnection, id: S) -> Result { + let record = read(connection, &id)?; _ = diesel::dsl::delete(line_items::table) .filter(line_items::id.eq(&id.as_ref())) - .execute(&mut connection)?; + .execute(connection)?; Ok(record) } pub(crate) fn delete_all_for_quote>( - tx: &mut PooledConnection>, + tx: &mut SqliteConnection, quote_id: S, ) -> Result { let line_items1 = diesel::alias!(line_items as line_items1); @@ -118,10 +98,7 @@ pub(crate) fn delete_all_for_quote>( Ok(()) } -pub(crate) fn delete_all_for_date>( - tx: &mut PooledConnection>, - id: S, -) -> Result { +pub(crate) fn delete_all_for_date>(tx: &mut SqliteConnection, id: S) -> Result { _ = diesel::dsl::delete(line_items::table) .filter(line_items::line_item_date_id.eq(&id.as_ref())) .execute(tx)?; diff --git a/src/line_items/view.rs b/src/line_items/view.rs index 7c5dd9b..e357c72 100644 --- a/src/line_items/view.rs +++ b/src/line_items/view.rs @@ -1,5 +1,10 @@ -use crate::quotes::view::SwapFooter; -use crate::{layout::Flash, line_items::model::LineItemPresenter, quotes::model::QuotePresenter}; +use crate::{ + forms::css_for_field, + layout::Flash, + line_items::model::{EditLineItemForm, LineItemPresenter, NewLineItemForm}, + quotes::{model::QuotePresenter, view::SwapFooter}, +}; +use rocket::form::{Contextual, Form}; markup::define! { LineItem<'a>(line_item: &'a LineItemPresenter) { @@ -37,9 +42,7 @@ markup::define! { } } - EditForm<'a>(line_item: &'a LineItemPresenter, - quote: &'a QuotePresenter, - error_message: Option) { + EditForm<'a>(line_item: &'a LineItemPresenter, quote: &'a QuotePresenter) { div[id = &line_item.dom_id()] { form[id = &line_item.dom_id(), "hx-post" = "/line_items/update", @@ -47,17 +50,13 @@ markup::define! { "hx-swap" = "outerHTML", class = "flex flex-wrap items-start bg-white gap-2 mb-3 p-2 rounded-md", autocomplete = "off", + novalidate, "accept-charset" = "UTF-8"] { - @let form_input_class = if error_message.is_some() { "form-input border-primary" } else { "form-input" }; - @if let Some(message) = error_message { - div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { @message } - } - @if let Some(id) = &line_item.id { - input[id = "line_item_id", - name = "id", - "type" = "hidden", - value = id] {} - } + + input[id = "id", + name = "id", + "type" = "hidden", + value = &line_item.id.clone().unwrap()] {} input[id = "quote_id", name = "quote_id", "type" = "hidden", @@ -66,10 +65,11 @@ markup::define! { name = "line_item_date_id", "type" = "hidden", value = &line_item.line_item_date_id] {} + div[class = "flex-1 font-bold mb-0"] { input[id = "line_item_name", name = "name", - class = form_input_class, + class = "form-input", autofocus = "autofocus", placeholder = "Name of your item", required, @@ -79,7 +79,7 @@ markup::define! { div[class = "block flex-[0_0_7rem] mb-0"] { input[id = "line_item_quantity", name = "quantity", - class = form_input_class, + class = "form-input", placeholder = "1", required, "type" = "number", @@ -90,7 +90,7 @@ markup::define! { div[class = "block flex-[0_0_9rem] mb-0"] { input[id = "line_item_price", name = "unit_price", - class = form_input_class, + class = "form-input", placeholder = "$100.00", required, "type" = "number", @@ -101,7 +101,7 @@ markup::define! { div[class = "basis-full order-2 m-w-100 font-normal text-[0.875rem] text-[hsl(0,1%,44%)] mb-0"] { textarea[id = "line_item_description", name = "description", - class = {format!("resize-none {}", form_input_class)}, + class = "resize-none form-input", placeholder = "Description (optional)"] { @line_item.description } } a[class = "button button-light", @@ -118,9 +118,97 @@ markup::define! { } } + EditFormWithErrors<'a, 'r>(form: &'a Form>) { + @let context = &form.context; + @let id = context.field_value("id").unwrap_or(""); + @let quote_id = context.field_value("quote_id").unwrap_or(""); + @let line_item_date_id = context.field_value("line_item_date_id").unwrap_or(""); + @let name = context.field_value("name").unwrap_or(""); + @let quantity = context.field_value("quantity").unwrap_or(""); + @let unit_price = context.field_value("unit_price").unwrap_or(""); + @let description = context.field_value("description").unwrap_or(""); + @let dom_id = format!("line_item_{}", &id); + + div[id = &dom_id] { + form[id = &dom_id, + "hx-post" = "/line_items/update", + "hx-target" = {format!("#{}", &dom_id)}, + "hx-swap" = "outerHTML", + class = "flex flex-wrap items-start bg-white gap-2 mb-3 p-2 rounded-md", + autocomplete = "off", + novalidate, + "accept-charset" = "UTF-8"] { + + @let messages = context.errors().map(|item| item.to_string()).collect::>(); + div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { + @for message in messages { + p { @message } + } + } + + input[id = "id", + name = "id", + "type" = "hidden", + value = &id] {} + input[id = "quote_id", + name = "quote_id", + "type" = "hidden", + value = "e_id] {} + input[id = "line_item_date_id", + name = "line_item_date_id", + "type" = "hidden", + value = &line_item_date_id] {} + div[class = "flex-1 font-bold mb-0"] { + input[id = "line_item_name", + name = "name", + class = css_for_field(form, "name", "form-input", "border-primary"), + autofocus = "autofocus", + placeholder = "Name of your item", + "type" = "text", + value = &name] {} + } + div[class = "block flex-[0_0_7rem] mb-0"] { + input[id = "line_item_quantity", + name = "quantity", + class = css_for_field(form, "quantity", "form-input", "border-primary"), + placeholder = "1", + "type" = "number", + min = "1", + step = "1", + value = &quantity] {} + } + div[class = "block flex-[0_0_9rem] mb-0"] { + input[id = "line_item_price", + name = "unit_price", + class = css_for_field(form, "unit_price", "form-input", "border-primary"), + placeholder = "$100.00", + "type" = "number", + min = "0.01", + step = "0.01", + value = &unit_price] {} + } + div[class = "basis-full order-2 m-w-100 font-normal text-[0.875rem] text-[hsl(0,1%,44%)] mb-0"] { + textarea[id = "line_item_description", + name = "description", + class = css_for_field(form, "description", "resize-none form-input", "border-primary"), + placeholder = "Description (optional)"] { @description } + } + a[class = "button button-light", + "hx-get" = {format!("/line_items/{}", &id)}, + "hx-target" = {format!("#{}", &dom_id)}, + "hx-trigger" = "click", + "hx-swap" = "outerHTML"] { "Cancel" } + input[name = "commit", + "type" = "submit", + value = "Update item", + class = "button button-secondary", + "_" = "on click add { pointer-events: none }"] {} + } + } + } + NewForm<'a>(line_item: &'a LineItemPresenter, - quote: &'a QuotePresenter, - error_message: Option) { + quote: &'a QuotePresenter) { div[id = &line_item.dom_id()] { @let line_item_new_dom_id = format!("#line_item_date_{}_line_items", &line_item.line_item_date_id); form[id = "form_new", @@ -129,17 +217,9 @@ markup::define! { "hx-swap" = "beforeend", class = "flex flex-wrap items-start bg-white gap-2 mb-3 p-2 rounded-md", autocomplete = "off", + novalidate, "accept-charset" = "UTF-8"] { - @let form_input_class = if error_message.is_some() { "form-input border-primary" } else { "form-input" }; - @if let Some(message) = error_message { - div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { @message } - } - @if let Some(id) = &line_item.id { - input[id = "line_item_id", - name = "id", - "type" = "hidden", - value = id] {} - } + input[id = "quote_id", name = "quote_id", "type" = "hidden", @@ -151,19 +231,17 @@ markup::define! { div[class = "flex-1 font-bold mb-0"] { input[id = "line_item_name", name = "name", - class = form_input_class, + class = "form-input", autofocus = "autofocus", placeholder = "Name of your item", - required, "type" = "text", value = &line_item.name] {} } div[class = "block flex-[0_0_7rem] mb-0"] { input[id = "line_item_quantity", name = "quantity", - class = form_input_class, + class = "form-input", placeholder = "1", - required, "type" = "number", min = "1", step = "1", @@ -172,9 +250,8 @@ markup::define! { div[class = "block flex-[0_0_9rem] mb-0"] { input[id = "line_item_price", name = "unit_price", - class = form_input_class, + class = "form-input", placeholder = "$100.00", - required, "type" = "number", min = "0.01", step = "0.01", @@ -183,7 +260,7 @@ markup::define! { div[class = "basis-full order-2 m-w-100 font-normal text-[0.875rem] text-[hsl(0,1%,44%)] mb-0"] { textarea[id = "line_item_description", name = "description", - class = {format!("resize-none {}", form_input_class)}, + class = "resize-none form-input", placeholder = "Description (optional)"] { @line_item.description } } a[class = "button button-light", @@ -197,6 +274,90 @@ markup::define! { } } + NewFormWithErrors<'a, 'r>(form: &'a Form>) { + @let context = &form.context; + @let quote_id = context.field_value("quote_id").unwrap_or(""); + @let line_item_date_id = context.field_value("line_item_date_id").unwrap_or(""); + @let name = context.field_value("name").unwrap_or(""); + @let quantity = context.field_value("quantity").unwrap_or(""); + @let unit_price = context.field_value("unit_price").unwrap_or(""); + @let description = context.field_value("description").unwrap_or(""); + + div[id = "line_item_new"] { + @let line_item_new_dom_id = format!("#line_item_date_{}_line_items", &line_item_date_id); + form[id = "form_new", + "hx-post" = "/line_items/create", + "hx-target" = line_item_new_dom_id, + "hx-swap" = "beforeend", + class = "flex flex-wrap items-start bg-white gap-2 mb-3 p-2 rounded-md", + autocomplete = "off", + novalidate, + "accept-charset" = "UTF-8"] { + + @let messages = context.errors().map(|item| item.to_string()).collect::>(); + div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { + @for message in messages { + p { @message } + } + } + + input[id = "quote_id", + name = "quote_id", + "type" = "hidden", + value = "e_id] {} + input[id = "line_item_date_id", + name = "line_item_date_id", + "type" = "hidden", + value = &line_item_date_id] {} + div[class = "flex-1 font-bold mb-0"] { + input[id = "line_item_name", + name = "name", + class = css_for_field(form, "name", "form-input", "border-primary"), + autofocus = "autofocus", + placeholder = "Name of your item", + required, + "type" = "text", + value = &name] {} + } + div[class = "block flex-[0_0_7rem] mb-0"] { + input[id = "line_item_quantity", + name = "quantity", + class = css_for_field(form, "quantity", "form-input", "border-primary"), + placeholder = "1", + required, + "type" = "number", + min = "1", + step = "1", + value = &quantity] {} + } + div[class = "block flex-[0_0_9rem] mb-0"] { + input[id = "line_item_price", + name = "unit_price", + class = css_for_field(form, "unit_price", "form-input", "border-primary"), + placeholder = "$100.00", + required, + "type" = "number", + min = "0.01", + step = "0.01", + value = &unit_price] {} + } + div[class = "basis-full order-2 m-w-100 font-normal text-[0.875rem] text-[hsl(0,1%,44%)] mb-0"] { + textarea[id = "line_item_description", + name = "description", + class = css_for_field(form, "description", "resize-none form-input", "border-primary"), + placeholder = "Description (optional)"] { @description } + } + a[class = "button button-light", + "_" = "on click remove #form_new"] { "Cancel" } + input[name = "commit", + "type" = "submit", + value = "Create item", + class = "button button-secondary", + "_" = "on click add { pointer-events: none }"] {} + } + } + } + Create<'a>(line_item: &'a LineItemPresenter, quote: &'a QuotePresenter, message: &'a str) { @let line_item_new_dom_id = format!("line_item_date_{}_line_item_new", &line_item.line_item_date_id); @LineItem{ line_item } diff --git a/src/main.rs b/src/main.rs index ddaa1f1..cee8678 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,9 @@ #![deny(unreachable_pub, private_bounds, private_interfaces)] #![forbid(unsafe_code)] +#[macro_use] +extern crate rocket; + mod assets; mod currency; mod error; @@ -9,125 +12,54 @@ pub mod layout; pub mod line_item_dates; pub mod line_items; pub mod quotes; +mod rocket_ext; mod schema; mod time; +mod forms; -use assets::asset_handler; -use axum::{ - handler::HandlerWithoutStateExt, - response::Redirect, - routing::{get, post, Router}, -}; -use diesel::connection::SimpleConnection; -use diesel::prelude::*; -use diesel::r2d2::{ConnectionManager, Pool}; -use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; -use dotenvy::dotenv; -use std::env; -use tower_http::trace::{DefaultOnResponse, TraceLayer}; -use tower_http::LatencyUnit; -use tracing::{info, Level}; -use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; +use diesel::sqlite::SqliteConnection; +use rocket::response::Redirect; +use rocket::{fairing::AdHoc, Build, Rocket}; +use rocket_sync_db_pools::database; -const MIGRATIONS: EmbeddedMigrations = embed_migrations!(); +#[database("demo")] +struct Db(SqliteConnection); pub(crate) type Result = std::result::Result; -#[tokio::main] -async fn main() { - dotenv().ok(); - - let rust_log = env::var("RUST_LOG").unwrap_or_else(|_| { - let value = "INFO,tower_http=info"; - env::set_var("RUST_LOG", value); - value.into() - }); - println!("RUST_LOG={rust_log}"); - - tracing_subscriber::registry() - .with(EnvFilter::from_default_env()) - .with(fmt::layer()) - .init(); - - let database_url = env::var("DATABASE_URL").unwrap(); - println!("DATABASE_URL={database_url}"); - - let manager = ConnectionManager::::new(database_url); - let pool = Pool::builder() - .max_size(10) - .build(manager) - .expect("Could not build connection pool"); - - let mut conn = pool.get().unwrap(); +#[launch] +fn rocket() -> _ { + rocket::build() + .attach(AdHoc::on_ignite("Diesel SQLite Stage", |rocket| async { + rocket + .attach(Db::fairing()) + .attach(AdHoc::on_ignite("Diesel Migrations", run_migrations)) + })) + .mount("/", routes![index]) + .attach(quotes::controller::stage()) + .attach(line_item_dates::controller::stage()) + .attach(line_items::controller::stage()) + .attach(assets::stage()) +} - conn.batch_execute(" - PRAGMA journal_mode = WAL; -- better write-concurrency - PRAGMA synchronous = NORMAL; -- fsync only in critical moments - PRAGMA wal_autocheckpoint = 1000; -- write WAL changes back every 1000 pages, for an in average 1MB WAL file. May affect readers if number is increased - PRAGMA wal_checkpoint(TRUNCATE); -- free some space by truncating possibly massive WAL files from the last run. - PRAGMA busy_timeout = 250; -- sleep if the database is busy - PRAGMA foreign_keys = ON; -- enforce foreign keys - ").unwrap(); +#[get("/")] +fn index() -> Redirect { + Redirect::to(uri!("/quotes")) +} - conn.run_pending_migrations(MIGRATIONS).unwrap(); - drop(conn); +async fn run_migrations(rocket: Rocket) -> Rocket { + use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; - let trace_layer = TraceLayer::new_for_http().on_response( - DefaultOnResponse::new() - .level(Level::INFO) - .latency_unit(LatencyUnit::Micros), - ); + const MIGRATIONS: EmbeddedMigrations = embed_migrations!(); - let app = Router::new() - .route("/", get(|| async { Redirect::to("/quotes") })) - .route("/quotes", get(quotes::controller::index)) - .route("/quotes/:id", get(quotes::controller::quote)) - .route("/quotes/show/:id", get(quotes::controller::show)) - .route("/quotes/new", get(quotes::controller::new)) - .route("/quotes/create", post(quotes::controller::create)) - .route("/quotes/edit/:id", get(quotes::controller::edit)) - .route("/quotes/update", post(quotes::controller::update)) - .route("/quotes/delete", post(quotes::controller::delete)) - .route_service("/dist/*file", asset_handler.into_service()) - .route( - "/line_item_dates/:id", - get(line_item_dates::controller::line_item_date), - ) - .route( - "/line_item_dates/new/:quote_id", - get(line_item_dates::controller::new), - ) - .route( - "/line_item_dates/create", - post(line_item_dates::controller::create), - ) - .route( - "/line_item_dates/edit/:id", - get(line_item_dates::controller::edit), - ) - .route( - "/line_item_dates/update", - post(line_item_dates::controller::update), - ) - .route( - "/line_item_dates/delete", - post(line_item_dates::controller::delete), - ) - .route( - "/line_items/new/:line_item_date_id", - get(line_items::controller::new), - ) - .route("/line_items/:id", get(line_items::controller::line_item)) - .route("/line_items/create", post(line_items::controller::create)) - .route("/line_items/edit/:id", get(line_items::controller::edit)) - .route("/line_items/update", post(line_items::controller::update)) - .route("/line_items/delete", post(line_items::controller::delete)) - .with_state(pool) - .layer(trace_layer) - .fallback_service(asset_handler.into_service()); + Db::get_one(&rocket) + .await + .expect("failure obtaining database connection") + .run(|conn| { + conn.run_pending_migrations(MIGRATIONS) + .expect("failure running diesel migrations"); + }) + .await; - let addr: std::net::SocketAddr = "[::]:8081".parse().unwrap(); - info!("listening on {addr}"); - let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); - axum::serve(listener, app).await.unwrap(); + rocket } diff --git a/src/quotes/controller.rs b/src/quotes/controller.rs index 8e518c8..4972a02 100644 --- a/src/quotes/controller.rs +++ b/src/quotes/controller.rs @@ -4,33 +4,40 @@ use crate::{ line_items::{self, model::LineItemPresenter}, quotes::{ self, - model::{DeleteForm, QuoteForm, QuotePresenter}, - view::{Create, EditForm, Index, NewForm, Quote, Show, Update}, + model::{DeleteForm, EditQuoteForm, NewQuoteForm, QuotePresenter}, + view::*, }, - Result, + rocket_ext::HtmxResponder, + Db, Result, }; -use axum::{ - extract::{Path, State}, - response::{Html, IntoResponse}, -}; -use diesel::prelude::SqliteConnection; -use diesel::r2d2::{ConnectionManager, Pool}; use itertools::Itertools; -use std::time::Instant; -use tracing::info; -use validator::Validate; - -pub(crate) async fn index( - State(pool): State>>, -) -> Result> { - let start = Instant::now(); - let quotes = quotes::query::all(&pool) - .await? - .into_iter() - .map(|record| record.into()) - .collect::>(); - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); +use rocket::{ + fairing::AdHoc, + form::{Contextual, Form}, + http::Header, + response::content::RawHtml, +}; + +pub(crate) fn stage() -> AdHoc { + AdHoc::on_ignite("Quote Stage", |rocket| async { + rocket.mount( + "/quotes", + routes![index, quote, show, new, create, edit, update, delete], + ) + }) +} + +#[get("/")] +async fn index(db: Db) -> Result> { + let quotes = db + .run(move |conn| { + let records = quotes::query::all(conn)? + .into_iter() + .map(|record| record.into()) + .collect::>(); + Result::Ok(records) + }) + .await?; let template = Layout { head: markup::new! { @@ -39,50 +46,56 @@ pub(crate) async fn index( body: Index { quotes }, }; - Ok(Html(template.to_string())) + Ok(RawHtml(template.to_string())) } -pub(crate) async fn quote( - State(pool): State>>, - Path(id): Path, -) -> Result { - let start = Instant::now(); - let quote = quotes::query::read(&pool, &id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); +#[get("/")] +async fn quote(db: Db, id: String) -> Result> { + let quote = db + .run(move |conn| { + let quote = quotes::query::read(conn, &id)?; + Result::Ok(quote) + }) + .await?; let quote = Quote { quote: "e.into(), }; - Ok(Html(quote.to_string())) + Ok(RawHtml(quote.to_string())) } -pub(crate) async fn show( - State(pool): State>>, - Path(id): Path, -) -> Result { - let start = Instant::now(); - let quote = quotes::query::read(&pool, &id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - let start = Instant::now(); - let line_item_dates = line_item_dates::query::all(&pool, "e.id) - .await? - .into_iter() - .map(|record| record.into()) - .collect::>(); - let duration = start.elapsed().as_micros(); - info!("lid - read all duration: {duration} μs"); - let start = Instant::now(); - let line_items = line_items::query::all_for_quote(&pool, "e.id) - .await? - .into_iter() - .map(|record| record.into()) - .collect::>() - .into_iter() - .into_group_map_by(|line_item| line_item.line_item_date_id.clone()); - let duration = start.elapsed().as_micros(); - info!("li - read all duration: {duration} μs"); +#[get("/show/")] +async fn show(db: Db, id: String) -> Result> { + let quote = db + .run(move |conn| { + let quote = quotes::query::read(conn, &id)?; + Result::Ok(quote) + }) + .await?; + + let quote_id = quote.id.clone(); + let line_item_dates = db + .run(move |conn| { + let records = line_item_dates::query::all(conn, quote_id)? + .into_iter() + .map(|record| record.into()) + .collect::>(); + Result::Ok(records) + }) + .await?; + + let quote_id = quote.id.clone(); + let line_items = db + .run(move |conn| { + let index = line_items::query::all_for_quote(conn, quote_id)? + .into_iter() + .map(|record| record.into()) + .collect::>() + .into_iter() + .into_group_map_by(|line_item| line_item.line_item_date_id.clone()); + Result::Ok(index) + }) + .await?; let quote_name = quote.name.clone(); let template = Layout { @@ -96,119 +109,104 @@ pub(crate) async fn show( }, }; - Ok(Html(template.to_string())) + Ok(RawHtml(template.to_string())) } -pub(crate) async fn new() -> impl IntoResponse { - Html( - NewForm { - quote: &QuotePresenter::default(), - error_message: None, - } - .to_string(), - ) +#[get("/new")] +async fn new() -> RawHtml { + RawHtml(NewForm {}.to_string()) } -pub(crate) async fn create( - State(pool): State>>, - axum::Form(form): axum::Form, -) -> Result { - let result = form.validate(); - match result { - Ok(_) => { - let start = Instant::now(); - let quote = quotes::query::insert(&pool, &form).await?; - let duration = start.elapsed().as_micros(); - info!("quo - insert duration: {duration} μs"); - Ok(Html( - Create { - quote: "e.into(), - message: "Quote was successfully created.", - } - .to_string(), - ) - .into_response()) +#[post("/create", data = "")] +async fn create(db: Db, form: Form>) -> Result { + print!("Form:\n{form:?}"); + match form.value { + Some(ref quote_form) => { + let quote_form = quote_form.clone(); + let quote = db + .run(move |conn| { + let record = quotes::query::insert(conn, "e_form)?; + Result::Ok(record) + }) + .await?; + + let content = Create { + quote: "e.into(), + message: "Quote was successfully created.", + } + .to_string(); + + Ok(HtmxResponder::Ok(content)) } - Err(errors) => { - info!("ValidationErrors:\n{:?}", errors); - let error_message = String::from("Test"); - Ok(Html( - NewForm { - quote: &form.into(), - error_message: Some(error_message), - } - .to_string(), - ) - .into_response()) + None => { + let template = NewFormWithErrors { form: &form }; + let content = template.to_string(); + Ok(HtmxResponder::Retarget { + content, + retarget: Header::new("HX-Retarget", "#quote_new".to_string()), + reswap: Header::new("HX-Reswap", "outerhtml".to_string()), + }) } } } -pub(crate) async fn edit( - State(pool): State>>, - Path(id): Path, -) -> Result { - let start = Instant::now(); - let quote = quotes::query::read(&pool, &id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - read duration: {duration} μs"); - Ok(Html( +#[get("/edit/")] +async fn edit(db: Db, id: String) -> Result> { + let quote = db + .run(move |conn| { + let quote = quotes::query::read(conn, &id)?; + Result::Ok(quote) + }) + .await?; + + Ok(RawHtml( EditForm { quote: "e.into(), - error_message: None, } .to_string(), )) } -pub(crate) async fn update( - State(pool): State>>, - axum::Form(form): axum::Form, -) -> Result { - let result = form.validate(); - match result { - Ok(_) => { - let start = Instant::now(); - let quote = quotes::query::update(&pool, &form).await?; - let duration = start.elapsed().as_micros(); - info!("quo - update duration: {duration} μs"); - Ok(Html( +#[post("/update", data = "")] +async fn update(db: Db, form: Form>) -> Result> { + match form.value { + Some(ref quote_form) => { + let quote_form = quote_form.clone(); + let quote = db + .run(move |conn| { + let record = quotes::query::update(conn, "e_form)?; + Result::Ok(record) + }) + .await?; + + Ok(RawHtml( Update { quote: "e.into(), message: "Quote was successfully updated.", } .to_string(), - ) - .into_response()) + )) } - Err(errors) => { - info!("ValidationErrors:\n{:?}", errors); - let error_message = String::from("Test"); - Ok(Html( - EditForm { - quote: &form.into(), - error_message: Some(error_message), - } - .to_string(), - ) - .into_response()) + None => { + let template = EditFormWithErrors { form: &form }; + let html = template.to_string(); + Ok(RawHtml(html)) } } } -pub(crate) async fn delete( - State(pool): State>>, - axum::Form(form): axum::Form, -) -> Result { - let start = Instant::now(); - quotes::query::delete(&pool, &form.id).await?; - let duration = start.elapsed().as_micros(); - info!("quo - delete duration: {duration} μs"); - Ok(Html( +#[post("/delete", data = "")] +async fn delete(db: Db, form: Form) -> Result> { + db.run(move |conn| { + quotes::query::delete(conn, &form.id)?; + Result::Ok(()) + }) + .await?; + + Ok(RawHtml( Flash { message: "Quote was successfully destroyed.", } .to_string(), - ) - .into_response()) + )) } diff --git a/src/quotes/model.rs b/src/quotes/model.rs index a6eaa92..b183361 100644 --- a/src/quotes/model.rs +++ b/src/quotes/model.rs @@ -2,10 +2,8 @@ use crate::schema::quotes; use currency_rs::Currency; use diesel::prelude::*; use diesel::sql_types::*; -use serde::Deserialize; use time::OffsetDateTime; use ulid::Ulid; -use validator::Validate; #[derive(Debug, QueryableByName)] pub struct QuoteWithTotal { @@ -30,10 +28,10 @@ pub struct Quote { pub updated_at: OffsetDateTime, } -impl From<&QuoteForm> for Quote { - fn from(value: &QuoteForm) -> Self { +impl From<&NewQuoteForm> for Quote { + fn from(value: &NewQuoteForm) -> Self { Quote { - id: value.id.clone().unwrap_or(Ulid::new().to_string()), + id: Ulid::new().to_string(), name: value.name.clone(), created_at: OffsetDateTime::now_utc(), updated_at: OffsetDateTime::now_utc(), @@ -41,11 +39,28 @@ impl From<&QuoteForm> for Quote { } } -#[derive(Debug, Deserialize, Validate)] -pub(crate) struct QuoteForm { - #[validate(length(min = 1, message = "can't be blank"))] - pub(crate) id: Option, - #[validate(length(min = 1, message = "Can't be blank"))] +impl From<&EditQuoteForm> for Quote { + fn from(value: &EditQuoteForm) -> Self { + Quote { + id: value.id.clone(), + name: value.name.clone(), + created_at: OffsetDateTime::now_utc(), + updated_at: OffsetDateTime::now_utc(), + } + } +} + +#[derive(Clone, Debug, FromForm)] +pub struct NewQuoteForm { + #[field(validate = len(1..).or_else(msg!("Please enter a name")))] + pub(crate) name: String, +} + +#[derive(Clone, Debug, FromForm)] +pub struct EditQuoteForm { + #[field(validate = len(1..))] + pub(crate) id: String, + #[field(validate = len(1..).or_else(msg!("Please enter a name")))] pub(crate) name: String, } @@ -99,17 +114,27 @@ impl From for QuotePresenter { } } -impl From for QuotePresenter { - fn from(value: QuoteForm) -> Self { +impl From for QuotePresenter { + fn from(value: NewQuoteForm) -> Self { + QuotePresenter { + id: None, + name: value.name, + total: Currency::new_float(0f64, None), + } + } +} + +impl From for QuotePresenter { + fn from(value: EditQuoteForm) -> Self { QuotePresenter { - id: value.id, + id: Some(value.id), name: value.name, total: Currency::new_float(0f64, None), } } } -#[derive(Debug, Deserialize)] +#[derive(Clone, Debug, FromForm)] pub(crate) struct DeleteForm { pub(crate) id: String, } diff --git a/src/quotes/query.rs b/src/quotes/query.rs index f9f8477..73ecaf9 100644 --- a/src/quotes/query.rs +++ b/src/quotes/query.rs @@ -1,30 +1,25 @@ use crate::{ line_item_dates, - quotes::model::{Quote, QuoteForm, QuoteWithTotal}, + quotes::model::{EditQuoteForm, NewQuoteForm, Quote, QuoteWithTotal}, schema::quotes, Result, }; use diesel::prelude::*; -use diesel::r2d2::{ConnectionManager, Pool, PooledConnection}; -pub(crate) async fn all(pool: &Pool>) -> Result> { - let mut connection = pool.get()?; - let records = quotes::table - .order_by(quotes::id) - .get_results(&mut connection)?; +pub(crate) fn all(connection: &mut SqliteConnection) -> Result> { + let records = quotes::table.order_by(quotes::id).get_results(connection)?; Ok(records) } -pub(crate) async fn read>( - pool: &Pool>, +pub(crate) fn read>( + connection: &mut SqliteConnection, id: S, ) -> Result { - let mut connection = pool.get()?; - read_from_connection(&mut connection, id) + read_from_connection(connection, id) } fn read_from_connection>( - connection: &mut PooledConnection>, + connection: &mut SqliteConnection, id: S, ) -> Result { // language=SQL @@ -48,8 +43,8 @@ fn read_from_connection>( Ok(record) } -pub(crate) async fn from_line_item_date_id>( - pool: &Pool>, +pub(crate) fn from_line_item_date_id>( + connection: &mut SqliteConnection, id: S, ) -> Result { // language=SQL @@ -68,51 +63,44 @@ pub(crate) async fn from_line_item_date_id>( inner join quotes q on lid.quote_id = q.id where lid.id = ? "#; - let mut connection = pool.get()?; let record = diesel::dsl::sql_query(sql) .bind::(id.as_ref()) - .get_result(&mut connection)?; + .get_result(connection)?; Ok(record) } -pub(crate) async fn insert( - pool: &Pool>, - form: &QuoteForm, -) -> Result { +pub(crate) fn insert(connection: &mut SqliteConnection, form: &NewQuoteForm) -> Result { let record: Quote = form.into(); - let mut connection = pool.get()?; diesel::dsl::insert_into(quotes::table) .values(&record) - .execute(&mut connection)?; + .execute(connection)?; Ok(record) } -pub(crate) async fn update( - pool: &Pool>, - form: &QuoteForm, +pub(crate) fn update( + connection: &mut SqliteConnection, + form: &EditQuoteForm, ) -> Result { let record: Quote = form.into(); - let mut connection = pool.get()?; diesel::dsl::update(quotes::table) .set(( quotes::name.eq(&record.name), quotes::updated_at.eq(&record.updated_at), )) .filter(quotes::id.eq(&record.id)) - .execute(&mut connection)?; + .execute(connection)?; - read_from_connection(&mut connection, &record.id) + read_from_connection(connection, &record.id) } -pub(crate) async fn delete>( - pool: &Pool>, +pub(crate) fn delete>( + connection: &mut SqliteConnection, id: S, ) -> Result { - let mut connection = pool.get()?; - let record = read_from_connection(&mut connection, &id)?; + let record = read_from_connection(connection, &id)?; _ = connection.transaction::<_, _, _>(|tx| { line_item_dates::query::delete_all_for_quote(tx, &id)?; diff --git a/src/quotes/view.rs b/src/quotes/view.rs index fd454f5..350761f 100644 --- a/src/quotes/view.rs +++ b/src/quotes/view.rs @@ -1,9 +1,11 @@ use crate::{ + forms::css_for_field, layout::Flash, line_item_dates::{model::LineItemDatePresenter, view::LineItemDate}, line_items::model::LineItemPresenter, - quotes::model::QuotePresenter, + quotes::model::{EditQuoteForm, NewQuoteForm, QuotePresenter}, }; +use rocket::form::{Contextual, Form}; use std::collections::HashMap; markup::define! { @@ -96,7 +98,7 @@ markup::define! { @InitialFooter { quote } } - EditForm<'a>(quote: &'a QuotePresenter, error_message: Option) { + EditForm<'a>(quote: &'a QuotePresenter) { div[id = "e.dom_id()] { form[id = format!("form_{}", "e.id()), "hx-post" = "/quotes/update", @@ -104,26 +106,20 @@ markup::define! { "hx-swap" = "outerHTML", class = "flex flex-wrap justify-between items-center gap-3 bg-white rounded-md mb-4 px-4 py-2 shadow-[1px_3px_6px_hsl(0,0%,0%,0.1)]", autocomplete = "off", + novalidate, "accept-charset" = "UTF-8"] { - @let form_input_class = if error_message.is_some() { "form-input border-primary" } else { "form-input" }; - @if let Some(message) = error_message { - div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { @message } - } div[class = "[flex:1]"] { - @if let Some(id) = "e.id { - input[id = "quote_id", - name = "id", - "type" = "hidden", - value = id] {} - } + input[id = "quote_id", + name = "id", + "type" = "hidden", + value = "e.id.clone().unwrap()] {} label[class = "visually-hidden", "for" = "quote_name"] { "Name" } input[id = "quote_name", name = "name", - class = form_input_class, + class = "form-input", autofocus = "autofocus", placeholder = "Name of your quote", - required, "type" = "text", value = "e.name] {} } @@ -140,36 +136,113 @@ markup::define! { } } - NewForm<'a>(quote: &'a QuotePresenter, error_message: Option) { - div[id = "e.dom_id()] { + EditFormWithErrors<'a, 'r>(form: &'a Form>) { + @let id = form.context.field_value("id").unwrap_or(""); + @let name = form.context.field_value("name").unwrap_or(""); + @let dom_id = format!("quote_{}", &id); + div[id = &dom_id] { + form[id = format!("form_{}", &id), + "hx-post" = "/quotes/update", + "hx-target" = {format!("#{}", &dom_id)}, + "hx-swap" = "outerHTML", + class = "flex flex-wrap justify-between items-center gap-3 bg-white rounded-md mb-4 px-4 py-2 shadow-[1px_3px_6px_hsl(0,0%,0%,0.1)]", + autocomplete = "off", + novalidate, + "accept-charset" = "UTF-8"] { + + @let messages = form.context.errors().map(|item| item.to_string()).collect::>(); + div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { + @for message in messages { + p { @message } + } + } + + div[class = "[flex:1]"] { + input[id = "quote_id", + name = "id", + "type" = "hidden", + value = &id] {} + label[class = "visually-hidden", "for" = "quote_name"] { "Name" } + input[id = "quote_name", + name = "name", + class = css_for_field(form, "name", "form-input", "border-primary"), + autofocus = "autofocus", + placeholder = "Name of your quote", + "type" = "text", + value = &name] {} + } + a[class = "button button-light", + "hx-get" = {format!("/quotes/{}", &id)}, + "hx-target" = {format!("#{}", &dom_id)}, + "hx-trigger" = "click"] { "Cancel" } + input[name = "commit", + "type" = "submit", + value = "Update quote", + class = "button button-secondary", + "_" = "on click add { pointer-events: none }"] {} + } + } + } + + NewForm() { + div[id = "quote_new"] { form[id = "form_new", "hx-post" = "/quotes/create", "hx-target" = "#quotes_empty", "hx-swap" = "afterend", class = "flex flex-wrap justify-between items-center gap-3 bg-white rounded-md mb-4 px-4 py-2 shadow-[1px_3px_6px_hsl(0,0%,0%,0.1)]", autocomplete = "off", + novalidate, "accept-charset" = "UTF-8"] { - @let form_input_class = if error_message.is_some() { "form-input border-primary" } else { "form-input" }; - @if let Some(message) = error_message { - div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { @message } - } div[class = "[flex:1]"] { - @if let Some(id) = "e.id { - input[id = "quote_id", - name = "id", - "type" = "hidden", - value = id] {} + label[class = "visually-hidden", "for" = "quote_name"] { "Name" } + input[id = "quote_name", + name = "name", + class = "form-input", + autofocus = "autofocus", + placeholder = "Name of your quote", + "type" = "text"] {} + } + a[class = "button button-light", + "_" = "on click remove #form_new"] { "Cancel" } + input[name = "commit", + "type" = "submit", + value = "Create quote", + class = "button button-secondary", + "_" = "on click add { pointer-events: none }"] {} + } + } + } + + NewFormWithErrors<'a, 'r>(form: &'a Form>) { + @let name = form.context.field_value("name").unwrap_or(""); + div[id = "quote_new"] { + form[id = "form_new", + "hx-post" = "/quotes/create", + "hx-target" = "#quotes_empty", + "hx-swap" = "afterend", + class = "flex flex-wrap justify-between items-center gap-3 bg-white rounded-md mb-4 px-4 py-2 shadow-[1px_3px_6px_hsl(0,0%,0%,0.1)]", + autocomplete = "off", + novalidate, + "accept-charset" = "UTF-8"] { + + @let messages = form.context.errors().map(|item| item.to_string()).collect::>(); + div[class = "w-full text-primary bg-primary-bg p-2 rounded-md"] { + @for message in messages { + p { @message } } + } + + div[class = "[flex:1]"] { label[class = "visually-hidden", "for" = "quote_name"] { "Name" } input[id = "quote_name", name = "name", - class = form_input_class, + class = "form-input border-primary", autofocus = "autofocus", placeholder = "Name of your quote", - required, "type" = "text", - value = "e.name] {} + value = &name] {} } a[class = "button button-light", "_" = "on click remove #form_new"] { "Cancel" } diff --git a/src/rocket_ext.rs b/src/rocket_ext.rs new file mode 100644 index 0000000..5da1198 --- /dev/null +++ b/src/rocket_ext.rs @@ -0,0 +1,12 @@ +use rocket::http::Header; + +#[derive(Responder)] +#[response(status = 200, content_type = "html")] +pub(crate) enum HtmxResponder { + Ok(String), + Retarget { + content: String, + retarget: Header<'static>, + reswap: Header<'static>, + }, +} diff --git a/ui/src/app.js b/ui/src/app.js index fdfd8c3..740acaa 100644 --- a/ui/src/app.js +++ b/ui/src/app.js @@ -1,16 +1,3 @@ import "htmx.org"; import * as hyperscript from "hyperscript.org"; hyperscript.browserInit(); - -// document.addEventListener("turbo:before-frame-render", (event) => { -// const inputs = event.detail.newFrame.querySelectorAll("input, select, textarea"); -// inputs.forEach(input => { -// input.addEventListener( -// "invalid", -// _event => { -// input.classList.add("error"); -// }, -// false -// ); -// }); -// }) \ No newline at end of file