diff --git a/flake.lock b/flake.lock index 83909bb..203568a 100644 --- a/flake.lock +++ b/flake.lock @@ -2,16 +2,16 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1721497942, - "narHash": "sha256-EDPL9qJfklXoowl3nEBmjDIqcvXKUZInt5n6CCc1Hn4=", + "lastModified": 1726463316, + "narHash": "sha256-gI9kkaH0ZjakJOKrdjaI/VbaMEo9qBbSUl93DnU7f4c=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d43f0636fc9492e83be8bbb41f9595d7a87106b8", + "rev": "99dc8785f6a0adac95f5e2ab05cc2e1bf666d172", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index e3503a2..929608e 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,6 @@ { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; }; outputs = diff --git a/nix/deploy/qs/default.nix b/nix/deploy/qs/default.nix index dabd468..22e14dc 100644 --- a/nix/deploy/qs/default.nix +++ b/nix/deploy/qs/default.nix @@ -15,5 +15,6 @@ acmeEmail = "thilo.hohlt@tutanota.com"; dnsProvider = "porkbun"; dnsEnvironmentFile = /var/lib/porkbun.env; + disableRegistration = true; }; } diff --git a/nix/module.nix b/nix/module.nix index d939861..dcf73b1 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -75,6 +75,12 @@ in default = null; description = "API secrets for the DNS-01 challenge (required for wildcard domains)."; }; + + disableRegistration = mkOption { + type = types.bool; + default = false; + description = "By default any user can create an account. That behavior can be disabled by using this option."; + }; }; config = mkIf cfg.enable { @@ -108,7 +114,7 @@ in ${pkgs.dbmate}/bin/dbmate --url postgres://postgres@localhost:5432/archtika?sslmode=disable --migrations-dir ${cfg.package}/rest-api/db/migrations up - PGRST_ADMIN_SERVER_PORT=${toString cfg.apiAdminPort} PGRST_SERVER_PORT=${toString cfg.apiPort} PGRST_DB_SCHEMAS="api" PGRST_DB_ANON_ROLE="anon" PGRST_OPENAPI_MODE="ignore-privileges" PGRST_DB_URI="postgres://authenticator@localhost:5432/${cfg.databaseName}" PGRST_JWT_SECRET="$JWT_SECRET" ${pkgs.postgrest}/bin/postgrest + PGRST_SERVER_CORS_ALLOWED_ORIGINS="https://${cfg.domain}" PGRST_ADMIN_SERVER_PORT=${toString cfg.apiAdminPort} PGRST_SERVER_PORT=${toString cfg.apiPort} PGRST_DB_SCHEMAS="api" PGRST_DB_ANON_ROLE="anon" PGRST_OPENAPI_MODE="ignore-privileges" PGRST_DB_URI="postgres://authenticator@localhost:5432/${cfg.databaseName}" PGRST_JWT_SECRET="$JWT_SECRET" ${pkgs.postgrest}/bin/postgrest ''; }; @@ -125,7 +131,7 @@ in }; script = '' - BODY_SIZE_LIMIT=Infinity ORIGIN=https://${cfg.domain} PORT=${toString cfg.webAppPort} ${pkgs.nodejs_22}/bin/node ${cfg.package}/web-app + REGISTRATION_IS_DISABLED=${toString cfg.disableRegistration} BODY_SIZE_LIMIT=10M ORIGIN=https://${cfg.domain} PORT=${toString cfg.webAppPort} ${pkgs.nodejs_22}/bin/node ${cfg.package}/web-app ''; }; @@ -148,6 +154,20 @@ in enable = true; recommendedProxySettings = true; recommendedTlsSettings = true; + recommendedZstdSettings = true; + recommendedOptimisation = true; + + appendHttpConfig = '' + limit_req_zone $binary_remote_addr zone=requestLimit:10m rate=5r/s; + limit_req_status 429; + limit_req zone=requestLimit burst=20 nodelay; + + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Permissions-Policy "accelerometer=(),autoplay=(),camera=(),cross-origin-isolated=(),display-capture=(),encrypted-media=(),fullscreen=(self),geolocation=(),gyroscope=(),keyboard-map=(),magnetometer=(),microphone=(),midi=(),payment=(),picture-in-picture=(self),publickey-credentials-get=(),screen-wake-lock=(),sync-xhr=(self),usb=(),xr-spatial-tracking=(),clipboard-read=(self),clipboard-write=(self),gamepad=(),hid=(),idle-detection=(),interest-cohort=(),serial=(),unload=()" always; + ''; virtualHosts = { "${cfg.domain}" = { @@ -165,14 +185,17 @@ in "/api/" = { proxyPass = "http://localhost:${toString cfg.apiPort}/"; extraConfig = '' - default_type application/json; - proxy_set_header Connection ""; - proxy_http_version 1.1; + default_type application/json; + ''; + }; + "/api/rpc/register" = mkIf cfg.disableRegistration { + extraConfig = '' + deny all; ''; }; }; }; - "~^(?.+)\\.${lib.strings.escapeRegex cfg.domain}$" = { + "~^(?.+)\\.${cfg.domain}$" = { useACMEHost = cfg.domain; forceSSL = true; locations = { diff --git a/rest-api/db/migrations/20240719071602_main_tables.sql b/rest-api/db/migrations/20240719071602_main_tables.sql index 0a1ca79..2c023ab 100644 --- a/rest-api/db/migrations/20240719071602_main_tables.sql +++ b/rest-api/db/migrations/20240719071602_main_tables.sql @@ -25,7 +25,8 @@ CREATE TABLE internal.user ( id UUID PRIMARY KEY DEFAULT gen_random_uuid (), username VARCHAR(16) UNIQUE NOT NULL CHECK (LENGTH(username) >= 3), password_hash CHAR(60) NOT NULL, - role NAME NOT NULL DEFAULT 'authenticated_user' + role NAME NOT NULL DEFAULT 'authenticated_user', + created_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP() ); CREATE TABLE internal.website ( @@ -33,8 +34,8 @@ CREATE TABLE internal.website ( user_id UUID REFERENCES internal.user (id) ON DELETE CASCADE NOT NULL DEFAULT (CURRENT_SETTING('request.jwt.claims', TRUE)::JSON ->> 'user_id') ::UUID, content_type VARCHAR(10) CHECK (content_type IN ('Blog', 'Docs')) NOT NULL, title VARCHAR(50) NOT NULL CHECK (TRIM(title) != ''), - created_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), is_published BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), last_modified_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), last_modified_by UUID REFERENCES internal.user (id) ON DELETE SET NULL, title_search TSVECTOR GENERATED ALWAYS AS (TO_TSVECTOR('english', title)) STORED @@ -52,8 +53,10 @@ CREATE TABLE internal.media ( CREATE TABLE internal.settings ( website_id UUID PRIMARY KEY REFERENCES internal.website (id) ON DELETE CASCADE, - accent_color_light_theme CHAR(7) CHECK (accent_color_light_theme ~ '^#[a-fA-F0-9]{6}$') NOT NULL DEFAULT '#a5d8ff', - accent_color_dark_theme CHAR(7) CHECK (accent_color_dark_theme ~ '^#[a-fA-F0-9]{6}$') NOT NULL DEFAULT '#114678', + accent_color_dark_theme CHAR(7) CHECK (accent_color_light_theme ~ '^#[a-fA-F0-9]{6}$') NOT NULL DEFAULT '#a5d8ff', + accent_color_light_theme CHAR(7) CHECK (accent_color_dark_theme ~ '^#[a-fA-F0-9]{6}$') NOT NULL DEFAULT '#114678', + background_color_dark_theme CHAR(7) CHECK (accent_color_light_theme ~ '^#[a-fA-F0-9]{6}$') NOT NULL DEFAULT '#262626', + background_color_light_theme CHAR(7) CHECK (accent_color_dark_theme ~ '^#[a-fA-F0-9]{6}$') NOT NULL DEFAULT '#ffffff', favicon_image UUID REFERENCES internal.media (id) ON DELETE SET NULL, last_modified_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), last_modified_by UUID REFERENCES internal.user (id) ON DELETE SET NULL @@ -82,6 +85,7 @@ CREATE TABLE internal.docs_category ( user_id UUID REFERENCES internal.user (id) ON DELETE SET NULL DEFAULT (CURRENT_SETTING('request.jwt.claims', TRUE)::JSON ->> 'user_id') ::UUID, category_name VARCHAR(50) NOT NULL CHECK (TRIM(category_name) != ''), category_weight INTEGER CHECK (category_weight >= 0) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), last_modified_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), last_modified_by UUID REFERENCES internal.user (id) ON DELETE SET NULL, UNIQUE (website_id, category_name), @@ -117,6 +121,7 @@ CREATE TABLE internal.footer ( CREATE TABLE internal.legal_information ( website_id UUID PRIMARY KEY REFERENCES internal.website (id) ON DELETE CASCADE, main_content TEXT NOT NULL CHECK (TRIM(main_content) != ''), + created_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), last_modified_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), last_modified_by UUID REFERENCES internal.user (id) ON DELETE SET NULL ); diff --git a/rest-api/db/migrations/20240720132802_exposed_views_functions.sql b/rest-api/db/migrations/20240720132802_exposed_views_functions.sql index 1611e91..0e7e4aa 100644 --- a/rest-api/db/migrations/20240720132802_exposed_views_functions.sql +++ b/rest-api/db/migrations/20240720132802_exposed_views_functions.sql @@ -127,39 +127,39 @@ GRANT SELECT ON api.account TO authenticated_user; GRANT SELECT ON api.user TO authenticated_user; -GRANT SELECT, UPDATE, DELETE ON internal.website TO authenticated_user; +GRANT SELECT, UPDATE (title, is_published), DELETE ON internal.website TO authenticated_user; GRANT SELECT, UPDATE, DELETE ON api.website TO authenticated_user; -GRANT SELECT, UPDATE ON internal.settings TO authenticated_user; +GRANT SELECT, UPDATE (accent_color_dark_theme, accent_color_light_theme, background_color_dark_theme, background_color_light_theme, favicon_image) ON internal.settings TO authenticated_user; GRANT SELECT, UPDATE ON api.settings TO authenticated_user; -GRANT SELECT, UPDATE ON internal.header TO authenticated_user; +GRANT SELECT, UPDATE (logo_type, logo_text, logo_image) ON internal.header TO authenticated_user; GRANT SELECT, UPDATE ON api.header TO authenticated_user; -GRANT SELECT, UPDATE ON internal.home TO authenticated_user; +GRANT SELECT, UPDATE (main_content) ON internal.home TO authenticated_user; GRANT SELECT, UPDATE ON api.home TO authenticated_user; -GRANT SELECT, INSERT, UPDATE, DELETE ON internal.article TO authenticated_user; +GRANT SELECT, INSERT (website_id, title, meta_description, meta_author, cover_image, publication_date, main_content, category, article_weight), UPDATE (title, meta_description, meta_author, cover_image, publication_date, main_content, category, article_weight), DELETE ON internal.article TO authenticated_user; GRANT SELECT, INSERT, UPDATE, DELETE ON api.article TO authenticated_user; -GRANT SELECT, INSERT, UPDATE, DELETE ON internal.docs_category TO authenticated_user; +GRANT SELECT, INSERT (website_id, category_name, category_weight), UPDATE (category_name, category_weight), DELETE ON internal.docs_category TO authenticated_user; GRANT SELECT, INSERT, UPDATE, DELETE ON api.docs_category TO authenticated_user; -GRANT SELECT, UPDATE ON internal.footer TO authenticated_user; +GRANT SELECT, UPDATE (additional_text) ON internal.footer TO authenticated_user; GRANT SELECT, UPDATE ON api.footer TO authenticated_user; -GRANT SELECT, INSERT, UPDATE, DELETE ON internal.legal_information TO authenticated_user; +GRANT SELECT, INSERT (website_id, main_content), UPDATE (website_id, main_content), DELETE ON internal.legal_information TO authenticated_user; GRANT SELECT, INSERT, UPDATE, DELETE ON api.legal_information TO authenticated_user; -GRANT SELECT, INSERT, UPDATE, DELETE ON internal.collab TO authenticated_user; +GRANT SELECT, INSERT (website_id, user_id, permission_level), UPDATE (permission_level), DELETE ON internal.collab TO authenticated_user; GRANT SELECT, INSERT, UPDATE, DELETE ON api.collab TO authenticated_user; diff --git a/rest-api/db/migrations/20240805132306_last_modified_triggers.sql b/rest-api/db/migrations/20240805132306_last_modified_triggers.sql index ea8794b..bcc55e1 100644 --- a/rest-api/db/migrations/20240805132306_last_modified_triggers.sql +++ b/rest-api/db/migrations/20240805132306_last_modified_triggers.sql @@ -30,7 +30,8 @@ BEGIN RETURN COALESCE(NEW, OLD); END; $$ -LANGUAGE plpgsql; +LANGUAGE plpgsql +SECURITY DEFINER; CREATE TRIGGER update_website_last_modified BEFORE UPDATE ON internal.website @@ -68,7 +69,7 @@ CREATE TRIGGER update_footer_last_modified EXECUTE FUNCTION internal.update_last_modified (); CREATE TRIGGER update_legal_information_last_modified - BEFORE INSERT OR DELETE ON internal.legal_information + BEFORE INSERT OR UPDATE OR DELETE ON internal.legal_information FOR EACH ROW EXECUTE FUNCTION internal.update_last_modified (); diff --git a/rest-api/db/migrations/20240810115846_image_upload_function.sql b/rest-api/db/migrations/20240810115846_image_upload_function.sql index e94d73a..dd9af74 100644 --- a/rest-api/db/migrations/20240810115846_image_upload_function.sql +++ b/rest-api/db/migrations/20240810115846_image_upload_function.sql @@ -8,7 +8,7 @@ DECLARE _website_id UUID := (_headers ->> 'x-website-id')::UUID; _mimetype TEXT := _headers ->> 'x-mimetype'; _original_filename TEXT := _headers ->> 'x-original-filename'; - _allowed_mimetypes TEXT[] := ARRAY['image/png', 'image/jpeg', 'image/webp']; + _allowed_mimetypes TEXT[] := ARRAY['image/png', 'image/jpeg', 'image/webp', 'image/avif', 'image/gif', 'image/svg+xml']; _max_file_size INT := 5 * 1024 * 1024; _has_access BOOLEAN; BEGIN diff --git a/rest-api/db/migrations/20240920090915_custom_domain_prefix.sql b/rest-api/db/migrations/20240920090915_custom_domain_prefix.sql new file mode 100644 index 0000000..ba1dece --- /dev/null +++ b/rest-api/db/migrations/20240920090915_custom_domain_prefix.sql @@ -0,0 +1,57 @@ +-- migrate:up +CREATE TABLE internal.domain_prefix ( + website_id UUID PRIMARY KEY REFERENCES internal.website (id) ON DELETE CASCADE, + prefix VARCHAR(16) UNIQUE NOT NULL CHECK (LENGTH(prefix) >= 3 AND prefix ~ '^[a-z]+(-[a-z]+)*$'), + created_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), + last_modified_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(), + last_modified_by UUID REFERENCES internal.user (id) ON DELETE SET NULL +); + +CREATE VIEW api.domain_prefix WITH ( security_invoker = ON +) AS +SELECT + * +FROM + internal.domain_prefix; + +GRANT SELECT, INSERT (website_id, prefix), UPDATE (website_id, prefix), DELETE ON internal.domain_prefix TO authenticated_user; + +GRANT SELECT, INSERT, UPDATE, DELETE ON api.domain_prefix TO authenticated_user; + +ALTER TABLE internal.domain_prefix ENABLE ROW LEVEL SECURITY; + +CREATE POLICY view_domain_prefix ON internal.domain_prefix + FOR SELECT + USING (internal.user_has_website_access (website_id, 10)); + +CREATE POLICY update_domain_prefix ON internal.domain_prefix + FOR UPDATE + USING (internal.user_has_website_access (website_id, 30)); + +CREATE POLICY delete_domain_prefix ON internal.domain_prefix + FOR DELETE + USING (internal.user_has_website_access (website_id, 30)); + +CREATE POLICY insert_domain_prefix ON internal.domain_prefix + FOR INSERT + WITH CHECK (internal.user_has_website_access (website_id, 30)); + +CREATE TRIGGER update_domain_prefix_last_modified + BEFORE INSERT OR UPDATE OR DELETE ON internal.domain_prefix + FOR EACH ROW + EXECUTE FUNCTION internal.update_last_modified (); + +CREATE TRIGGER domain_prefix_track_changes + AFTER INSERT OR UPDATE OR DELETE ON internal.domain_prefix + FOR EACH ROW + EXECUTE FUNCTION internal.track_changes (); + +-- migrate:down +DROP TRIGGER domain_prefix_track_changes ON internal.domain_prefix; + +DROP TRIGGER update_domain_prefix_last_modified ON internal.domain_prefix; + +DROP VIEW api.domain_prefix; + +DROP TABLE internal.domain_prefix; + diff --git a/web-app/package-lock.json b/web-app/package-lock.json index 97b6ede..12e611a 100644 --- a/web-app/package-lock.json +++ b/web-app/package-lock.json @@ -10,32 +10,32 @@ "dependencies": { "fast-diff": "1.3.0", "highlight.js": "11.10.0", - "isomorphic-dompurify": "2.14.0", - "marked": "14.0.0", + "isomorphic-dompurify": "2.15.0", + "marked": "14.1.2", "marked-highlight": "2.1.4" }, "devDependencies": { - "@playwright/test": "1.40.0", - "@sveltejs/adapter-auto": "3.2.4", - "@sveltejs/adapter-node": "5.2.2", - "@sveltejs/kit": "2.5.22", - "@sveltejs/vite-plugin-svelte": "3.1.1", + "@playwright/test": "1.46.0", + "@sveltejs/adapter-auto": "3.2.5", + "@sveltejs/adapter-node": "5.2.3", + "@sveltejs/kit": "2.5.28", + "@sveltejs/vite-plugin-svelte": "4.0.0-next.6", "@types/eslint": "9.6.1", "@types/eslint__js": "8.42.3", "@types/eslint-config-prettier": "6.11.3", - "@types/node": "22.2.0", + "@types/node": "22.5.5", "eslint": "9.10.0", "eslint-config-prettier": "9.1.0", - "eslint-plugin-svelte": "2.43.0", + "eslint-plugin-svelte": "2.44.0", "globals": "15.9.0", "pg-to-ts": "4.1.1", "prettier": "3.3.3", "prettier-plugin-svelte": "3.2.6", - "svelte": "5.0.0-next.220", - "svelte-check": "3.8.5", - "typescript": "5.5.4", - "typescript-eslint": "8.4.0", - "vite": "5.4.0" + "svelte": "5.0.0-next.253", + "svelte-check": "4.0.2", + "typescript": "5.6.2", + "typescript-eslint": "8.6.0", + "vite": "5.4.6" } }, "node_modules/@ampproject/remapping": { @@ -764,19 +764,19 @@ } }, "node_modules/@playwright/test": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.0.tgz", - "integrity": "sha512-PdW+kn4eV99iP5gxWNSDQCbhMaDVej+RXL5xr6t04nbKLCBwYtA046t7ofoczHOm8u6c+45hpDKQVZqtqwkeQg==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.0.tgz", + "integrity": "sha512-/QYft5VArOrGRP5pgkrfKksqsKA6CEFyGQ/gjNe6q0y4tZ1aaPfq4gIjudr1s3D+pXyrPRdsy4opKDrjBabE5w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.40.0" + "playwright": "1.46.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/@polka/url": { @@ -883,9 +883,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.20.0.tgz", - "integrity": "sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", + "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", "cpu": [ "arm" ], @@ -897,9 +897,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.20.0.tgz", - "integrity": "sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", + "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", "cpu": [ "arm64" ], @@ -911,9 +911,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.20.0.tgz", - "integrity": "sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", + "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", "cpu": [ "arm64" ], @@ -925,9 +925,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.20.0.tgz", - "integrity": "sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", + "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", "cpu": [ "x64" ], @@ -939,9 +939,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.20.0.tgz", - "integrity": "sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", + "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", "cpu": [ "arm" ], @@ -953,9 +953,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.20.0.tgz", - "integrity": "sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", + "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", "cpu": [ "arm" ], @@ -967,9 +967,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.20.0.tgz", - "integrity": "sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", + "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", "cpu": [ "arm64" ], @@ -981,9 +981,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.20.0.tgz", - "integrity": "sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", + "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", "cpu": [ "arm64" ], @@ -995,9 +995,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.20.0.tgz", - "integrity": "sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", + "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", "cpu": [ "ppc64" ], @@ -1009,9 +1009,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.20.0.tgz", - "integrity": "sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", + "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", "cpu": [ "riscv64" ], @@ -1023,9 +1023,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.20.0.tgz", - "integrity": "sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", + "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", "cpu": [ "s390x" ], @@ -1037,9 +1037,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz", - "integrity": "sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", + "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", "cpu": [ "x64" ], @@ -1051,9 +1051,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.20.0.tgz", - "integrity": "sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", + "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", "cpu": [ "x64" ], @@ -1065,9 +1065,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.20.0.tgz", - "integrity": "sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", + "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", "cpu": [ "arm64" ], @@ -1079,9 +1079,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.20.0.tgz", - "integrity": "sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", + "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", "cpu": [ "ia32" ], @@ -1093,9 +1093,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.20.0.tgz", - "integrity": "sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", + "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", "cpu": [ "x64" ], @@ -1107,9 +1107,9 @@ ] }, "node_modules/@sveltejs/adapter-auto": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-3.2.4.tgz", - "integrity": "sha512-a64AKYbfTUrVwU0xslzv1Jf3M8bj0IwhptaXmhgIkjXspBXhD0od9JiItQHchijpLMGdEDcYBlvqySkEawv6mQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-3.2.5.tgz", + "integrity": "sha512-27LR+uKccZ62lgq4N/hvyU2G+hTP9fxWEAfnZcl70HnyfAjMSsGk1z/SjAPXNCD1mVJIE7IFu3TQ8cQ/UH3c0A==", "dev": true, "license": "MIT", "dependencies": { @@ -1120,9 +1120,9 @@ } }, "node_modules/@sveltejs/adapter-node": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.2.2.tgz", - "integrity": "sha512-BCX4zP0cf86TXpmvLQTnnT/tp7P12UMezf+5LwljP1MJC1fFzn9XOXpAHQCyP+pyHGy2K7p5gY0LyLcZFAL02w==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.2.3.tgz", + "integrity": "sha512-0KNrTc9NiEhB1vyVL0HiqZaW2P5JWNJgTYT5PnUZCLO9Oydx8G+6PNtJPJ/NNPyeGrn+6LwR5L8GNRvA4b5Bpw==", "dev": true, "license": "MIT", "dependencies": { @@ -1136,9 +1136,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.5.22", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.22.tgz", - "integrity": "sha512-PQ98baF2WzvG5yiO4cZKJZJG60XjHTZD1jyho3u9Kmthx2ytdGYyVPPvKXgKXpKSq4wwctD9dl0d2blSbJMcOg==", + "version": "2.5.28", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.28.tgz", + "integrity": "sha512-/O7pvFGBsQPcFa9UrW8eUC5uHTOXLsUp3SN0dY6YmRAL9nfPSrJsSJk//j5vMpinSshzUjteAFcfQTU+04Ka1w==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1163,65 +1163,51 @@ "node": ">=18.13" }, "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3" } }, "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-3.1.1.tgz", - "integrity": "sha512-rimpFEAboBBHIlzISibg94iP09k/KYdHgVhJlcsTfn7KMBhc70jFX/GRWkRdFCc2fdnk+4+Bdfej23cMDnJS6A==", + "version": "4.0.0-next.6", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-4.0.0-next.6.tgz", + "integrity": "sha512-7+bEFN5F9pthG6nOEHNz9yioHxNXK6yl+0GnTy9WOfxN/SvPykkH/Hs6MqTGjo47a9G2q3QXQnzuxG5WXNX4Tg==", "dev": true, "license": "MIT", "dependencies": { - "@sveltejs/vite-plugin-svelte-inspector": "^2.1.0", - "debug": "^4.3.4", + "@sveltejs/vite-plugin-svelte-inspector": "^3.0.0-next.0||^3.0.0", + "debug": "^4.3.6", "deepmerge": "^4.3.1", "kleur": "^4.1.5", - "magic-string": "^0.30.10", - "svelte-hmr": "^0.16.0", + "magic-string": "^0.30.11", "vitefu": "^0.2.5" }, "engines": { - "node": "^18.0.0 || >=20" + "node": "^18.0.0 || ^20.0.0 || >=22" }, "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.0", + "svelte": "^5.0.0-next.96 || ^5.0.0", "vite": "^5.0.0" } }, "node_modules/@sveltejs/vite-plugin-svelte-inspector": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-2.1.0.tgz", - "integrity": "sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==", + "version": "3.0.0-next.3", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-3.0.0-next.3.tgz", + "integrity": "sha512-kuGJ2CZ5lAw3gKF8Kw0AfKtUJWbwdlDHY14K413B0MCyrzvQvsKTorwmwZcky0+QqY6RnVIZ/5FttB9bQmkLXg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.4" + "debug": "^4.3.5" }, "engines": { - "node": "^18.0.0 || >=20" + "node": "^18.0.0 || ^20.0.0 || >=22" }, "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.0", - "svelte": "^4.0.0 || ^5.0.0-next.0", + "@sveltejs/vite-plugin-svelte": "^4.0.0-next.0||^4.0.0", + "svelte": "^5.0.0-next.96 || ^5.0.0", "vite": "^5.0.0" } }, - "node_modules/@sveltejs/vite-plugin-svelte/node_modules/svelte-hmr": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz", - "integrity": "sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^12.20 || ^14.13.1 || >= 16" - }, - "peerDependencies": { - "svelte": "^3.19.0 || ^4.0.0" - } - }, "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", @@ -1281,22 +1267,15 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz", - "integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==", + "version": "22.5.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz", + "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.13.0" + "undici-types": "~6.19.2" } }, - "node_modules/@types/pug": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz", - "integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -1311,17 +1290,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.4.0.tgz", - "integrity": "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz", + "integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.4.0", - "@typescript-eslint/type-utils": "8.4.0", - "@typescript-eslint/utils": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/type-utils": "8.6.0", + "@typescript-eslint/utils": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1345,16 +1324,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.4.0.tgz", - "integrity": "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz", + "integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.4.0", - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/typescript-estree": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4" }, "engines": { @@ -1374,14 +1353,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.4.0.tgz", - "integrity": "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", + "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0" + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1392,14 +1371,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.4.0.tgz", - "integrity": "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", + "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.4.0", - "@typescript-eslint/utils": "8.4.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/utils": "8.6.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1417,9 +1396,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.4.0.tgz", - "integrity": "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", + "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", "dev": true, "license": "MIT", "engines": { @@ -1431,14 +1410,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.4.0.tgz", - "integrity": "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", + "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1460,16 +1439,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.4.0.tgz", - "integrity": "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", + "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.4.0", - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/typescript-estree": "8.4.0" + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1483,13 +1462,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.4.0.tgz", - "integrity": "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", + "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/types": "8.6.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -1623,13 +1602,13 @@ "license": "Python-2.0" }, "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", + "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", "dev": true, "license": "Apache-2.0", - "dependencies": { - "dequal": "^2.0.3" + "engines": { + "node": ">= 0.4" } }, "node_modules/assert-options": { @@ -1701,16 +1680,6 @@ "node": ">=8" } }, - "node_modules/buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -1995,23 +1964,17 @@ } }, "node_modules/cssstyle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", - "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "license": "MIT", "dependencies": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" }, "engines": { "node": ">=18" } }, - "node_modules/cssstyle/node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "license": "MIT" - }, "node_modules/data-urls": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", @@ -2074,26 +2037,6 @@ "node": ">=0.4.0" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/devalue": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.0.0.tgz", @@ -2170,13 +2113,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", - "dev": true, - "license": "MIT" - }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -2329,9 +2265,9 @@ } }, "node_modules/eslint-plugin-svelte": { - "version": "2.43.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.43.0.tgz", - "integrity": "sha512-REkxQWvg2pp7QVLxQNa+dJ97xUqRe7Y2JJbSWkHSuszu0VcblZtXkPBPckkivk99y5CdLw4slqfPylL2d/X4jQ==", + "version": "2.44.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.44.0.tgz", + "integrity": "sha512-wav4MOs02vBb1WjvTCYItwJCxMkuk2Z4p+K/eyjL0N/z7ahXLP+0LtQQjiKc2ezuif7GnZLbD1F3o1VHzSvdVg==", "dev": true, "license": "MIT", "dependencies": { @@ -2345,7 +2281,7 @@ "postcss-safe-parser": "^6.0.0", "postcss-selector-parser": "^6.1.0", "semver": "^7.6.2", - "svelte-eslint-parser": "^0.41.0" + "svelte-eslint-parser": "^0.41.1" }, "engines": { "node": "^14.17.0 || >=16.0.0" @@ -2691,13 +2627,6 @@ "node": ">= 6" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2794,13 +2723,6 @@ "dev": true, "license": "MIT" }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -2938,25 +2860,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "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, - "license": "ISC" - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3086,14 +2989,14 @@ "license": "ISC" }, "node_modules/isomorphic-dompurify": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/isomorphic-dompurify/-/isomorphic-dompurify-2.14.0.tgz", - "integrity": "sha512-7xyjuzBf3P/HBt0PbOpmv5LuV38TmfvidBFvgyuSWVMLwCGDITBPHWsBZ/L1a8DpcGz5PEintBeGdlrKzUqt5A==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/isomorphic-dompurify/-/isomorphic-dompurify-2.15.0.tgz", + "integrity": "sha512-RDHlyeVmwEDAPZuX1VaaBzSn9RrsfvswxH7faEQK9cTHC1dXeNuK6ElUeSr7locFyeLguut8ASfhQWxHB4Ttug==", "license": "MIT", "dependencies": { "@types/dompurify": "^3.0.5", "dompurify": "^3.1.6", - "jsdom": "^24.1.1" + "jsdom": "^25.0.0" }, "engines": { "node": ">=18" @@ -3129,9 +3032,9 @@ } }, "node_modules/jsdom": { - "version": "24.1.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.3.tgz", - "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==", + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.0.tgz", + "integrity": "sha512-OhoFVT59T7aEq75TVw9xxEfkXgacpqAhQaYgP9y/fDqWQCMB/b1H66RfmPm/MaeaAIU9nDwMOVTlPN51+ao6CQ==", "license": "MIT", "dependencies": { "cssstyle": "^4.0.1", @@ -3295,9 +3198,9 @@ } }, "node_modules/marked": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", - "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.2.tgz", + "integrity": "sha512-f3r0yqpz31VXiDB/wj9GaOB0a2PRLQl6vJmXiFrniNwjkKdvakqJRULhjFKJpxOchlCRiG5fcacoUZY5Xa6PEQ==", "license": "MIT", "bin": { "marked": "bin/marked.js" @@ -3360,16 +3263,6 @@ "node": ">= 0.6" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -3386,16 +3279,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -3406,19 +3289,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -3487,16 +3357,6 @@ "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", "license": "MIT" }, - "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, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3596,16 +3456,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -3777,9 +3627,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true, "license": "ISC" }, @@ -3797,35 +3647,35 @@ } }, "node_modules/playwright": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.0.tgz", - "integrity": "sha512-gyHAgQjiDf1m34Xpwzaqb76KgfzYrhK7iih+2IzcOCoZWr/8ZqmdBw+t0RU85ZmfJMgtgAiNtBQ/KS2325INXw==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz", + "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.40.0" + "playwright-core": "1.46.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.0.tgz", - "integrity": "sha512-fvKewVJpGeca8t0ipM56jkVSU6Eo0RmFvQ/MaCQNDYm+sdvKkMBBWTE1FdeMqIdumRaXXjZChWHvIzCGM/tA/Q==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz", + "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==", "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/playwright/node_modules/fsevents": { @@ -3844,9 +3694,9 @@ } }, "node_modules/postcss": { - "version": "8.4.40", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", - "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -3865,8 +3715,8 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -4157,70 +4007,10 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/rollup": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.20.0.tgz", - "integrity": "sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", + "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", "dev": true, "license": "MIT", "dependencies": { @@ -4234,22 +4024,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.20.0", - "@rollup/rollup-android-arm64": "4.20.0", - "@rollup/rollup-darwin-arm64": "4.20.0", - "@rollup/rollup-darwin-x64": "4.20.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.20.0", - "@rollup/rollup-linux-arm-musleabihf": "4.20.0", - "@rollup/rollup-linux-arm64-gnu": "4.20.0", - "@rollup/rollup-linux-arm64-musl": "4.20.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.20.0", - "@rollup/rollup-linux-riscv64-gnu": "4.20.0", - "@rollup/rollup-linux-s390x-gnu": "4.20.0", - "@rollup/rollup-linux-x64-gnu": "4.20.0", - "@rollup/rollup-linux-x64-musl": "4.20.0", - "@rollup/rollup-win32-arm64-msvc": "4.20.0", - "@rollup/rollup-win32-ia32-msvc": "4.20.0", - "@rollup/rollup-win32-x64-msvc": "4.20.0", + "@rollup/rollup-android-arm-eabi": "4.22.4", + "@rollup/rollup-android-arm64": "4.22.4", + "@rollup/rollup-darwin-arm64": "4.22.4", + "@rollup/rollup-darwin-x64": "4.22.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", + "@rollup/rollup-linux-arm-musleabihf": "4.22.4", + "@rollup/rollup-linux-arm64-gnu": "4.22.4", + "@rollup/rollup-linux-arm64-musl": "4.22.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", + "@rollup/rollup-linux-riscv64-gnu": "4.22.4", + "@rollup/rollup-linux-s390x-gnu": "4.22.4", + "@rollup/rollup-linux-x64-gnu": "4.22.4", + "@rollup/rollup-linux-x64-musl": "4.22.4", + "@rollup/rollup-win32-arm64-msvc": "4.22.4", + "@rollup/rollup-win32-ia32-msvc": "4.22.4", + "@rollup/rollup-win32-x64-msvc": "4.22.4", "fsevents": "~2.3.2" } }, @@ -4302,19 +4092,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, - "node_modules/sander": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", - "integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es6-promise": "^3.1.2", - "graceful-fs": "^4.1.3", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.2" - } - }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -4405,26 +4182,10 @@ "node": ">= 10" } }, - "node_modules/sorcery": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.1.tgz", - "integrity": "sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.14", - "buffer-crc32": "^1.0.0", - "minimist": "^1.2.0", - "sander": "^0.5.0" - }, - "bin": { - "sorcery": "bin/sorcery" - } - }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -4555,19 +4316,6 @@ "node": ">=8" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4608,24 +4356,24 @@ } }, "node_modules/svelte": { - "version": "5.0.0-next.220", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.0.0-next.220.tgz", - "integrity": "sha512-ETTqNWJXr2RNnKjDZpHmVghBeD8lfFy1OO1BHQvNQXwmwu1rGIGre75vSVsLW35FYRXb/tJ7G225w9vrhY9eAg==", + "version": "5.0.0-next.253", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.0.0-next.253.tgz", + "integrity": "sha512-s32X0g/yJJcada3+ZdQiirospMUSl4f8h8/hrMeJ7Oim6+bWccP4pZaKQY+x+LCqyzmBNMxVm3j7+SU5xOaAzg==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.1", - "@jridgewell/sourcemap-codec": "^1.4.15", + "@ampproject/remapping": "^2.3.0", + "@jridgewell/sourcemap-codec": "^1.5.0", "@types/estree": "^1.0.5", - "acorn": "^8.11.3", + "acorn": "^8.12.1", "acorn-typescript": "^1.4.13", - "aria-query": "^5.3.0", - "axobject-query": "^4.0.0", + "aria-query": "^5.3.1", + "axobject-query": "^4.1.0", "esm-env": "^1.0.0", "esrap": "^1.2.2", "is-reference": "^3.0.2", "locate-character": "^3.0.0", - "magic-string": "^0.30.5", + "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" }, "engines": { @@ -4633,30 +4381,63 @@ } }, "node_modules/svelte-check": { - "version": "3.8.5", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.8.5.tgz", - "integrity": "sha512-3OGGgr9+bJ/+1nbPgsvulkLC48xBsqsgtc8Wam281H4G9F5v3mYGa2bHRsPuwHC5brKl4AxJH95QF73kmfihGQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.0.2.tgz", + "integrity": "sha512-w2yqcG9ELJe2RJCnAvB7v0OgkHhL3czzz/tVoxGFfO6y4mOrF6QHCDhXijeXzsU7LVKEwWS3Qd9tza4JBuDxqA==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^3.4.1", + "fdir": "^6.2.0", "picocolors": "^1.0.0", - "sade": "^1.7.4", - "svelte-preprocess": "^5.1.3", - "typescript": "^5.0.3" + "sade": "^1.7.4" }, "bin": { "svelte-check": "bin/svelte-check" }, + "engines": { + "node": ">= 18.0.0" + }, "peerDependencies": { - "svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0" + "svelte": "^4.0.0 || ^5.0.0-next.0", + "typescript": ">=5.0.0" + } + }, + "node_modules/svelte-check/node_modules/fdir": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.3.0.tgz", + "integrity": "sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/svelte-check/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/svelte-eslint-parser": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.41.0.tgz", - "integrity": "sha512-L6f4hOL+AbgfBIB52Z310pg1d2QjRqm7wy3kI1W6hhdhX5bvu7+f0R6w4ykp5HoDdzq+vGhIJmsisaiJDGmVfA==", + "version": "0.41.1", + "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.41.1.tgz", + "integrity": "sha512-08ndI6zTghzI8SuJAFpvMbA/haPSGn3xz19pjre19yYMw8Nw/wQJ2PrZBI/L8ijGTgtkWCQQiLLy+Z1tfaCwNA==", "dev": true, "license": "MIT", "dependencies": { @@ -4729,69 +4510,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/svelte-preprocess": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.4.tgz", - "integrity": "sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@types/pug": "^2.0.6", - "detect-indent": "^6.1.0", - "magic-string": "^0.30.5", - "sorcery": "^0.11.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">= 16.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.10.2", - "coffeescript": "^2.5.1", - "less": "^3.11.3 || ^4.0.0", - "postcss": "^7 || ^8", - "postcss-load-config": "^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", - "pug": "^3.0.0", - "sass": "^1.26.8", - "stylus": "^0.55.0", - "sugarss": "^2.0.0 || ^3.0.0 || ^4.0.0", - "svelte": "^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0", - "typescript": ">=3.9.5 || ^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "coffeescript": { - "optional": true - }, - "less": { - "optional": true - }, - "postcss": { - "optional": true - }, - "postcss-load-config": { - "optional": true - }, - "pug": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, "node_modules/svelte/node_modules/is-reference": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", @@ -4903,9 +4621,9 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4917,15 +4635,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.4.0.tgz", - "integrity": "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.6.0.tgz", + "integrity": "sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.4.0", - "@typescript-eslint/parser": "8.4.0", - "@typescript-eslint/utils": "8.4.0" + "@typescript-eslint/eslint-plugin": "8.6.0", + "@typescript-eslint/parser": "8.6.0", + "@typescript-eslint/utils": "8.6.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4961,9 +4679,9 @@ } }, "node_modules/undici-types": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", - "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true, "license": "MIT" }, @@ -5004,15 +4722,15 @@ "license": "MIT" }, "node_modules/vite": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.0.tgz", - "integrity": "sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", + "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.21.3", - "postcss": "^8.4.40", - "rollup": "^4.13.0" + "postcss": "^8.4.43", + "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" @@ -5257,13 +4975,6 @@ "node": ">=8" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, "node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", diff --git a/web-app/package.json b/web-app/package.json index 44c0c95..79e6551 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -14,34 +14,34 @@ "gents": "pg-to-ts generate -c postgres://postgres@localhost:15432/archtika -o src/lib/db-schema.ts -s internal" }, "devDependencies": { - "@playwright/test": "1.40.0", - "@sveltejs/adapter-auto": "3.2.4", - "@sveltejs/adapter-node": "5.2.2", - "@sveltejs/kit": "2.5.22", - "@sveltejs/vite-plugin-svelte": "3.1.1", + "@playwright/test": "1.46.0", + "@sveltejs/adapter-auto": "3.2.5", + "@sveltejs/adapter-node": "5.2.3", + "@sveltejs/kit": "2.5.28", + "@sveltejs/vite-plugin-svelte": "4.0.0-next.6", "@types/eslint": "9.6.1", "@types/eslint__js": "8.42.3", "@types/eslint-config-prettier": "6.11.3", - "@types/node": "22.2.0", + "@types/node": "22.5.5", "eslint": "9.10.0", "eslint-config-prettier": "9.1.0", - "eslint-plugin-svelte": "2.43.0", + "eslint-plugin-svelte": "2.44.0", "globals": "15.9.0", "pg-to-ts": "4.1.1", "prettier": "3.3.3", "prettier-plugin-svelte": "3.2.6", - "svelte": "5.0.0-next.220", - "svelte-check": "3.8.5", - "typescript": "5.5.4", - "typescript-eslint": "8.4.0", - "vite": "5.4.0" + "svelte": "5.0.0-next.253", + "svelte-check": "4.0.2", + "typescript": "5.6.2", + "typescript-eslint": "8.6.0", + "vite": "5.4.6" }, "type": "module", "dependencies": { "fast-diff": "1.3.0", "highlight.js": "11.10.0", - "isomorphic-dompurify": "2.14.0", - "marked": "14.0.0", + "isomorphic-dompurify": "2.15.0", + "marked": "14.1.2", "marked-highlight": "2.1.4" } } diff --git a/web-app/src/hooks.server.ts b/web-app/src/hooks.server.ts index 51a677c..73cf58b 100644 --- a/web-app/src/hooks.server.ts +++ b/web-app/src/hooks.server.ts @@ -1,32 +1,36 @@ import { redirect } from "@sveltejs/kit"; -import { API_BASE_PREFIX } from "$lib/server/utils"; -import type { User } from "$lib/db-schema"; +import { API_BASE_PREFIX, apiRequest } from "$lib/server/utils"; export const handle = async ({ event, resolve }) => { if (!event.url.pathname.startsWith("/api/")) { - const userData = await event.fetch(`${API_BASE_PREFIX}/account`, { - method: "GET", + const userData = await apiRequest(event.fetch, `${API_BASE_PREFIX}/account`, "GET", { headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${event.cookies.get("session_token")}`, - Accept: "application/vnd.pgrst.object+json" - } + Accept: "application/vnd.pgrst.object+json", + Authorization: `Bearer ${event.cookies.get("session_token")}` + }, + returnData: true }); - if (!userData.ok && !["/login", "/register"].includes(event.url.pathname)) { + if (!userData.success && !["/login", "/register"].includes(event.url.pathname)) { throw redirect(303, "/login"); } - if (userData.ok) { + if (userData.success) { if (["/login", "/register"].includes(event.url.pathname)) { throw redirect(303, "/"); } - const user: User = await userData.json(); - - event.locals.user = user; + event.locals.user = userData.data; } } return await resolve(event); }; + +export const handleFetch = async ({ event, request, fetch }) => { + if (event.locals.user) { + request.headers.set("Authorization", `Bearer ${event.cookies.get("session_token")}`); + } + + return fetch(request); +}; diff --git a/web-app/src/lib/components/LoadingSpinner.svelte b/web-app/src/lib/components/LoadingSpinner.svelte index 6eb9339..12ee598 100644 --- a/web-app/src/lib/components/LoadingSpinner.svelte +++ b/web-app/src/lib/components/LoadingSpinner.svelte @@ -10,7 +10,7 @@ .spinner { position: fixed; inset: 0; - background-color: rgba(0, 0, 0, 0.5); + background-color: var(--bg-blurred); z-index: 40; } @@ -27,6 +27,6 @@ border: var(--border-primary); border-width: 0.125rem; border-block-start-color: var(--color-accent); - animation: spinner 0.6s linear infinite; + animation: spinner 500ms linear infinite; } diff --git a/web-app/src/lib/components/MarkdownEditor.svelte b/web-app/src/lib/components/MarkdownEditor.svelte new file mode 100644 index 0000000..cbe47c6 --- /dev/null +++ b/web-app/src/lib/components/MarkdownEditor.svelte @@ -0,0 +1,72 @@ + + + diff --git a/web-app/src/lib/components/Modal.svelte b/web-app/src/lib/components/Modal.svelte index 0f446c4..2a01eef 100644 --- a/web-app/src/lib/components/Modal.svelte +++ b/web-app/src/lib/components/Modal.svelte @@ -39,7 +39,7 @@ position: fixed; inset: 0; z-index: 10; - background-color: rgba(0, 0, 0, 0.5); + background-color: var(--bg-blurred); } .modal__content { diff --git a/web-app/src/lib/components/WebsiteEditor.svelte b/web-app/src/lib/components/WebsiteEditor.svelte index 0038b73..267831d 100644 --- a/web-app/src/lib/components/WebsiteEditor.svelte +++ b/web-app/src/lib/components/WebsiteEditor.svelte @@ -2,30 +2,27 @@ import type { Snippet } from "svelte"; import { md } from "$lib/utils"; import { page } from "$app/stores"; + import { previewContent, textareaScrollTop } from "$lib/runes.svelte"; const { id, contentType, title, children, - fullPreview = false, - previewContent, - previewScrollTop = 0 + fullPreview = false }: { id: string; contentType: string; title: string; children: Snippet; fullPreview?: boolean; - previewContent: string; - previewScrollTop?: number; } = $props(); let previewElement: HTMLDivElement; $effect(() => { const scrollHeight = previewElement.scrollHeight - previewElement.clientHeight; - previewElement.scrollTop = (previewScrollTop / 100) * scrollHeight; + previewElement.scrollTop = (textareaScrollTop.value / 100) * scrollHeight; }); @@ -66,9 +63,12 @@
{#if fullPreview} - + {:else} - {@html md(previewContent, Object.keys($page.params).length > 1 ? true : false)} + {@html md( + previewContent.value || "Write some markdown content to see a live preview here", + Object.keys($page.params).length > 1 ? true : false + )} {/if}
diff --git a/web-app/src/lib/db-schema.ts b/web-app/src/lib/db-schema.ts index 1e45e9d..a02fb53 100644 --- a/web-app/src/lib/db-schema.ts +++ b/web-app/src/lib/db-schema.ts @@ -5,7 +5,7 @@ * AUTO-GENERATED FILE - DO NOT EDIT! * * This file was automatically generated by pg-to-ts v.4.1.1 - * $ pg-to-ts generate -c postgres://username:password@localhost:15432/archtika -t article -t change_log -t collab -t docs_category -t footer -t header -t home -t legal_information -t media -t settings -t user -t website -s internal + * $ pg-to-ts generate -c postgres://username:password@localhost:15432/archtika -t article -t change_log -t collab -t docs_category -t domain_prefix -t footer -t header -t home -t legal_information -t media -t settings -t user -t website -s internal * */ @@ -169,6 +169,7 @@ export interface DocsCategory { user_id: string | null; category_name: string; category_weight: number; + created_at: Date; last_modified_at: Date; last_modified_by: string | null; } @@ -178,6 +179,7 @@ export interface DocsCategoryInput { user_id?: string | null; category_name: string; category_weight: number; + created_at?: Date; last_modified_at?: Date; last_modified_by?: string | null; } @@ -189,6 +191,7 @@ const docs_category = { "user_id", "category_name", "category_weight", + "created_at", "last_modified_at", "last_modified_by" ], @@ -203,6 +206,34 @@ const docs_category = { $input: null as unknown as DocsCategoryInput } as const; +// Table domain_prefix +export interface DomainPrefix { + website_id: string; + prefix: string; + created_at: Date; + last_modified_at: Date; + last_modified_by: string | null; +} +export interface DomainPrefixInput { + website_id: string; + prefix: string; + created_at?: Date; + last_modified_at?: Date; + last_modified_by?: string | null; +} +const domain_prefix = { + tableName: "domain_prefix", + columns: ["website_id", "prefix", "created_at", "last_modified_at", "last_modified_by"], + requiredForInsert: ["website_id", "prefix"], + primaryKey: "website_id", + foreignKeys: { + website_id: { table: "website", column: "id", $type: null as unknown as Website }, + last_modified_by: { table: "user", column: "id", $type: null as unknown as User } + }, + $type: null as unknown as DomainPrefix, + $input: null as unknown as DomainPrefixInput +} as const; + // Table footer export interface Footer { website_id: string; @@ -297,18 +328,20 @@ const home = { export interface LegalInformation { website_id: string; main_content: string; + created_at: Date; last_modified_at: Date; last_modified_by: string | null; } export interface LegalInformationInput { website_id: string; main_content: string; + created_at?: Date; last_modified_at?: Date; last_modified_by?: string | null; } const legal_information = { tableName: "legal_information", - columns: ["website_id", "main_content", "last_modified_at", "last_modified_by"], + columns: ["website_id", "main_content", "created_at", "last_modified_at", "last_modified_by"], requiredForInsert: ["website_id", "main_content"], primaryKey: "website_id", foreignKeys: { @@ -354,16 +387,20 @@ const media = { // Table settings export interface Settings { website_id: string; - accent_color_light_theme: string; accent_color_dark_theme: string; + accent_color_light_theme: string; + background_color_dark_theme: string; + background_color_light_theme: string; favicon_image: string | null; last_modified_at: Date; last_modified_by: string | null; } export interface SettingsInput { website_id: string; - accent_color_light_theme?: string; accent_color_dark_theme?: string; + accent_color_light_theme?: string; + background_color_dark_theme?: string; + background_color_light_theme?: string; favicon_image?: string | null; last_modified_at?: Date; last_modified_by?: string | null; @@ -372,8 +409,10 @@ const settings = { tableName: "settings", columns: [ "website_id", - "accent_color_light_theme", "accent_color_dark_theme", + "accent_color_light_theme", + "background_color_dark_theme", + "background_color_light_theme", "favicon_image", "last_modified_at", "last_modified_by" @@ -395,16 +434,18 @@ export interface User { username: string; password_hash: string; role: string; + created_at: Date; } export interface UserInput { id?: string; username: string; password_hash: string; role?: string; + created_at?: Date; } const user = { tableName: "user", - columns: ["id", "username", "password_hash", "role"], + columns: ["id", "username", "password_hash", "role", "created_at"], requiredForInsert: ["username", "password_hash"], primaryKey: "id", foreignKeys: {}, @@ -418,8 +459,8 @@ export interface Website { user_id: string; content_type: string; title: string; - created_at: Date; is_published: boolean; + created_at: Date; last_modified_at: Date; last_modified_by: string | null; title_search: any | null; @@ -429,8 +470,8 @@ export interface WebsiteInput { user_id?: string; content_type: string; title: string; - created_at?: Date; is_published?: boolean; + created_at?: Date; last_modified_at?: Date; last_modified_by?: string | null; title_search?: any | null; @@ -442,8 +483,8 @@ const website = { "user_id", "content_type", "title", - "created_at", "is_published", + "created_at", "last_modified_at", "last_modified_by", "title_search" @@ -475,6 +516,10 @@ export interface TableTypes { select: DocsCategory; input: DocsCategoryInput; }; + domain_prefix: { + select: DomainPrefix; + input: DomainPrefixInput; + }; footer: { select: Footer; input: FooterInput; @@ -514,6 +559,7 @@ export const tables = { change_log, collab, docs_category, + domain_prefix, footer, header, home, diff --git a/web-app/src/lib/runes.svelte.ts b/web-app/src/lib/runes.svelte.ts new file mode 100644 index 0000000..fab051e --- /dev/null +++ b/web-app/src/lib/runes.svelte.ts @@ -0,0 +1,30 @@ +let sendingState = $state(false); +let previewContentState = $state(""); +let textareaScrollTopState = $state(0); + +export const sending = { + get value() { + return sendingState; + }, + set value(val) { + sendingState = val; + } +}; + +export const previewContent = { + get value() { + return previewContentState; + }, + set value(val) { + previewContentState = val; + } +}; + +export const textareaScrollTop = { + get value() { + return textareaScrollTopState; + }, + set value(val) { + textareaScrollTopState = val; + } +}; diff --git a/web-app/src/lib/server/utils.ts b/web-app/src/lib/server/utils.ts index e745aeb..134430c 100644 --- a/web-app/src/lib/server/utils.ts +++ b/web-app/src/lib/server/utils.ts @@ -3,3 +3,54 @@ import { dev } from "$app/environment"; export const API_BASE_PREFIX = dev ? "http://localhost:3000" : `${process.env.ORIGIN ? `${process.env.ORIGIN}/api` : "http://localhost:3000"}`; + +export const REGISTRATION_IS_DISABLED = dev + ? false + : process.env.REGISTRATION_IS_DISABLED + ? JSON.parse(process.env.REGISTRATION_IS_DISABLED) + : false; + +export const apiRequest = async ( + customFetch: typeof fetch, + url: string, + method: "HEAD" | "GET" | "POST" | "PATCH" | "DELETE", + options: { + headers?: Record; + body?: any; + successMessage?: string; + returnData?: boolean; + } = { + headers: {}, + body: undefined, + successMessage: "Operation was successful", + returnData: false + } +) => { + const headers = { + "Content-Type": "application/json", + ...options.headers + }; + + const response = await customFetch(url, { + method, + headers, + ...(!["HEAD", "GET", "DELETE"].includes(method) && { + body: options.body instanceof ArrayBuffer ? options.body : JSON.stringify(options.body) + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + return { success: false, message: errorData.message }; + } + + if (options.returnData) { + return { + success: true, + message: options.successMessage, + data: method === "HEAD" ? response : await response.json() + }; + } + + return { success: true, message: options.successMessage }; +}; diff --git a/web-app/src/lib/templates/common/Footer.svelte b/web-app/src/lib/templates/common/Footer.svelte index da65909..d18594d 100644 --- a/web-app/src/lib/templates/common/Footer.svelte +++ b/web-app/src/lib/templates/common/Footer.svelte @@ -1,5 +1,5 @@ - - - - {title} - - - {#if websiteOverview.settings.favicon_image} - - {/if} - + + + {title} + + + {#if websiteOverview.settings.favicon_image} + + {/if} diff --git a/web-app/src/lib/utils.ts b/web-app/src/lib/utils.ts index 9307bb9..9a03ad3 100644 --- a/web-app/src/lib/utils.ts +++ b/web-app/src/lib/utils.ts @@ -12,10 +12,20 @@ import type { Footer, Article, DocsCategory, - LegalInformation + LegalInformation, + DomainPrefix } from "$lib/db-schema"; +import type { SubmitFunction } from "@sveltejs/kit"; +import { sending } from "./runes.svelte"; -export const ALLOWED_MIME_TYPES = ["image/jpeg", "image/png", "image/webp"]; +export const ALLOWED_MIME_TYPES = [ + "image/jpeg", + "image/png", + "image/webp", + "image/avif", + "image/gif", + "image/svg+xml" +]; export const slugify = (string: string) => { return string @@ -24,8 +34,8 @@ export const slugify = (string: string) => { .toLowerCase() // Convert to lowercase .trim() // Trim leading and trailing whitespace .replace(/\s+/g, "-") // Replace spaces with hyphens - .replace(/[^\w\-]+/g, "") // Remove non-word characters (except hyphens) - .replace(/\-\-+/g, "-") // Replace multiple hyphens with single hyphen + .replace(/[^\w-]+/g, "") // Remove non-word characters (except hyphens) + .replace(/-+/g, "-") // Replace multiple hyphens with single hyphen .replace(/^-+/, "") // Remove leading hyphens .replace(/-+$/, ""); // Remove trailing hyphens }; @@ -51,8 +61,8 @@ const createMarkdownParser = (showToc = true) => { ); const gfmHeadingId = ({ prefix = "", showToc = true } = {}) => { - let headings: { text: string; level: number; id: string }[] = []; - let sectionStack: { level: number; id: string }[] = []; + const headings: { text: string; level: number; id: string }[] = []; + const sectionStack: { level: number; id: string }[] = []; return { renderer: { @@ -143,45 +153,59 @@ export const md = (markdownContent: string, showToc = true) => { return html; }; -export const handleImagePaste = async (event: ClipboardEvent, API_BASE_PREFIX: string) => { - const clipboardItems = Array.from(event.clipboardData?.items ?? []); - const file = clipboardItems.find((item) => item.type.startsWith("image/")); +export const LOADING_DELAY = 500; +let loadingDelay: number; - if (!file) return null; +export const enhanceForm = (options?: { + reset?: boolean; + closeModal?: boolean; +}): SubmitFunction => { + return () => { + loadingDelay = window.setTimeout(() => (sending.value = true), LOADING_DELAY); - event.preventDefault(); + return async ({ update }) => { + await update({ reset: options?.reset ?? true }); + window.clearTimeout(loadingDelay); + if (options?.closeModal) { + window.location.hash = "!"; + } + sending.value = false; + }; + }; +}; - const fileObject = file.getAsFile(); +export const hexToHSL = (hex: string) => { + const r = parseInt(hex.slice(1, 3), 16) / 255; + const g = parseInt(hex.slice(3, 5), 16) / 255; + const b = parseInt(hex.slice(5, 7), 16) / 255; - if (!fileObject) return; + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + const d = max - min; - const formData = new FormData(); - formData.append("file", fileObject); + let h = 0; + const l = (max + min) / 2; + const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1)); - const request = await fetch("?/pasteImage", { - method: "POST", - body: formData - }); - - const result = deserialize(await request.clone().text()); - applyAction(result); - - const response = await request.json(); - - if (JSON.parse(response.data)[1]) { - const fileId = JSON.parse(response.data)[3]; - const fileUrl = `${API_BASE_PREFIX}/rpc/retrieve_file?id=${fileId}`; - - const target = event.target as HTMLTextAreaElement; - const newContent = - target.value.slice(0, target.selectionStart) + - `![](${fileUrl})` + - target.value.slice(target.selectionStart); - - return newContent; - } else { - return ""; + if (d !== 0) { + switch (max) { + case r: + h = ((g - b) / d + (g < b ? 6 : 0)) / 6; + break; + case g: + h = ((b - r) / d + 2) / 6; + break; + case b: + h = ((r - g) / d + 4) / 6; + break; + } } + + return { + h: Math.round(h * 360), + s: Math.round(s * 100), + l: Math.round(l * 100) + }; }; export interface WebsiteOverview extends Website { @@ -191,4 +215,5 @@ export interface WebsiteOverview extends Website { footer: Footer; article: (Article & { docs_category: DocsCategory | null })[]; legal_information?: LegalInformation; + domain_prefix?: DomainPrefix; } diff --git a/web-app/src/routes/(anonymous)/login/+page.server.ts b/web-app/src/routes/(anonymous)/login/+page.server.ts index ce747c8..747b6a7 100644 --- a/web-app/src/routes/(anonymous)/login/+page.server.ts +++ b/web-app/src/routes/(anonymous)/login/+page.server.ts @@ -1,26 +1,24 @@ import type { Actions } from "./$types"; -import { API_BASE_PREFIX } from "$lib/server/utils"; +import { API_BASE_PREFIX, apiRequest } from "$lib/server/utils"; export const actions: Actions = { default: async ({ request, cookies, fetch }) => { const data = await request.formData(); - const res = await fetch(`${API_BASE_PREFIX}/rpc/login`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ + const response = await apiRequest(fetch, `${API_BASE_PREFIX}/rpc/login`, "POST", { + body: { username: data.get("username"), pass: data.get("password") - }) + }, + returnData: true, + successMessage: "Successfully logged in, you can refresh the page" }); - const response = await res.json(); - - if (!res.ok) { - return { success: false, message: response.message }; + if (!response.success) { + return response; } - cookies.set("session_token", response.token, { path: "/" }); - return { success: true, message: "Successfully logged in" }; + cookies.set("session_token", response.data.token, { path: "/" }); + return response; } }; diff --git a/web-app/src/routes/(anonymous)/login/+page.svelte b/web-app/src/routes/(anonymous)/login/+page.svelte index 30bcd57..bb9d470 100644 --- a/web-app/src/routes/(anonymous)/login/+page.svelte +++ b/web-app/src/routes/(anonymous)/login/+page.svelte @@ -3,28 +3,19 @@ import SuccessOrError from "$lib/components/SuccessOrError.svelte"; import type { ActionData } from "./$types"; import LoadingSpinner from "$lib/components/LoadingSpinner.svelte"; + import { sending } from "$lib/runes.svelte"; + import { enhanceForm } from "$lib/utils"; const { form }: { form: ActionData } = $props(); - - let sending = $state(false); -{#if sending} +{#if sending.value} {/if} -
{ - sending = true; - return async ({ update }) => { - await update(); - sending = false; - }; - }} -> +