From 0a7aaed60db7b5cb7c1ce5e1b4219e3af2836d0b Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Mon, 19 Feb 2024 17:27:16 +0100 Subject: [PATCH 1/8] fix: add punycode library to fix deprecation warning --- package.json | 1 + pnpm-lock.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/package.json b/package.json index fe59a0b..a88f31b 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@prisma/client": "^5.9.1", "isomorphic-dompurify": "^2.3.0", "marked": "^12.0.0", + "punycode": "^2.3.1", "svelte-floating-ui": "^1.5.8", "zod": "^3.22.4", "zod-form-data": "^2.0.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 299c13b..11a463f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ dependencies: marked: specifier: ^12.0.0 version: 12.0.0 + punycode: + specifier: ^2.3.1 + version: 2.3.1 svelte-floating-ui: specifier: ^1.5.8 version: 1.5.8 From 39973c0a83b3d3e961b459faf8ce2d9d944be9a2 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Wed, 21 Feb 2024 13:55:39 +0100 Subject: [PATCH 2/8] feat: add entry history display --- package.json | 12 +- pnpm-lock.yaml | 403 ++++++++++++++---- src/app.pcss | 4 + src/lib/server/trpc/routes/entry.ts | 7 + src/lib/shared/util/diff.test.ts | 110 +++++ src/lib/shared/util/diff.ts | 46 ++ src/lib/shared/util/index.ts | 4 + .../(app)/entry/[id]/versions/+page.svelte | 82 ++++ src/routes/(app)/entry/[id]/versions/+page.ts | 11 + 9 files changed, 602 insertions(+), 77 deletions(-) create mode 100644 src/lib/shared/util/diff.test.ts create mode 100644 src/lib/shared/util/diff.ts create mode 100644 src/routes/(app)/entry/[id]/versions/+page.svelte create mode 100644 src/routes/(app)/entry/[id]/versions/+page.ts diff --git a/package.json b/package.json index a88f31b..5ba4788 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,9 @@ "@floating-ui/core": "^1.6.0", "@mdi/js": "^7.4.47", "@prisma/client": "^5.9.1", + "diff": "^5.2.0", "isomorphic-dompurify": "^2.3.0", "marked": "^12.0.0", - "punycode": "^2.3.1", "svelte-floating-ui": "^1.5.8", "zod": "^3.22.4", "zod-form-data": "^2.0.2" @@ -38,23 +38,25 @@ "@tailwindcss/typography": "^0.5.10", "@trpc/client": "^10.45.1", "@trpc/server": "^10.45.1", + "@types/diff": "^5.0.9", "@types/node": "^20.11.19", - "@typescript-eslint/eslint-plugin": "^7.0.1", - "@typescript-eslint/parser": "^7.0.1", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", "autoprefixer": "^10.4.17", "daisyui": "^4.7.2", + "dotenv": "^16.4.5", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-no-relative-import-paths": "^1.5.3", "eslint-plugin-svelte": "^2.35.1", "postcss-import": "^16.0.1", - "postcss-nesting": "^12.0.2", + "postcss-nesting": "^12.0.3", "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.1", "prisma": "^5.9.1", "svelte": "^4.2.11", "svelte-check": "^3.6.4", - "sveltekit-superforms": "^2.3.0", + "sveltekit-superforms": "^2.4.0", "tailwindcss": "^3.4.1", "trpc-sveltekit": "^3.5.26", "tslib": "^2.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 11a463f..d4f04a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,15 +20,15 @@ dependencies: '@prisma/client': specifier: ^5.9.1 version: 5.9.1(prisma@5.9.1) + diff: + specifier: ^5.2.0 + version: 5.2.0 isomorphic-dompurify: specifier: ^2.3.0 version: 2.3.0 marked: specifier: ^12.0.0 version: 12.0.0 - punycode: - specifier: ^2.3.1 - version: 2.3.1 svelte-floating-ui: specifier: ^1.5.8 version: 1.5.8 @@ -64,21 +64,27 @@ devDependencies: '@trpc/server': specifier: ^10.45.1 version: 10.45.1 + '@types/diff': + specifier: ^5.0.9 + version: 5.0.9 '@types/node': specifier: ^20.11.19 version: 20.11.19 '@typescript-eslint/eslint-plugin': - specifier: ^7.0.1 - version: 7.0.1(@typescript-eslint/parser@7.0.1)(eslint@8.56.0)(typescript@5.3.3) + specifier: ^7.0.2 + version: 7.0.2(@typescript-eslint/parser@7.0.2)(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^7.0.1 - version: 7.0.1(eslint@8.56.0)(typescript@5.3.3) + specifier: ^7.0.2 + version: 7.0.2(eslint@8.56.0)(typescript@5.3.3) autoprefixer: specifier: ^10.4.17 version: 10.4.17(postcss@8.4.35) daisyui: specifier: ^4.7.2 version: 4.7.2(postcss@8.4.35) + dotenv: + specifier: ^16.4.5 + version: 16.4.5 eslint: specifier: ^8.56.0 version: 8.56.0 @@ -95,8 +101,8 @@ devDependencies: specifier: ^16.0.1 version: 16.0.1(postcss@8.4.35) postcss-nesting: - specifier: ^12.0.2 - version: 12.0.2(postcss@8.4.35) + specifier: ^12.0.3 + version: 12.0.3(postcss@8.4.35) prettier: specifier: ^3.2.5 version: 3.2.5 @@ -113,8 +119,8 @@ devDependencies: specifier: ^3.6.4 version: 3.6.4(postcss@8.4.35)(svelte@4.2.11) sveltekit-superforms: - specifier: ^2.3.0 - version: 2.3.0(@sveltejs/kit@2.5.0)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.19.12)(svelte@4.2.11) + specifier: ^2.4.0 + version: 2.4.0(@sveltejs/kit@2.5.0)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.1)(svelte@4.2.11) tailwindcss: specifier: ^3.4.1 version: 3.4.1 @@ -195,8 +201,8 @@ packages: - nodemailer dev: false - /@csstools/selector-specificity@3.0.1(postcss-selector-parser@6.0.15): - resolution: {integrity: sha512-NPljRHkq4a14YzZ3YD406uaxh7s0g6eAq3L9aLOWywoqe8PkYamAvtsh7KNX6c++ihDrJ0RiU+/z7rGnhlZ5ww==} + /@csstools/selector-specificity@3.0.2(postcss-selector-parser@6.0.15): + resolution: {integrity: sha512-RpHaZ1h9LE7aALeQXmXrJkRG84ZxIsctEN2biEUmFyKpzFM3zZ35eUMcIzZFsw/2olQE6v69+esEqU2f1MKycg==} engines: {node: ^14 || ^16 || >=18} peerDependencies: postcss-selector-parser: ^6.0.13 @@ -212,6 +218,15 @@ packages: requiresBuild: true optional: true + /@esbuild/aix-ppc64@0.20.1: + resolution: {integrity: sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm64@0.19.12: resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} engines: {node: '>=12'} @@ -220,6 +235,15 @@ packages: requiresBuild: true optional: true + /@esbuild/android-arm64@0.20.1: + resolution: {integrity: sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm@0.19.12: resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} engines: {node: '>=12'} @@ -228,6 +252,15 @@ packages: requiresBuild: true optional: true + /@esbuild/android-arm@0.20.1: + resolution: {integrity: sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-x64@0.19.12: resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} engines: {node: '>=12'} @@ -236,6 +269,15 @@ packages: requiresBuild: true optional: true + /@esbuild/android-x64@0.20.1: + resolution: {integrity: sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-arm64@0.19.12: resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} engines: {node: '>=12'} @@ -244,6 +286,15 @@ packages: requiresBuild: true optional: true + /@esbuild/darwin-arm64@0.20.1: + resolution: {integrity: sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-x64@0.19.12: resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} engines: {node: '>=12'} @@ -252,6 +303,15 @@ packages: requiresBuild: true optional: true + /@esbuild/darwin-x64@0.20.1: + resolution: {integrity: sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-arm64@0.19.12: resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} engines: {node: '>=12'} @@ -260,6 +320,15 @@ packages: requiresBuild: true optional: true + /@esbuild/freebsd-arm64@0.20.1: + resolution: {integrity: sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-x64@0.19.12: resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} engines: {node: '>=12'} @@ -268,6 +337,15 @@ packages: requiresBuild: true optional: true + /@esbuild/freebsd-x64@0.20.1: + resolution: {integrity: sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm64@0.19.12: resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} engines: {node: '>=12'} @@ -276,6 +354,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-arm64@0.20.1: + resolution: {integrity: sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm@0.19.12: resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} engines: {node: '>=12'} @@ -284,6 +371,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-arm@0.20.1: + resolution: {integrity: sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ia32@0.19.12: resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} engines: {node: '>=12'} @@ -292,6 +388,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-ia32@0.20.1: + resolution: {integrity: sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64@0.19.12: resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} engines: {node: '>=12'} @@ -300,6 +405,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-loong64@0.20.1: + resolution: {integrity: sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-mips64el@0.19.12: resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} engines: {node: '>=12'} @@ -308,6 +422,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-mips64el@0.20.1: + resolution: {integrity: sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ppc64@0.19.12: resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} engines: {node: '>=12'} @@ -316,6 +439,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-ppc64@0.20.1: + resolution: {integrity: sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-riscv64@0.19.12: resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} engines: {node: '>=12'} @@ -324,6 +456,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-riscv64@0.20.1: + resolution: {integrity: sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-s390x@0.19.12: resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} engines: {node: '>=12'} @@ -332,6 +473,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-s390x@0.20.1: + resolution: {integrity: sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-x64@0.19.12: resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} engines: {node: '>=12'} @@ -340,6 +490,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-x64@0.20.1: + resolution: {integrity: sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/netbsd-x64@0.19.12: resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} engines: {node: '>=12'} @@ -348,6 +507,15 @@ packages: requiresBuild: true optional: true + /@esbuild/netbsd-x64@0.20.1: + resolution: {integrity: sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/openbsd-x64@0.19.12: resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} engines: {node: '>=12'} @@ -356,6 +524,15 @@ packages: requiresBuild: true optional: true + /@esbuild/openbsd-x64@0.20.1: + resolution: {integrity: sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/sunos-x64@0.19.12: resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} engines: {node: '>=12'} @@ -364,6 +541,15 @@ packages: requiresBuild: true optional: true + /@esbuild/sunos-x64@0.20.1: + resolution: {integrity: sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-arm64@0.19.12: resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} engines: {node: '>=12'} @@ -372,6 +558,15 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-arm64@0.20.1: + resolution: {integrity: sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-ia32@0.19.12: resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} engines: {node: '>=12'} @@ -380,6 +575,15 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-ia32@0.20.1: + resolution: {integrity: sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-x64@0.19.12: resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} engines: {node: '>=12'} @@ -388,6 +592,15 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-x64@0.20.1: + resolution: {integrity: sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -447,7 +660,7 @@ packages: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} dev: false - /@gcornut/valibot-json-schema@0.0.22(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.19.12)(valibot@0.28.1): + /@gcornut/valibot-json-schema@0.0.22(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.1)(valibot@0.28.1): resolution: {integrity: sha512-aUrIDndl7KJF1LruNMpGFMIQRNwB4pV5YhiTvgmIKkjet+OhEmX5ZfaET8MQQ+Br0Dd6fQgVtNbxhmyLPDB1+A==} hasBin: true requiresBuild: true @@ -458,8 +671,8 @@ packages: valibot: '>= 0.21.0' dependencies: '@types/json-schema': 7.0.15 - esbuild: 0.19.12 - esbuild-runner: 2.2.2(esbuild@0.19.12) + esbuild: 0.20.1 + esbuild-runner: 2.2.2(esbuild@0.20.1) valibot: 0.28.1 dev: true optional: true @@ -926,6 +1139,10 @@ packages: /@types/cookie@0.6.0: resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + /@types/diff@5.0.9: + resolution: {integrity: sha512-RWVEhh/zGXpAVF/ZChwNnv7r4rvqzJ7lYNSmZSVTxjV0PBLf6Qu7RNg+SUtkpzxmiNkjCx0Xn2tPp7FIkshJwQ==} + dev: true + /@types/dompurify@3.0.5: resolution: {integrity: sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==} dependencies: @@ -966,8 +1183,8 @@ packages: dev: true optional: true - /@typescript-eslint/eslint-plugin@7.0.1(@typescript-eslint/parser@7.0.1)(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-OLvgeBv3vXlnnJGIAgCLYKjgMEU+wBGj07MQ/nxAaON+3mLzX7mJbhRYrVGiVvFiXtwFlkcBa/TtmglHy0UbzQ==} + /@typescript-eslint/eslint-plugin@7.0.2(@typescript-eslint/parser@7.0.2)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-/XtVZJtbaphtdrWjr+CJclaCVGPtOdBpFEnvtNf/jRV0IiEemRrL0qABex/nEt8isYcnFacm3nPHYQwL+Wb7qg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -978,11 +1195,11 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.0.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/scope-manager': 7.0.1 - '@typescript-eslint/type-utils': 7.0.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/utils': 7.0.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 7.0.1 + '@typescript-eslint/parser': 7.0.2(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 7.0.2 + '@typescript-eslint/type-utils': 7.0.2(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 7.0.2(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 7.0.2 debug: 4.3.4 eslint: 8.56.0 graphemer: 1.4.0 @@ -995,8 +1212,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@7.0.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ==} + /@typescript-eslint/parser@7.0.2(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^8.56.0 @@ -1005,10 +1222,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 7.0.1 - '@typescript-eslint/types': 7.0.1 - '@typescript-eslint/typescript-estree': 7.0.1(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 7.0.1 + '@typescript-eslint/scope-manager': 7.0.2 + '@typescript-eslint/types': 7.0.2 + '@typescript-eslint/typescript-estree': 7.0.2(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 7.0.2 debug: 4.3.4 eslint: 8.56.0 typescript: 5.3.3 @@ -1016,16 +1233,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@7.0.1: - resolution: {integrity: sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==} + /@typescript-eslint/scope-manager@7.0.2: + resolution: {integrity: sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 7.0.1 - '@typescript-eslint/visitor-keys': 7.0.1 + '@typescript-eslint/types': 7.0.2 + '@typescript-eslint/visitor-keys': 7.0.2 dev: true - /@typescript-eslint/type-utils@7.0.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-YtT9UcstTG5Yqy4xtLiClm1ZpM/pWVGFnkAa90UfdkkZsR1eP2mR/1jbHeYp8Ay1l1JHPyGvoUYR6o3On5Nhmw==} + /@typescript-eslint/type-utils@7.0.2(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-IKKDcFsKAYlk8Rs4wiFfEwJTQlHcdn8CLwLaxwd6zb8HNiMcQIFX9sWax2k4Cjj7l7mGS5N1zl7RCHOVwHq2VQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^8.56.0 @@ -1034,8 +1251,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 7.0.1(typescript@5.3.3) - '@typescript-eslint/utils': 7.0.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 7.0.2(typescript@5.3.3) + '@typescript-eslint/utils': 7.0.2(eslint@8.56.0)(typescript@5.3.3) debug: 4.3.4 eslint: 8.56.0 ts-api-utils: 1.2.1(typescript@5.3.3) @@ -1044,13 +1261,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types@7.0.1: - resolution: {integrity: sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==} + /@typescript-eslint/types@7.0.2: + resolution: {integrity: sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@7.0.1(typescript@5.3.3): - resolution: {integrity: sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==} + /@typescript-eslint/typescript-estree@7.0.2(typescript@5.3.3): + resolution: {integrity: sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1058,8 +1275,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 7.0.1 - '@typescript-eslint/visitor-keys': 7.0.1 + '@typescript-eslint/types': 7.0.2 + '@typescript-eslint/visitor-keys': 7.0.2 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1071,8 +1288,8 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@7.0.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==} + /@typescript-eslint/utils@7.0.2(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^8.56.0 @@ -1080,9 +1297,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@types/json-schema': 7.0.15 '@types/semver': 7.5.7 - '@typescript-eslint/scope-manager': 7.0.1 - '@typescript-eslint/types': 7.0.1 - '@typescript-eslint/typescript-estree': 7.0.1(typescript@5.3.3) + '@typescript-eslint/scope-manager': 7.0.2 + '@typescript-eslint/types': 7.0.2 + '@typescript-eslint/typescript-estree': 7.0.2(typescript@5.3.3) eslint: 8.56.0 semver: 7.6.0 transitivePeerDependencies: @@ -1090,11 +1307,11 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys@7.0.1: - resolution: {integrity: sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==} + /@typescript-eslint/visitor-keys@7.0.2: + resolution: {integrity: sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 7.0.1 + '@typescript-eslint/types': 7.0.2 eslint-visitor-keys: 3.4.3 dev: true @@ -1279,7 +1496,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.23.0 - caniuse-lite: 1.0.30001587 + caniuse-lite: 1.0.30001588 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -1326,8 +1543,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001587 - electron-to-chromium: 1.4.673 + caniuse-lite: 1.0.30001588 + electron-to-chromium: 1.4.676 node-releases: 2.0.14 update-browserslist-db: 1.0.13(browserslist@4.23.0) dev: true @@ -1368,8 +1585,8 @@ packages: dev: true optional: true - /caniuse-lite@1.0.30001587: - resolution: {integrity: sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==} + /caniuse-lite@1.0.30001588: + resolution: {integrity: sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==} dev: true /chai@4.4.1: @@ -1581,6 +1798,11 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true + /diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + dev: false + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1603,12 +1825,17 @@ packages: resolution: {integrity: sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ==} dev: false + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + dev: true + /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true - /electron-to-chromium@1.4.673: - resolution: {integrity: sha512-zjqzx4N7xGdl5468G+vcgzDhaHkaYgVcf9MqgexcTqsl2UHSCmOj/Bi3HAprg4BZCpC7HyD8a6nZl6QAZf72gw==} + /electron-to-chromium@1.4.676: + resolution: {integrity: sha512-uHt4FB8SeYdhcOsj2ix/C39S7sPSNFJpzShjxGOm1KdF4MHyGqGi389+T5cErsodsijojXilYaHIKKqJfqh7uQ==} dev: true /emoji-regex@8.0.0: @@ -1628,13 +1855,13 @@ packages: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} dev: true - /esbuild-runner@2.2.2(esbuild@0.19.12): + /esbuild-runner@2.2.2(esbuild@0.20.1): resolution: {integrity: sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==} hasBin: true peerDependencies: esbuild: '*' dependencies: - esbuild: 0.19.12 + esbuild: 0.20.1 source-map-support: 0.5.21 tslib: 2.4.0 dev: true @@ -1670,6 +1897,38 @@ packages: '@esbuild/win32-ia32': 0.19.12 '@esbuild/win32-x64': 0.19.12 + /esbuild@0.20.1: + resolution: {integrity: sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.1 + '@esbuild/android-arm': 0.20.1 + '@esbuild/android-arm64': 0.20.1 + '@esbuild/android-x64': 0.20.1 + '@esbuild/darwin-arm64': 0.20.1 + '@esbuild/darwin-x64': 0.20.1 + '@esbuild/freebsd-arm64': 0.20.1 + '@esbuild/freebsd-x64': 0.20.1 + '@esbuild/linux-arm': 0.20.1 + '@esbuild/linux-arm64': 0.20.1 + '@esbuild/linux-ia32': 0.20.1 + '@esbuild/linux-loong64': 0.20.1 + '@esbuild/linux-mips64el': 0.20.1 + '@esbuild/linux-ppc64': 0.20.1 + '@esbuild/linux-riscv64': 0.20.1 + '@esbuild/linux-s390x': 0.20.1 + '@esbuild/linux-x64': 0.20.1 + '@esbuild/netbsd-x64': 0.20.1 + '@esbuild/openbsd-x64': 0.20.1 + '@esbuild/sunos-x64': 0.20.1 + '@esbuild/win32-arm64': 0.20.1 + '@esbuild/win32-ia32': 0.20.1 + '@esbuild/win32-x64': 0.20.1 + dev: true + optional: true + /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -1910,13 +2169,13 @@ packages: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: - flatted: 3.2.9 + flatted: 3.2.10 keyv: 4.5.4 rimraf: 3.0.2 dev: true - /flatted@3.2.9: - resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + /flatted@3.2.10: + resolution: {integrity: sha512-hla0i4X34dHDV1/QqK0ZfSfx/Vo4VVFZj5PVxFsM9UNRXQzkml6q4TJIm8d6lsyV1Klu+27l/db3r6xPOqdXXg==} dev: true /foreground-child@3.1.1: @@ -2355,8 +2614,8 @@ packages: engines: {node: '>=10'} dev: true - /lilconfig@3.1.0: - resolution: {integrity: sha512-p3cz0JV5vw/XeouBU3Ldnp+ZkBjE+n8ydJ4mcwBrOiXXPqNlrzGBqWs9X4MWF7f+iKUBu794Y8Hh8yawiJbCjw==} + /lilconfig@3.1.1: + resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} engines: {node: '>=14'} dev: true @@ -2805,7 +3064,7 @@ packages: ts-node: optional: true dependencies: - lilconfig: 3.1.0 + lilconfig: 3.1.1 postcss: 8.4.35 yaml: 2.3.4 dev: true @@ -2820,13 +3079,13 @@ packages: postcss-selector-parser: 6.0.15 dev: true - /postcss-nesting@12.0.2(postcss@8.4.35): - resolution: {integrity: sha512-63PpJHSeNs93S3ZUIyi+7kKx4JqOIEJ6QYtG3x+0qA4J03+4n0iwsyA1GAHyWxsHYljQS4/4ZK1o2sMi70b5wQ==} + /postcss-nesting@12.0.3(postcss@8.4.35): + resolution: {integrity: sha512-yrtMRPFNkfZMv9ikBvZ/Eh3RxhpMBKQ3KzD7LCY8+jYVlgju/Mdcxi4JY8bW2Y7ISXw8GTLuF/o+kFtp+yaVfQ==} engines: {node: ^14 || ^16 || >=18} peerDependencies: postcss: ^8.4 dependencies: - '@csstools/selector-specificity': 3.0.1(postcss-selector-parser@6.0.15) + '@csstools/selector-specificity': 3.0.2(postcss-selector-parser@6.0.15) postcss: 8.4.35 postcss-selector-parser: 6.0.15 dev: true @@ -3365,8 +3624,8 @@ packages: magic-string: 0.30.7 periscopic: 3.1.0 - /sveltekit-superforms@2.3.0(@sveltejs/kit@2.5.0)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.19.12)(svelte@4.2.11): - resolution: {integrity: sha512-ahToo6eEJfckRwl9TGHqjJjBq92bKXzex3YiTvH0bDYQ1G/ML4QYPAbUvQuEEG7UcFv8kRjPh8GcEjrxstI3eg==} + /sveltekit-superforms@2.4.0(@sveltejs/kit@2.5.0)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.1)(svelte@4.2.11): + resolution: {integrity: sha512-hVX6nDN4LdGDf8asygI9c7W/M4o0hSv0HwsCMYlBIVwb/LnWUDa7Nt+fc0Ro7iKtOu52u71yGsDXv8kbjYpJbg==} requiresBuild: true peerDependencies: '@sveltejs/kit': 1.x || 2.x @@ -3396,7 +3655,7 @@ packages: svelte: 4.2.11 ts-deepmerge: 7.0.0 optionalDependencies: - '@gcornut/valibot-json-schema': 0.0.22(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.19.12)(valibot@0.28.1) + '@gcornut/valibot-json-schema': 0.0.22(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.1)(valibot@0.28.1) '@sinclair/typebox': 0.32.14 '@sodaru/yup-to-json-schema': 2.0.1 '@vinejs/vine': 1.7.1 diff --git a/src/app.pcss b/src/app.pcss index 05095e1..6e5eff2 100644 --- a/src/app.pcss +++ b/src/app.pcss @@ -17,6 +17,10 @@ button { text-overflow: ellipsis; } +.border-1 { + border-width: 1px; +} + .v-form-field > input { @apply input input-bordered w-full max-w-xs; } diff --git a/src/lib/server/trpc/routes/entry.ts b/src/lib/server/trpc/routes/entry.ts index 246b787..b6372f0 100644 --- a/src/lib/server/trpc/routes/entry.ts +++ b/src/lib/server/trpc/routes/entry.ts @@ -17,6 +17,7 @@ import { newEntryExecution, newEntryVersion, } from "$lib/server/query"; +import { versionsDiff } from "$lib/shared/util/diff"; const ZEntityId = fields.EntityId(); @@ -38,6 +39,12 @@ export const entryRouter = t.router({ versions: t.procedure .input(ZEntityId) .query(async (opts) => trpcWrap(async () => getEntryVersions(opts.input))), + versionsDiff: t.procedure.input(ZEntityId).query(async (opts) => + trpcWrap(async () => { + const versions = await getEntryVersions(opts.input); + return versionsDiff(versions); + }) + ), executions: t.procedure .input(ZEntityId) .query(async (opts) => trpcWrap(async () => getEntryExecutions(opts.input))), diff --git a/src/lib/shared/util/diff.test.ts b/src/lib/shared/util/diff.test.ts new file mode 100644 index 0000000..bcf6737 --- /dev/null +++ b/src/lib/shared/util/diff.test.ts @@ -0,0 +1,110 @@ +import { test, expect } from "vitest"; +import type { EntryVersion } from "$lib/shared/model"; +import { CATEGORIES, U1, U2 } from "$tests/helpers/testdata"; +import { versionsDiff } from "./diff"; + +test("versions diff", () => { + const versions: EntryVersion[] = [ + { + id: 1, + author: U1, + category: CATEGORIES[0], + created_at: new Date(Date.UTC(2024, 1, 10, 10, 30)), + date: "2024-01-11", + priority: false, + text: "10ml Blut abnehmen.\n\nDas Blut muss auf XYZ getestet werden.", + }, + { + id: 2, + author: U2, + category: CATEGORIES[0], + created_at: new Date(Date.UTC(2024, 1, 10, 11, 30)), + date: "2024-01-12", + priority: true, + text: "10ml Blut abnehmen.\n\nDas Blut muss auf XYZ-Erreger getestet werden.\n\nHierfür ist das Labor Meier zuständig.", + }, + { + id: 3, + author: U1, + category: CATEGORIES[0], + created_at: new Date(Date.UTC(2024, 1, 10, 11, 31)), + date: "2024-01-12", + priority: true, + text: "10ml Blut abnehmen.\n\nDas Blut muss auf Lambda-Erreger getestet werden.\n\nHierfür ist das Labor Meier zuständig.", + }, + ]; + + const diff = versionsDiff(versions); + expect(diff).toStrictEqual([ + { + id: 3, + author: { + id: 1, + name: "Sven Schulz", + email: "sven.schulz@example.com", + }, + category: { + id: 1, + name: "Laborabnahme", + description: "Blutabnahme zur Untersuchung im Labor", + color: "FF0000", + }, + created_at: new Date("2024-02-10T11:31:00.000Z"), + date: "2024-01-12", + priority: true, + text: [ + { + count: 38, + added: true, + removed: undefined, + value: + "10ml Blut abnehmen.\n\nDas Blut muss auf Lambda-Erreger getestet werden.\n\nHierfür ist das Labor Meier zuständig.", + }, + ], + }, + { + id: 2, + author: { + id: 2, + name: "Sabrina Loewe", + email: "sabrina.loewe@example.com", + }, + created_at: new Date("2024-02-10T11:30:00.000Z"), + category: undefined, + date: undefined, + priority: undefined, + text: [ + { count: 16, value: "10ml Blut abnehmen.\n\nDas Blut muss auf " }, + { count: 1, added: undefined, removed: true, value: "Lambda" }, + { count: 1, added: true, removed: undefined, value: "XYZ" }, + { + count: 21, + value: "-Erreger getestet werden.\n\nHierfür ist das Labor Meier zuständig.", + }, + ], + }, + { + id: 1, + author: { + id: 1, + name: "Sven Schulz", + email: "sven.schulz@example.com", + }, + created_at: new Date("2024-02-10T10:30:00.000Z"), + category: undefined, + text: [ + { count: 17, value: "10ml Blut abnehmen.\n\nDas Blut muss auf XYZ" }, + { count: 2, added: undefined, removed: true, value: "-Erreger" }, + { count: 5, value: " getestet werden." }, + { + count: 14, + added: undefined, + removed: true, + value: "\n\nHierfür ist das Labor Meier zuständig.", + }, + ], + date: "2024-01-11", + priority: false, + }, + ]); +}); diff --git a/src/lib/shared/util/diff.ts b/src/lib/shared/util/diff.ts new file mode 100644 index 0000000..726346e --- /dev/null +++ b/src/lib/shared/util/diff.ts @@ -0,0 +1,46 @@ +import { diffWords } from "diff"; +import type { EntryVersion, Category, Option, UserTag } from "$lib/shared/model"; + +export type EntryVersionChange = { + id: number; + author: UserTag; + created_at: Date; + + text: Diff.Change[]; + date?: string; + category?: Option; + priority?: boolean; +}; + +function newOrUndef(o: T, n: T): T | undefined { + return o === n ? undefined : n; +} + +export function versionsDiff(versions: EntryVersion[]): EntryVersionChange[] { + let prev = versions[versions.length - 1]; + const changes: EntryVersionChange[] = [ + { + ...prev, + text: diffWords("", prev.text), + }, + ]; + + for (let i = versions.length - 2; i >= 0; i--) { + const v = versions[i]; + const text = diffWords(prev.text, v.text); + + changes.push({ + id: v.id, + author: v.author, + created_at: v.created_at, + text, + date: newOrUndef(prev.date, v.date), + category: prev.category?.id === v.category?.id ? undefined : v.category, + priority: newOrUndef(prev.priority, v.priority), + }); + + prev = v; + } + + return changes; +} diff --git a/src/lib/shared/util/index.ts b/src/lib/shared/util/index.ts index 120df12..3c4c571 100644 --- a/src/lib/shared/util/index.ts +++ b/src/lib/shared/util/index.ts @@ -25,6 +25,10 @@ export function formatDate(date: Date | string, time = false): string { } } +export function formatBool(val: boolean): string { + return val ? "Ja" : "Nein"; +} + export function getQueryUrl(q: EntityQuery, basePath: string): string { if (Object.values(q).filter((q) => q !== undefined).length === 0) return basePath; return basePath + "/" + JSON.stringify(q); diff --git a/src/routes/(app)/entry/[id]/versions/+page.svelte b/src/routes/(app)/entry/[id]/versions/+page.svelte new file mode 100644 index 0000000..47c77d1 --- /dev/null +++ b/src/routes/(app)/entry/[id]/versions/+page.svelte @@ -0,0 +1,82 @@ + + + + Eintrag #{v1.id} - Versionen + + +

