From b5c94d41d1d21b8db7c81c65c1980c3d2c38f15e Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Tue, 17 Sep 2024 21:09:27 +0200 Subject: [PATCH 01/24] Trigger actions From a7a4942633acff1ddb97397baf1ce4b621a1e35e Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Tue, 17 Sep 2024 21:27:41 +0200 Subject: [PATCH 02/24] Move pagination to outer container --- .../website/[websiteId]/logs/+page.svelte | 123 +++++++++--------- 1 file changed, 60 insertions(+), 63 deletions(-) diff --git a/web-app/src/routes/(authenticated)/website/[websiteId]/logs/+page.svelte b/web-app/src/routes/(authenticated)/website/[websiteId]/logs/+page.svelte index 4967937..c04e819 100644 --- a/web-app/src/routes/(authenticated)/website/[websiteId]/logs/+page.svelte +++ b/web-app/src/routes/(authenticated)/website/[websiteId]/logs/+page.svelte @@ -158,6 +158,8 @@ {/each} + + @@ -245,8 +244,6 @@ .pagination { display: flex; align-items: center; - margin-inline: var(--space-2xs); - margin-block: var(--space-s); flex-wrap: wrap; gap: var(--space-xs); justify-content: end; From c97a6624d669fe700c896e6fd0fe23054c8fd649 Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Tue, 17 Sep 2024 22:44:16 +0200 Subject: [PATCH 03/24] Allow more common mimetypes --- .../20240810115846_image_upload_function.sql | 2 +- web-app/src/lib/utils.ts | 17 ++++++++++++----- .../articles/[articleId]/+page.svelte | 1 + .../website/[websiteId]/logs/+page.svelte | 6 ++++-- 4 files changed, 18 insertions(+), 8 deletions(-) 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/web-app/src/lib/utils.ts b/web-app/src/lib/utils.ts index 9307bb9..1af3833 100644 --- a/web-app/src/lib/utils.ts +++ b/web-app/src/lib/utils.ts @@ -15,7 +15,14 @@ import type { LegalInformation } from "$lib/db-schema"; -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 +31,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 +58,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: { diff --git a/web-app/src/routes/(authenticated)/website/[websiteId]/articles/[articleId]/+page.svelte b/web-app/src/routes/(authenticated)/website/[websiteId]/articles/[articleId]/+page.svelte index 83d6147..4acbb9c 100644 --- a/web-app/src/routes/(authenticated)/website/[websiteId]/articles/[articleId]/+page.svelte +++ b/web-app/src/routes/(authenticated)/website/[websiteId]/articles/[articleId]/+page.svelte @@ -21,6 +21,7 @@ const handlePaste = async (event: ClipboardEvent) => { const newContent = await handleImagePaste(event, data.API_BASE_PREFIX); + if (newContent) { previewContent = newContent; } diff --git a/web-app/src/routes/(authenticated)/website/[websiteId]/logs/+page.svelte b/web-app/src/routes/(authenticated)/website/[websiteId]/logs/+page.svelte index c04e819..06e02a7 100644 --- a/web-app/src/routes/(authenticated)/website/[websiteId]/logs/+page.svelte +++ b/web-app/src/routes/(authenticated)/website/[websiteId]/logs/+page.svelte @@ -34,11 +34,13 @@ let resources = $state({}); if (data.website.content_type === "Blog") { + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { user, change_log, media, docs_category, ...restTables } = tables; resources = restTables; } if (data.website.content_type === "Docs") { + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { user, change_log, media, ...restTables } = tables; resources = restTables; } @@ -253,8 +255,8 @@ margin-inline-start: auto; } - button[disabled] { - opacity: 0.5; + button:disabled { pointer-events: none; + color: hsl(0 0% 50%); } From 36de68c6a0e5405cd0d910b508beaa2fd91bd6b7 Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:22:52 +0200 Subject: [PATCH 04/24] Add creation time to remainin tables --- rest-api/db/migrations/20240719071602_main_tables.sql | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rest-api/db/migrations/20240719071602_main_tables.sql b/rest-api/db/migrations/20240719071602_main_tables.sql index 0a1ca79..8d7de5c 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 @@ -82,6 +83,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 +119,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 ); From 32b0cc30cd342e24d0557de0ca4ef04895a20c9f Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:46:36 +0200 Subject: [PATCH 05/24] Update npm packages to latest version --- web-app/package-lock.json | 695 ++++++------------- web-app/package.json | 28 +- web-app/src/lib/templates/common/Head.svelte | 24 +- 3 files changed, 228 insertions(+), 519 deletions(-) diff --git a/web-app/package-lock.json b/web-app/package-lock.json index 97b6ede..e0f5aa1 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.47.1", + "@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.47.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.1.tgz", + "integrity": "sha512-dbWpcNQZ5nj16m+A5UNScYx7HX5trIy7g4phrcitn+Nk83S32EBX/CLU4hiF4RGKX/yRc93AAqtfaXB7JWBd4Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.40.0" + "playwright": "1.47.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/@polka/url": { @@ -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.47.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.1.tgz", + "integrity": "sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.40.0" + "playwright-core": "1.47.1" }, "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.47.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.1.tgz", + "integrity": "sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ==", "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,66 +4007,6 @@ "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", @@ -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..dc662f5 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.47.1", + "@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/lib/templates/common/Head.svelte b/web-app/src/lib/templates/common/Head.svelte index d663ff9..b7416c3 100644 --- a/web-app/src/lib/templates/common/Head.svelte +++ b/web-app/src/lib/templates/common/Head.svelte @@ -17,17 +17,15 @@ - - - - {title} - - - {#if websiteOverview.settings.favicon_image} - - {/if} - + + + {title} + + + {#if websiteOverview.settings.favicon_image} + + {/if} From 0ff0401aea47a4379148b1482f1077c2a280604a Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:54:22 +0200 Subject: [PATCH 06/24] Set npm playwright version to new nix driver version --- flake.lock | 6 +++--- web-app/package-lock.json | 24 ++++++++++++------------ web-app/package.json | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/flake.lock b/flake.lock index 83909bb..e190a4b 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1721497942, - "narHash": "sha256-EDPL9qJfklXoowl3nEBmjDIqcvXKUZInt5n6CCc1Hn4=", + "lastModified": 1726583932, + "narHash": "sha256-zACxiQx8knB3F8+Ze+1BpiYrI+CbhxyWpcSID9kVhkQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d43f0636fc9492e83be8bbb41f9595d7a87106b8", + "rev": "658e7223191d2598641d50ee4e898126768fe847", "type": "github" }, "original": { diff --git a/web-app/package-lock.json b/web-app/package-lock.json index e0f5aa1..66dfbfe 100644 --- a/web-app/package-lock.json +++ b/web-app/package-lock.json @@ -15,7 +15,7 @@ "marked-highlight": "2.1.4" }, "devDependencies": { - "@playwright/test": "1.47.1", + "@playwright/test": "1.46.0", "@sveltejs/adapter-auto": "3.2.5", "@sveltejs/adapter-node": "5.2.3", "@sveltejs/kit": "2.5.28", @@ -764,13 +764,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.47.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.1.tgz", - "integrity": "sha512-dbWpcNQZ5nj16m+A5UNScYx7HX5trIy7g4phrcitn+Nk83S32EBX/CLU4hiF4RGKX/yRc93AAqtfaXB7JWBd4Q==", + "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.47.1" + "playwright": "1.46.0" }, "bin": { "playwright": "cli.js" @@ -3647,13 +3647,13 @@ } }, "node_modules/playwright": { - "version": "1.47.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.1.tgz", - "integrity": "sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw==", + "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.47.1" + "playwright-core": "1.46.0" }, "bin": { "playwright": "cli.js" @@ -3666,9 +3666,9 @@ } }, "node_modules/playwright-core": { - "version": "1.47.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.1.tgz", - "integrity": "sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ==", + "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": { diff --git a/web-app/package.json b/web-app/package.json index dc662f5..79e6551 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -14,7 +14,7 @@ "gents": "pg-to-ts generate -c postgres://postgres@localhost:15432/archtika -o src/lib/db-schema.ts -s internal" }, "devDependencies": { - "@playwright/test": "1.47.1", + "@playwright/test": "1.46.0", "@sveltejs/adapter-auto": "3.2.5", "@sveltejs/adapter-node": "5.2.3", "@sveltejs/kit": "2.5.28", From 2a420b25ee3c762a5b29858be06b5dc2510f6654 Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:04:36 +0200 Subject: [PATCH 07/24] Set Nix channel to nixos-unstable --- flake.lock | 8 ++++---- flake.nix | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index e190a4b..203568a 100644 --- a/flake.lock +++ b/flake.lock @@ -2,16 +2,16 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1726583932, - "narHash": "sha256-zACxiQx8knB3F8+Ze+1BpiYrI+CbhxyWpcSID9kVhkQ=", + "lastModified": 1726463316, + "narHash": "sha256-gI9kkaH0ZjakJOKrdjaI/VbaMEo9qBbSUl93DnU7f4c=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "658e7223191d2598641d50ee4e898126768fe847", + "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 = From f13dea3a3ca8f49f538424720946f93a53263d8e Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Thu, 19 Sep 2024 18:08:13 +0200 Subject: [PATCH 08/24] Set CORS allowed origins for PostgREST --- nix/module.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/module.nix b/nix/module.nix index d939861..a66cac6 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -108,7 +108,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="${cfg.domain}, *.${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 ''; }; From b27f4e1c6a6285e9a688f1d59968bfa45d64ad48 Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Thu, 19 Sep 2024 18:19:58 +0200 Subject: [PATCH 09/24] Prefix allowed cors origins with https --- nix/module.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/module.nix b/nix/module.nix index a66cac6..e95ed55 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -108,7 +108,7 @@ in ${pkgs.dbmate}/bin/dbmate --url postgres://postgres@localhost:5432/archtika?sslmode=disable --migrations-dir ${cfg.package}/rest-api/db/migrations up - PGRST_SERVER_CORS_ALLOWED_ORIGINS="${cfg.domain}, *.${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 + PGRST_SERVER_CORS_ALLOWED_ORIGINS="https://${cfg.domain}, 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 ''; }; From e297ebeaa61f0597d4c0c31566f6ee74f78d7c32 Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Thu, 19 Sep 2024 18:26:36 +0200 Subject: [PATCH 10/24] Update cors --- nix/module.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/module.nix b/nix/module.nix index e95ed55..878fac8 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -108,7 +108,7 @@ in ${pkgs.dbmate}/bin/dbmate --url postgres://postgres@localhost:5432/archtika?sslmode=disable --migrations-dir ${cfg.package}/rest-api/db/migrations up - PGRST_SERVER_CORS_ALLOWED_ORIGINS="https://${cfg.domain}, 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 + 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 ''; }; From 1c5681ddea89afcf8bf949113630943caaafde47 Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Thu, 19 Sep 2024 18:28:07 +0200 Subject: [PATCH 11/24] Trigger actions From 43009884636d97b7f09d31799b93fa97a7cefe54 Mon Sep 17 00:00:00 2001 From: Thilo Hohlt Date: Thu, 19 Sep 2024 22:16:40 +0200 Subject: [PATCH 12/24] Update module.nix --- nix/module.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nix/module.nix b/nix/module.nix index 878fac8..d31d2e5 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -168,6 +168,8 @@ in default_type application/json; proxy_set_header Connection ""; proxy_http_version 1.1; + allow 127.0.0.1; + deny all; ''; }; }; From 86ab7374296e8a2847831acfc3ec7da37328829e Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:56:07 +0200 Subject: [PATCH 13/24] Add custom domain prefixes and option to disable user registration --- nix/deploy/qs/default.nix | 1 + nix/module.nix | 15 ++- .../20240805132306_last_modified_triggers.sql | 2 +- .../20240920090915_custom_domain_prefix.sql | 57 ++++++++++ web-app/src/lib/db-schema.ts | 52 +++++++-- web-app/src/lib/server/utils.ts | 6 ++ web-app/src/lib/utils.ts | 4 +- .../(anonymous)/register/+page.server.ts | 10 +- .../routes/(anonymous)/register/+page.svelte | 72 +++++++++---- .../routes/(authenticated)/+page.server.ts | 23 +++- .../[websiteId]/publish/+page.server.ts | 101 ++++++++++++++++-- .../website/[websiteId]/publish/+page.svelte | 82 +++++++++++--- 12 files changed, 368 insertions(+), 57 deletions(-) create mode 100644 rest-api/db/migrations/20240920090915_custom_domain_prefix.sql 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 d31d2e5..52fc37c 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 { @@ -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=Infinity ORIGIN=https://${cfg.domain} PORT=${toString cfg.webAppPort} ${pkgs.nodejs_22}/bin/node ${cfg.package}/web-app ''; }; @@ -165,10 +171,13 @@ in "/api/" = { proxyPass = "http://localhost:${toString cfg.apiPort}/"; extraConfig = '' - default_type application/json; + default_type application/json; proxy_set_header Connection ""; proxy_http_version 1.1; - allow 127.0.0.1; + ''; + }; + "/api/rpc/register" = mkIf cfg.disableRegistration { + extraConfig = '' deny all; ''; }; diff --git a/rest-api/db/migrations/20240805132306_last_modified_triggers.sql b/rest-api/db/migrations/20240805132306_last_modified_triggers.sql index ea8794b..2714d42 100644 --- a/rest-api/db/migrations/20240805132306_last_modified_triggers.sql +++ b/rest-api/db/migrations/20240805132306_last_modified_triggers.sql @@ -68,7 +68,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/20240920090915_custom_domain_prefix.sql b/rest-api/db/migrations/20240920090915_custom_domain_prefix.sql new file mode 100644 index 0000000..fe4a428 --- /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, UPDATE, 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/src/lib/db-schema.ts b/web-app/src/lib/db-schema.ts index 1e45e9d..1706d8e 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: { @@ -395,16 +428,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 +453,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 +464,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 +477,8 @@ const website = { "user_id", "content_type", "title", - "created_at", "is_published", + "created_at", "last_modified_at", "last_modified_by", "title_search" @@ -475,6 +510,10 @@ export interface TableTypes { select: DocsCategory; input: DocsCategoryInput; }; + domain_prefix: { + select: DomainPrefix; + input: DomainPrefixInput; + }; footer: { select: Footer; input: FooterInput; @@ -514,6 +553,7 @@ export const tables = { change_log, collab, docs_category, + domain_prefix, footer, header, home, diff --git a/web-app/src/lib/server/utils.ts b/web-app/src/lib/server/utils.ts index e745aeb..22d499a 100644 --- a/web-app/src/lib/server/utils.ts +++ b/web-app/src/lib/server/utils.ts @@ -3,3 +3,9 @@ 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; diff --git a/web-app/src/lib/utils.ts b/web-app/src/lib/utils.ts index 1af3833..a16e396 100644 --- a/web-app/src/lib/utils.ts +++ b/web-app/src/lib/utils.ts @@ -12,7 +12,8 @@ import type { Footer, Article, DocsCategory, - LegalInformation + LegalInformation, + DomainPrefix } from "$lib/db-schema"; export const ALLOWED_MIME_TYPES = [ @@ -198,4 +199,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)/register/+page.server.ts b/web-app/src/routes/(anonymous)/register/+page.server.ts index d8dfc0c..4fd0aef 100644 --- a/web-app/src/routes/(anonymous)/register/+page.server.ts +++ b/web-app/src/routes/(anonymous)/register/+page.server.ts @@ -1,5 +1,11 @@ -import type { Actions } from "./$types"; -import { API_BASE_PREFIX } from "$lib/server/utils"; +import type { Actions, PageServerLoad } from "./$types"; +import { API_BASE_PREFIX, REGISTRATION_IS_DISABLED } from "$lib/server/utils"; + +export const load: PageServerLoad = async () => { + return { + REGISTRATION_IS_DISABLED + }; +}; export const actions: Actions = { default: async ({ request, fetch }) => { diff --git a/web-app/src/routes/(anonymous)/register/+page.svelte b/web-app/src/routes/(anonymous)/register/+page.svelte index 3c5a620..2ec07f3 100644 --- a/web-app/src/routes/(anonymous)/register/+page.svelte +++ b/web-app/src/routes/(anonymous)/register/+page.svelte @@ -1,10 +1,10 @@ @@ -15,24 +15,52 @@ {/if} -
{ - sending = true; - return async ({ update }) => { - await update(); - sending = false; - }; - }} -> - - +{#if data.REGISTRATION_IS_DISABLED} +

+ + + + Account registration is disabled on this instance +

+{:else} + { + sending = true; + return async ({ update }) => { + await update(); + sending = false; + }; + }} + > + + - -
+ + +{/if} + + diff --git a/web-app/src/routes/(authenticated)/+page.server.ts b/web-app/src/routes/(authenticated)/+page.server.ts index 2f37835..4482e00 100644 --- a/web-app/src/routes/(authenticated)/+page.server.ts +++ b/web-app/src/routes/(authenticated)/+page.server.ts @@ -103,6 +103,19 @@ export const actions: Actions = { deleteWebsite: async ({ request, cookies, fetch }) => { const data = await request.formData(); + const oldDomainPrefixData = await fetch( + `${API_BASE_PREFIX}/domain_prefix?website_id=eq.${data.get("id")}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${cookies.get("session_token")}`, + Accept: "application/vnd.pgrst.object+json" + } + } + ); + const oldDomainPrefix = await oldDomainPrefixData.json(); + const res = await fetch(`${API_BASE_PREFIX}/website?id=eq.${data.get("id")}`, { method: "DELETE", headers: { @@ -116,11 +129,19 @@ export const actions: Actions = { return { success: false, message: response.message }; } - await rm(join("/", "var", "www", "archtika-websites", data.get("id") as string), { + await rm(join("/", "var", "www", "archtika-websites", "previews", data.get("id") as string), { recursive: true, force: true }); + await rm( + join("/", "var", "www", "archtika-websites", oldDomainPrefix.prefix ?? data.get("id")), + { + recursive: true, + force: true + } + ); + return { success: true, message: "Successfully deleted website" }; } }; diff --git a/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.server.ts b/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.server.ts index 674e6e7..08101b9 100644 --- a/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.server.ts +++ b/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.server.ts @@ -1,4 +1,4 @@ -import { readFile, mkdir, writeFile } from "node:fs/promises"; +import { readFile, mkdir, writeFile, rename } from "node:fs/promises"; import { join } from "node:path"; import { type WebsiteOverview, slugify } from "$lib/utils"; import type { Actions, PageServerLoad } from "./$types"; @@ -9,10 +9,11 @@ import BlogArticle from "$lib/templates/blog/BlogArticle.svelte"; import DocsIndex from "$lib/templates/docs/DocsIndex.svelte"; import DocsArticle from "$lib/templates/docs/DocsArticle.svelte"; import { dev } from "$app/environment"; +import type { DomainPrefixInput } from "$lib/db-schema"; export const load: PageServerLoad = async ({ params, fetch, cookies }) => { const websiteOverviewData = await fetch( - `${API_BASE_PREFIX}/website?id=eq.${params.websiteId}&select=*,settings(*),header(*),home(*),footer(*),article(*,docs_category(*)),legal_information(*)`, + `${API_BASE_PREFIX}/website?id=eq.${params.websiteId}&select=*,settings(*),header(*),home(*),footer(*),article(*,docs_category(*)),legal_information(*),domain_prefix(*)`, { method: "GET", headers: { @@ -36,10 +37,13 @@ export const load: PageServerLoad = async ({ params, fetch, cookies }) => { }/previews/${websiteOverview.id}/`; const websiteProdUrl = dev - ? `http://localhost:18000/${websiteOverview.id}/` + ? `http://localhost:18000/${websiteOverview.domain_prefix?.prefix ?? websiteOverview.id}/` : process.env.ORIGIN - ? process.env.ORIGIN.replace("//", `//${websiteOverview.id}.`) - : `http://localhost:18000/${websiteOverview.id}/`; + ? process.env.ORIGIN.replace( + "//", + `//${websiteOverview.domain_prefix?.prefix ?? websiteOverview.id}.` + ) + : `http://localhost:18000/${websiteOverview.domain_prefix?.prefix ?? websiteOverview.id}/`; return { websiteOverview, @@ -51,7 +55,7 @@ export const load: PageServerLoad = async ({ params, fetch, cookies }) => { export const actions: Actions = { publishWebsite: async ({ fetch, params, cookies }) => { const websiteOverviewData = await fetch( - `${API_BASE_PREFIX}/website?id=eq.${params.websiteId}&select=*,settings(*),header(*),home(*),footer(*),article(*,docs_category(*)),legal_information(*)`, + `${API_BASE_PREFIX}/website?id=eq.${params.websiteId}&select=*,settings(*),header(*),home(*),footer(*),article(*,docs_category(*)),legal_information(*),domain_prefix(*)`, { method: "GET", headers: { @@ -82,10 +86,85 @@ export const actions: Actions = { } return { success: true, message: "Successfully published website" }; + }, + createUpdateCustomDomainPrefix: async ({ request, fetch, params, cookies }) => { + const data = await request.formData(); + + const oldDomainPrefixData = await fetch( + `${API_BASE_PREFIX}/domain_prefix?website_id=eq.${params.websiteId}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${cookies.get("session_token")}`, + Accept: "application/vnd.pgrst.object+json" + } + } + ); + const oldDomainPrefix = await oldDomainPrefixData.json(); + + const res = await fetch(`${API_BASE_PREFIX}/domain_prefix`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${cookies.get("session_token")}`, + Prefer: "resolution=merge-duplicates", + Accept: "application/vnd.pgrst.object+json" + }, + body: JSON.stringify({ + website_id: params.websiteId, + prefix: data.get("domain-prefix") as string + } satisfies DomainPrefixInput) + }); + + if (!res.ok) { + const response = await res.json(); + return { success: false, message: response.message }; + } + + await rename( + join( + "/", + "var", + "www", + "archtika-websites", + res.status === 201 ? params.websiteId : oldDomainPrefix.prefix + ), + join("/", "var", "www", "archtika-websites", data.get("domain-prefix") as string) + ); + + return { + success: true, + message: `Successfully ${res.status === 201 ? "created" : "updated"} domain prefix` + }; + }, + deleteCustomDomainPrefix: async ({ fetch, params, cookies }) => { + const res = await fetch(`${API_BASE_PREFIX}/domain_prefix?website_id=eq.${params.websiteId}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${cookies.get("session_token")}`, + Prefer: "return=representation", + Accept: "application/vnd.pgrst.object+json" + } + }); + + const response = await res.json(); + + if (!res.ok) { + return { success: false, message: response.message }; + } + + await rename( + join("/", "var", "www", "archtika-websites", response.prefix), + join("/", "var", "www", "archtika-websites", params.websiteId) + ); + + return { success: true, message: `Successfully deleted domain prefix` }; } }; -const generateStaticFiles = async (websiteData: WebsiteOverview, isPreview: boolean = true) => { +const generateStaticFiles = async (websiteData: WebsiteOverview, isPreview = true) => { const fileContents = (head: string, body: string) => { return ` @@ -112,7 +191,13 @@ const generateStaticFiles = async (websiteData: WebsiteOverview, isPreview: bool if (isPreview) { uploadDir = join("/", "var", "www", "archtika-websites", "previews", websiteData.id); } else { - uploadDir = join("/", "var", "www", "archtika-websites", websiteData.id); + uploadDir = join( + "/", + "var", + "www", + "archtika-websites", + websiteData.domain_prefix?.prefix ?? websiteData.id + ); } await mkdir(uploadDir, { recursive: true }); diff --git a/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.svelte b/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.svelte index bd97a70..8df031b 100644 --- a/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.svelte +++ b/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.svelte @@ -4,6 +4,7 @@ import SuccessOrError from "$lib/components/SuccessOrError.svelte"; import type { ActionData, PageServerData } from "./$types"; import LoadingSpinner from "$lib/components/LoadingSpinner.svelte"; + import Modal from "$lib/components/Modal.svelte"; const { data, form }: { data: PageServerData; form: ActionData } = $props(); @@ -45,18 +46,73 @@ > - - {#if data.websiteOverview.is_published} -
-

- Publication status -

-

- Your website is published at: -
- {data.websiteProdUrl} -

-
- {/if} + + {#if data.websiteOverview.is_published} +
+

+ Publication status +

+

+ Your website is published at: +
+ {data.websiteProdUrl} +

+
+ +
+

+ Custom domain prefix +

+
{ + sending = true; + return async ({ update }) => { + await update(); + sending = false; + }; + }} + > + + +
+ {#if data.websiteOverview.domain_prefix?.prefix} + +
{ + sending = true; + return async ({ update }) => { + await update(); + window.location.hash = "!"; + sending = false; + }; + }} + > +

Delete domain prefix

+

+ Caution! + This action will remove the domain prefix and reset it to its initial value. +

+ +
+
+ {/if} +
+ {/if} From c11d73c3282608f4e2d6829c48e932061c2bb8c3 Mon Sep 17 00:00:00 2001 From: thiloho <123883702+thiloho@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:47:25 +0200 Subject: [PATCH 14/24] Enable rate limiting and compression for NGINX --- nix/module.nix | 12 +++++++++--- .../website/[websiteId]/categories/+page.server.ts | 1 + .../website/[websiteId]/categories/+page.svelte | 5 +++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/nix/module.nix b/nix/module.nix index 52fc37c..3be0a0a 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -131,7 +131,7 @@ in }; script = '' - REGISTRATION_IS_DISABLED=${toString cfg.disableRegistration} 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 ''; }; @@ -154,6 +154,14 @@ 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; + ''; virtualHosts = { "${cfg.domain}" = { @@ -172,8 +180,6 @@ in proxyPass = "http://localhost:${toString cfg.apiPort}/"; extraConfig = '' default_type application/json; - proxy_set_header Connection ""; - proxy_http_version 1.1; ''; }; "/api/rpc/register" = mkIf cfg.disableRegistration { diff --git a/web-app/src/routes/(authenticated)/website/[websiteId]/categories/+page.server.ts b/web-app/src/routes/(authenticated)/website/[websiteId]/categories/+page.server.ts index f16941f..807dd05 100644 --- a/web-app/src/routes/(authenticated)/website/[websiteId]/categories/+page.server.ts +++ b/web-app/src/routes/(authenticated)/website/[websiteId]/categories/+page.server.ts @@ -60,6 +60,7 @@ export const actions: Actions = { Authorization: `Bearer ${cookies.get("session_token")}` }, body: JSON.stringify({ + category_name: data.get("category-name"), category_weight: data.get("category-weight") }) } diff --git a/web-app/src/routes/(authenticated)/website/[websiteId]/categories/+page.svelte b/web-app/src/routes/(authenticated)/website/[websiteId]/categories/+page.svelte index 71100d9..df9df36 100644 --- a/web-app/src/routes/(authenticated)/website/[websiteId]/categories/+page.svelte +++ b/web-app/src/routes/(authenticated)/website/[websiteId]/categories/+page.svelte @@ -89,6 +89,11 @@ > + +