+ Eintrag #{v1.id} - Versionen +

+ +
+ {#each data.versions as version} +
+ + + + + + + + + + + {#if version.category} + + + + + {/if} + {#if version.text.length > 0} + + + + + {/if} + {#if version.date !== undefined} + + + + + {/if} + {#if version.priority !== undefined} + + + + + {/if} + +
Autor
Erstellt am{formatDate(version.created_at, true)}
Katgeorie + {#if version.category}{/if} +
Text + {#each version.text as change} + + {change.value} + + {/each} +
Datum{formatDate(version.date)}
Priorität{formatBool(version.priority)}
+
+ {/each} +
+ + diff --git a/src/routes/(app)/entry/[id]/versions/+page.ts b/src/routes/(app)/entry/[id]/versions/+page.ts new file mode 100644 index 0000000..d7b5129 --- /dev/null +++ b/src/routes/(app)/entry/[id]/versions/+page.ts @@ -0,0 +1,11 @@ +import { ZUrlEntityId } from "$lib/shared/model/validation"; +import { trpc } from "$lib/shared/trpc"; +import { loadWrap } from "$lib/shared/util"; +import type { PageLoad } from "./$types"; + +export const load: PageLoad = async (event) => { + const id = ZUrlEntityId.parse(event.params.id); + const versions = await loadWrap(async () => trpc(event).entry.versionsDiff.query(id)); + + return { versions }; +}; From e60a5b016217253ecd14e89721cd30e2f0514d53 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Mon, 26 Feb 2024 16:18:57 +0100 Subject: [PATCH 3/8] add entry history view --- src/app.pcss | 29 ++++++ src/lib/components/ui/Header.svelte | 20 +++++ src/lib/shared/util/index.ts | 3 + src/routes/(app)/entry/[id]/+page.svelte | 63 ++++++------- src/routes/(app)/entry/[id]/+page.ts | 6 +- .../(app)/entry/[id]/versions/+page.svelte | 88 ++++++++----------- 6 files changed, 127 insertions(+), 82 deletions(-) create mode 100644 src/lib/components/ui/Header.svelte diff --git a/src/app.pcss b/src/app.pcss index 6e5eff2..77319c1 100644 --- a/src/app.pcss +++ b/src/app.pcss @@ -29,3 +29,32 @@ button { .v-form-field > [aria-invalid="true"] { @apply input-error; } + +.card2 { + @apply bg-base-200; + @apply rounded-xl; + @apply mb-8; + @apply flex flex-col; + @apply border-solid border-base-content/30 border-[1px]; + + .row { + @apply flex flex-row p-2; + @apply border-solid border-base-content/30 border-t-[1px]; + } + + .row:first-child { + @apply rounded-t-xl border-none; + } + + .row:last-child { + @apply rounded-b-xl; + } + + .c-light { + @apply bg-base-content/20; + } + + .c-primary { + @apply bg-primary text-primary-content; + } +} diff --git a/src/lib/components/ui/Header.svelte b/src/lib/components/ui/Header.svelte new file mode 100644 index 0000000..d41a655 --- /dev/null +++ b/src/lib/components/ui/Header.svelte @@ -0,0 +1,20 @@ + + +
+ {#if backHref} + + + + {/if} + +

{title}

+ + +
diff --git a/src/lib/shared/util/index.ts b/src/lib/shared/util/index.ts index 3c4c571..df6daf1 100644 --- a/src/lib/shared/util/index.ts +++ b/src/lib/shared/util/index.ts @@ -2,6 +2,7 @@ import { goto } from "$app/navigation"; import type { EntityQuery } from "$lib/shared/model"; import { TRPCClientError } from "@trpc/client"; import { error } from "@sveltejs/kit"; +import { ZodError } from "zod"; export function formatDate(date: Date | string, time = false): string { let dt = date; @@ -60,6 +61,8 @@ export async function loadWrap(f: () => Promise) { } catch (e) { if (e instanceof TRPCClientError) { error(e.data?.httpStatus ?? 500, e.message); + } else if (e instanceof ZodError) { + error(400, e.message); } else if (e instanceof Error) { error(500, e.message); } else { diff --git a/src/routes/(app)/entry/[id]/+page.svelte b/src/routes/(app)/entry/[id]/+page.svelte index 271d1c7..3c1f205 100644 --- a/src/routes/(app)/entry/[id]/+page.svelte +++ b/src/routes/(app)/entry/[id]/+page.svelte @@ -5,6 +5,9 @@ import RoomField from "$lib/components/table/RoomField.svelte"; import CategoryField from "$lib/components/table/CategoryField.svelte"; import Markdown from "$lib/components/ui/Markdown.svelte"; + import Header from "$lib/components/ui/Header.svelte"; + import Icon from "$lib/components/ui/Icon.svelte"; + import { mdiHistory } from "@mdi/js"; export let data: PageData; @@ -13,50 +16,50 @@ Eintrag #{data.entry.id} -

- Eintrag #{data.entry.id} +
{#if data.entry.current_version.category} {/if} -

-
-

+ + + + + + +

+
Patient
+
{#if data.entry.patient.room} {/if} {data.entry.patient.first_name} {data.entry.patient.last_name} ({data.entry.patient.age}) -

+
-
-

- -

+
+
Beschreibung
+
+

+ +

+
{#if data.entry.execution} -
-

- Erledigt am {formatDate(data.entry.execution.created_at, true)} von - : -

- -

- -

+
+
+

+ Erledigt am {formatDate(data.entry.execution.created_at, true)} von + : +

+
+
+

+ +

+
{/if} - - diff --git a/src/routes/(app)/entry/[id]/+page.ts b/src/routes/(app)/entry/[id]/+page.ts index 204d7cf..af28d20 100644 --- a/src/routes/(app)/entry/[id]/+page.ts +++ b/src/routes/(app)/entry/[id]/+page.ts @@ -4,8 +4,10 @@ import { loadWrap } from "$lib/shared/util"; import type { PageLoad } from "./$types"; export const load: PageLoad = async (event) => { - const id = ZUrlEntityId.parse(event.params.id); - const entry = await loadWrap(async () => trpc(event).entry.get.query(id)); + const entry = await loadWrap(async () => { + const id = ZUrlEntityId.parse(event.params.id); + return trpc(event).entry.get.query(id); + }); return { entry }; }; diff --git a/src/routes/(app)/entry/[id]/versions/+page.svelte b/src/routes/(app)/entry/[id]/versions/+page.svelte index 47c77d1..43aee44 100644 --- a/src/routes/(app)/entry/[id]/versions/+page.svelte +++ b/src/routes/(app)/entry/[id]/versions/+page.svelte @@ -3,6 +3,7 @@ import UserField from "$lib/components/table/UserField.svelte"; import { formatBool, formatDate } from "$lib/shared/util"; import type { PageData } from "./$types"; + import Header from "$lib/components/ui/Header.svelte"; export let data: PageData; $: v1 = data.versions[0]; @@ -12,64 +13,51 @@ Eintrag #{v1.id} - Versionen -

- Eintrag #{v1.id} - Versionen -

+
{#each data.versions as version} -
- - - - - - - - - - - {#if version.category} - - - - - {/if} - {#if version.text.length > 0} - - - - - {/if} - {#if version.date !== undefined} - - - - - {/if} - {#if version.priority !== undefined} - - - - - {/if} - -
Autor
Erstellt am{formatDate(version.created_at, true)}
Katgeorie - {#if version.category}{/if} -
Text - {#each version.text as change} - - {change.value} - - {/each} -
Datum{formatDate(version.date)}
Priorität{formatBool(version.priority)}
+
+
+ , {formatDate(version.created_at, true)} +
+ {#if version.category} +
+
Kategeorie
+
+
+ {/if} + {#if version.text.length > 0} +
+
Text
+
+ {#each version.text as change} + + {change.value} + + {/each} +
+
+ {/if} + {#if version.date !== undefined} +
+
Datum
+
{formatDate(version.date)}
+
+ {/if} + {#if version.priority !== undefined} +
+
Priorität
+
{formatBool(version.priority)}
+
+ {/if}
{/each}