Compare commits

...

7 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] 53867985d1 Initial plan 2026-02-12 17:48:29 +00:00
Bernd Storath b3cc1ce839 reduce container size
from around 700mb to 400mb
2026-02-11 15:36:29 +01:00
Bernd Storath 71aaec93ef add unit tests
this adds the groundwork to start unit testing some modules
2026-02-11 15:23:04 +01:00
HackingAll 7a219b73d4 Adding galician (#2473)
* Adding galego -> gl.json

* Update i18n.config.ts

* Update nuxt.config.ts
2026-02-10 11:18:02 +01:00
Bare7a c456c5e7dd Add Bulgarian translation (#2466) 2026-02-09 08:00:38 +01:00
Bernd Storath a5880cc0b8 update packages 2026-02-09 08:00:07 +01:00
Bernd Storath 5fca628ebd change date in copyright footer 2026-02-06 15:32:39 +01:00
13 changed files with 1814 additions and 794 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ COPY --from=build /app/.output /app
COPY --from=build /app/server/database/migrations /app/server/database/migrations
# libsql (https://github.com/nitrojs/nitro/issues/3328)
RUN cd /app/server && \
npm install --no-save libsql && \
npm install --no-save --omit=dev libsql && \
npm cache clean --force
# cli
COPY --from=build /app/cli/cli.sh /usr/local/bin/cli
+1 -1
View File
@@ -13,5 +13,5 @@
"devDependencies": {
"prettier": "^3.8.1"
},
"packageManager": "pnpm@10.28.2"
"packageManager": "pnpm@10.29.2"
}
+2
View File
@@ -23,4 +23,6 @@ logs
.env.*
!.env.example
coverage/
wg-easy.db
+1
View File
@@ -0,0 +1 @@
setups.@nuxt/test-utils="3.23.0"
+1 -1
View File
@@ -7,7 +7,7 @@
href="https://github.com/wg-easy/wg-easy"
>WireGuard Easy</a
>
({{ globalStore.information?.currentRelease }}) © 2021-2025 by
({{ globalStore.information?.currentRelease }}) © 2021-2026 by
<a
class="hover:underline"
target="_blank"
+4
View File
@@ -16,6 +16,8 @@ import bn from './locales/bn.json';
import id from './locales/id.json';
import nl from './locales/nl.json';
import nb from './locales/nb.json';
import bg from './locales/bg.json';
import gl from './locales/gl.json';
export default defineI18nConfig(() => ({
legacy: false,
@@ -39,5 +41,7 @@ export default defineI18nConfig(() => ({
id,
nl,
nb,
bg,
gl,
},
}));
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "Профил",
"clients": "Клиенти",
"admin": {
"panel": "Админ Панел",
"general": "Общи",
"config": "Конфигурация",
"interface": "Интерфейс",
"hooks": "Hooks"
}
},
"user": {
"email": "Имейл"
},
"me": {
"currentPassword": "Текуща парола",
"enable2fa": "Активирай двуфакторна автентикация",
"enable2faDesc": "Сканирай QR кода с твоето приложение за автентикатор или въведи ключа ръчно.",
"2faKey": "TOTP ключ",
"2faCodeDesc": "Въведи кода от твоето приложение за автентикатор.",
"disable2fa": "Деактивирай двуфакторна автентикация",
"disable2faDesc": "Въведи паролата си, за да деактивираш двуфакторната автентикация."
},
"general": {
"name": "Име",
"username": "Потребителско име",
"password": "Парола",
"newPassword": "Нова парола",
"updatePassword": "Обнови парола",
"mtu": "MTU",
"allowedIps": "Разрешени IP-та",
"dns": "DNS",
"persistentKeepalive": "Постоянно поддържане на връзката",
"logout": "Изход",
"continue": "Продължи",
"host": "Хост",
"port": "Порт",
"yes": "Да",
"no": "Не",
"confirmPassword": "Потвърди парола",
"loading": "Зареждане...",
"2fa": "Двуфакторна автентикация",
"2faCode": "TOTP код"
},
"setup": {
"welcome": "Добре дошъл в първоначалната настройка на wg-easy",
"welcomeDesc": "Откри най-лесния начин да инсталираш и управляваш WireGuard на всеки Linux сървър",
"existingSetup": "Имаш ли вече съществуваща инсталация?",
"createAdminDesc": "Моля, първо въведи администраторско потребителско име и силна сигурна парола. Тези данни ще се използват за вход в административния панел.",
"setupConfigDesc": "Моля, въведи хост и порт. Тази информация ще се използва при генериране на клиентски конфигурации за WireGuard.",
"setupMigrationDesc": "Ако желаеш да мигрираш данните от предишна версия на wg-easy, качи резервното копие.",
"upload": "Качи",
"migration": "Възстанови от резервно копие:",
"createAccount": "Създай акаунт",
"successful": "Настройката е успешна",
"hostDesc": "Публично име/адрес, към който клиентите ще се свързват",
"portDesc": "Публичен UDP порт, на който клиентите ще се свързват и на който WireGuard слуша"
},
"update": {
"updateAvailable": "Налична е актуализация!",
"update": "Актуализирай"
},
"theme": {
"dark": "Тъмна тема",
"light": "Светла тема",
"system": "Системна тема"
},
"layout": {
"toggleCharts": "Покажи/скрий графики",
"donate": "Дарение"
},
"login": {
"signIn": "Вход",
"rememberMe": "Запомни ме",
"rememberMeDesc": "Остани влязъл след затваряне на браузъра",
"insecure": "Не можеш да влезеш през несигурна връзка. Използвай HTTPS.",
"2faRequired": "Изисква се двуфакторна автентикация",
"2faWrong": "Грешен код за двуфакторна автентикация"
},
"client": {
"empty": "Все още няма клиенти.",
"newShort": "Нов",
"sort": "Сортирай",
"create": "Създай клиент",
"created": "Клиентът е създаден",
"new": "Нов клиент",
"name": "Име",
"expireDate": "Дата на изтичане",
"expireDateDesc": "Дата, след която клиентът ще бъде деактивиран. Празно = постоянен",
"delete": "Изтрий",
"deleteClient": "Изтрий клиент",
"deleteDialog1": "Сигурен ли си, че искаш да изтриеш",
"deleteDialog2": "Това действие е необратимо.",
"enabled": "Активен",
"address": "Адрес",
"serverAllowedIps": "Разрешени IP-та от сървъра",
"otlDesc": "Генерирай кратък еднократен линк",
"permanent": "Постоянно",
"createdOn": "Създаден на ",
"lastSeen": "Последно видян на ",
"totalDownload": "Общо изтеглени: ",
"totalUpload": "Общо качени: ",
"newClient": "Нов клиент",
"disableClient": "Деактивирай клиент",
"enableClient": "Активирай клиент",
"noPrivKey": "Този клиент няма известен частен ключ. Не може да се създаде конфигурация.",
"showQR": "Покажи QR код",
"downloadConfig": "Изтегли конфигурация",
"allowedIpsDesc": "Кои IP-та ще се насочват през VPN (замества глобалната настройка)",
"serverAllowedIpsDesc": "Кои IP-та сървърът ще насочва към клиента",
"mtuDesc": "Задава максималния размер на пакета (MTU) за VPN тунела",
"persistentKeepaliveDesc": "Интервал (в секунди) за изпращане на keep-alive пакети. 0 = изключено",
"hooks": "Hooks",
"hooksDescription": "Hooks работят само с wg-quick",
"hooksLeaveEmpty": "Само за wg-quick. В противен случай остави празно",
"dnsDesc": "DNS сървър, който клиентите ще използват (замества глобалната настройка)",
"notConnected": "Клиентът не е свързан",
"endpoint": "Крайна точка",
"endpointDesc": "IP адресът на клиента, от който е установена WireGuard връзката",
"search": "Търси клиенти...",
"config": "Конфигурация",
"viewConfig": "Прегледай конфигурацията"
},
"dialog": {
"change": "Промени",
"cancel": "Отказ",
"create": "Създай"
},
"toast": {
"success": "Успех",
"saved": "Запазено",
"error": "Грешка"
},
"form": {
"actions": "Действия",
"save": "Запази",
"revert": "Отмени промените",
"sectionGeneral": "Общи",
"sectionAdvanced": "Разширени",
"noItems": "Няма елементи",
"nullNoItems": "Няма елементи. Използва се глобалната конфигурация",
"add": "Добави"
},
"admin": {
"general": {
"sessionTimeout": "Време на сесията",
"sessionTimeoutDesc": "Продължителност на сесията при „Запомни ме“ (в секунди)",
"metrics": "Метрики",
"metricsPassword": "Парола",
"metricsPasswordDesc": "Bearer парола за достъп до metrics ендпойнт (парола или argon2 хеш)",
"json": "JSON",
"jsonDesc": "Път за метрики в JSON формат",
"prometheus": "Prometheus",
"prometheusDesc": "Път за Prometheus метрики"
},
"config": {
"connection": "Връзка",
"hostDesc": "Публично име/адрес за клиентите (инвалидира конфигурациите)",
"portDesc": "Публичен UDP порт за клиентите (инвалидира конфигурациите; вероятно искаш да смениш и порта на интерфейса)",
"allowedIpsDesc": "Разрешени IP-та за клиентите (глобална настройка)",
"dnsDesc": "DNS сървър за клиентите (глобална настройка)",
"mtuDesc": "MTU, който ще ползват клиентите (само за нови клиенти)",
"persistentKeepaliveDesc": "Интервал в секунди за keep-alive към сървъра. 0 = изключено (само за нови клиенти)",
"suggest": "Предложи",
"suggestDesc": "Избери IP адрес или хост за полето Host"
},
"interface": {
"cidrSuccess": "CIDR променен",
"device": "Устройство",
"deviceDesc": "Мрежово устройство, през което да се препраща WireGuard трафикът",
"mtuDesc": "MTU, който ще ползва WireGuard",
"portDesc": "UDP порт, на който слуша WireGuard (вероятно искаш да смениш и порта в Config)",
"changeCidr": "Смени CIDR",
"restart": "Рестартирай интерфейс",
"restartDesc": "Рестартиране на WireGuard интерфейса",
"restartWarn": "Сигурен ли си, че искаш да рестартираш интерфейса? Всички клиенти ще бъдат изключени.",
"restartSuccess": "Интерфейсът е рестартиран"
},
"introText": "Добре дошъл в административния панел.\n\nТук можеш да управляваш общите настройки, конфигурацията, настройките на интерфейса и hooks.\n\nЗапочни, като избереш някоя от секциите в страничното меню."
},
"zod": {
"generic": {
"required": "{0} е задължително",
"validNumber": "{0} трябва да е валидно число",
"validString": "{0} трябва да е валиден текст",
"validBoolean": "{0} трябва да е валидна булева стойност",
"validArray": "{0} трябва да е валиден масив",
"stringMin": "{0} трябва да съдържа поне {1} символа",
"numberMin": "{0} трябва да е поне {1}"
},
"client": {
"id": "ID на клиента",
"name": "Име",
"expiresAt": "Изтича на",
"address4": "IPv4 адрес",
"address6": "IPv6 адрес",
"serverAllowedIps": "Разрешени IP-та от сървъра"
},
"user": {
"username": "Потребителско име",
"password": "Парола",
"remember": "Запомни",
"name": "Име",
"email": "Имейл",
"emailInvalid": "Имейлът трябва да е валиден",
"passwordMatch": "Паролите трябва да съвпадат",
"totpEnable": "Активиране на TOTP",
"totpEnableTrue": "TOTP Enable трябва да е true",
"totpCode": "TOTP код"
},
"userConfig": {
"host": "Хост"
},
"general": {
"sessionTimeout": "Време на сесията",
"metricsEnabled": "Метрики",
"metricsPassword": "Парола за метрики"
},
"interface": {
"cidr": "CIDR",
"device": "Устройство",
"cidrValid": "CIDR трябва да е валиден"
},
"otl": "Еднократен линк",
"stringMalformed": "Невалиден формат на низа",
"body": "Тялото трябва да е валиден обект",
"hook": "Hook",
"enabled": "Активиран",
"mtu": "MTU",
"port": "Порт",
"persistentKeepalive": "Постоянно поддържане на връзката",
"address": "IP адрес",
"dns": "DNS",
"allowedIps": "Разрешени IP-та",
"file": "Файл"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
},
"copy": {
"notSupported": "Копиране не се поддържа",
"copied": "Копирано!",
"failed": "Копирането неуспешно",
"copy": "Копирай"
},
"awg": {
"jCLabel": "Брой junk пакети (Jc)",
"jCDescription": "Брой junk пакети за изпращане (1–128, препоръчително: 4–12)",
"jMinLabel": "Минимален размер на junk пакети (Jmin)",
"jMinDescription": "Минимален размер на junk пакетите (0–1279*, препоръчително: 8, трябва да е < Jmax)",
"jMaxLabel": "Максимален размер на junk пакети (Jmax)",
"jMaxDescription": "Максимален размер на junk пакетите (1–1280*, препоръчително: 80, трябва да е > Jmin)",
"s1Label": "Размер на junk в init пакета (S1)",
"s1Description": "Размер на junk в init пакета (01132 [1280*148=1132], препоръчително: 15150, S1+56 ≠ S2)",
"s2Label": "Размер на junk в отговорния пакет (S2)",
"s2Description": "Размер на junk в response пакета (01188 [1280*92=1188], препоръчително: 15–150)",
"s3Label": "Размер на junk в cookie reply пакета (S3)",
"s3Description": "Размер на junk в cookie reply пакета",
"s4Label": "Размер на junk в транспортния пакет (S4)",
"s4Description": "Размер на junk в транспортния пакет",
"i1Label": "Специален junk пакет 1 (I1)",
"i1Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"i2Label": "Специален junk пакет 2 (I2)",
"i2Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"i3Label": "Специален junk пакет 3 (I3)",
"i3Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"i4Label": "Специален junk пакет 4 (I4)",
"i4Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"i5Label": "Специален junk пакет 5 (I5)",
"i5Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"h1Label": "Init magic header (H1)",
"h1Description": "Стойност на хедера в init пакета (5–2147483647, уникална спрямо H2–H4)",
"h2Label": "Response magic header (H2)",
"h2Description": "Стойност на хедера в response пакета (52147483647, уникална спрямо H1, H3, H4)",
"h3Label": "Cookie reply magic header (H3)",
"h3Description": "Стойност на хедера в cookie reply пакета (52147483647, уникална спрямо H1, H2, H4)",
"h4Label": "Transport magic header (H4)",
"h4Description": "Стойност на хедера в транспортния пакет (5–2147483647, уникална спрямо H1–H3)",
"mtuNote": "Стойностите зависят от MTU",
"obfuscationParameters": "Параметри за обфускация на AmneziaWG"
}
}
+145
View File
@@ -0,0 +1,145 @@
{
"pages": {
"me": "Conta",
"clients": "Clientes",
"admin": {
"panel": "Panel de administración",
"general": "Xeral",
"config": "Configuración",
"interface": "Interface",
"hooks": "Hooks"
}
},
"user": {
"email": "Correo electrónico"
},
"me": {
"currentPassword": "Contrasinal actual",
"enable2fa": "Activar a autenticación de dobre factor",
"enable2faDesc": "Escanea o código QR coa túa aplicación de autenticación ou introduce a chave manualmente.",
"2faKey": "Chave TOTP",
"2faCodeDesc": "Introduce o código da túa aplicación de autenticación.",
"disable2fa": "Desactivar a autenticación de dobre factor",
"disable2faDesc": "Introduce o teu contrasinal para desactivar a autenticación de dobre factor."
},
"general": {
"name": "Nome",
"username": "Nome de usuario",
"password": "Contrasinal",
"newPassword": "Novo contrasinal",
"updatePassword": "Actualizar contrasinal",
"mtu": "MTU",
"allowedIps": "IP permitidas",
"dns": "DNS",
"persistentKeepalive": "Keepalive persistente",
"logout": "Pechar sesión",
"continue": "Continuar",
"host": "Host",
"port": "Porto",
"yes": "Si",
"no": "Non",
"confirmPassword": "Confirmar o contrasinal",
"loading": "Cargando...",
"2fa": "Autenticación de dobre factor",
"2faCode": "Código TOTP"
},
"setup": {
"welcome": "Benvido á túa primeira configuración de wg-easy",
"welcomeDesc": "Atopaches a forma máis doada de instalar e xestionar WireGuard en calquera sistema Linux",
"existingSetup": "Tes unha configuración existente?",
"createAdminDesc": "Por favor, introduce primeiro un usuario administrador cun contrasinal seguro. Esta información empregarase para acceder ao panel de administración.",
"setupConfigDesc": "Por favor, introduce a información do host e do porto. Isto empregarase para a configuración dos clientes ao configurar WireGuard nos seus dispositivos.",
"setupMigrationDesc": "Por favor, fornece o ficheiro da copia de seguridade se queres migrar os datos da túa versión anterior de wg-easy á nova configuración.",
"upload": "Subir",
"migration": "Recuperar a copia de seguridade:",
"createAccount": "Crear conta",
"successful": "Configuración completada con éxito",
"hostDesc": "Nome de host público ao que se conectarán os clientes",
"portDesc": "Porto UDP público ao que se conectarán os clientes e no que escoitará WireGuard"
},
"update": {
"updateAvailable": "Hai unha actualización dispoñible!",
"update": "Actualizar"
},
"theme": {
"dark": "Tema escuro",
"light": "Tema claro",
"system": "Tema do sistema"
},
"layout": {
"toggleCharts": "Amosar/Ocultar gráficas",
"donate": "Doar"
},
"login": {
"signIn": "Iniciar sesión",
"rememberMe": "Lembrarme",
"rememberMeDesc": "Manter a sesión iniciada ao pechar o navegador",
"insecure": "Non podes iniciar sesión cunha conexión insegura. Usa HTTPS.",
"2faRequired": "É necesaria a autenticación de dobre factor",
"2faWrong": "A autenticación de dobre factor é incorrecta"
},
"client": {
"empty": "Aínda non hai clientes.",
"newShort": "Novo",
"sort": "Ordenar",
"create": "Crear cliente",
"created": "Cliente creado",
"new": "Novo cliente",
"name": "Nome",
"expireDate": "Data de caducidade",
"expireDateDesc": "Data na que o cliente será desactivado. Déixao en branco para permanente",
"delete": "Eliminar",
"deleteClient": "Eliminar cliente",
"deleteDialog1": "Seguro que queres eliminar",
"deleteDialog2": "Esta acción non se pode desfacer.",
"enabled": "Activado",
"address": "Enderezo",
"serverAllowedIps": "IP permitidas polo servidor",
"otlDesc": "Xerar ligazón curta dun só uso",
"permanent": "Permanente",
"createdOn": "Creado o ",
"lastSeen": "Visto por última vez o ",
"totalDownload": "Descarga total: ",
"totalUpload": "Subida total: ",
"newClient": "Novo cliente",
"disableClient": "Desactivar cliente",
"enableClient": "Activar cliente",
"noPrivKey": "Este cliente non ten unha chave privada coñecida. Non se pode crear a configuración.",
"showQR": "Amosar código QR",
"downloadConfig": "Descargar configuración",
"allowedIpsDesc": "IP que se encamiñarán a través da VPN (sobrescribe a configuración global)",
"serverAllowedIpsDesc": "IP que o servidor encamiñará ao cliente",
"mtuDesc": "Define a unidade máxima de transmisión (tamaño do paquete) para o túnel VPN",
"persistentKeepaliveDesc": "Define o intervalo (en segundos) para os paquetes keep-alive. 0 desactívaos",
"hooks": "Hooks",
"hooksDescription": "Os hooks só funcionan con wg-quick",
"hooksLeaveEmpty": "Só para wg-quick. Noutro caso, déixao baleiro",
"dnsDesc": "Servidor DNS que empregarán os clientes (sobrescribe a configuración global)",
"notConnected": "Cliente non conectado",
"endpoint": "Punto final",
"endpointDesc": "IP do cliente desde a que se establece a conexión WireGuard",
"search": "Buscar clientes...",
"config": "Configuración",
"viewConfig": "Ver configuración"
},
"dialog": {
"change": "Cambiar",
"cancel": "Cancelar",
"create": "Crear"
},
"toast": {
"success": "Éxito",
"saved": "Gardado",
"error": "Erro"
},
"form": {
"actions": "Accións",
"save": "Gardar",
"revert": "Reverter",
"sectionGeneral": "Xeral",
"sectionAdvanced": "Avanzado",
"noItems": "Sen elementos",
"nullNoItems": "Sen elementos. Usando a configuración global",
"add": "Engadir"
}
}
+12 -1
View File
@@ -5,7 +5,7 @@ export default defineNuxtConfig({
future: {
compatibilityVersion: 4,
},
compatibilityDate: '2025-02-04',
compatibilityDate: '2026-02-06',
devtools: { enabled: true },
modules: [
'@nuxtjs/i18n',
@@ -15,6 +15,7 @@ export default defineNuxtConfig({
'radix-vue/nuxt',
'@vueuse/nuxt',
'@nuxt/eslint',
'@nuxt/test-utils/module',
],
colorMode: {
preference: 'system',
@@ -119,6 +120,16 @@ export default defineNuxtConfig({
language: 'nb-NO',
name: 'Norsk bokmål',
},
{
code: 'bg',
language: 'bg-BG',
name: 'Български',
},
{
code: 'gl',
language: 'gl-ES',
name: 'Galego',
},
],
defaultLocale: 'en',
vueI18n: './i18n.config.ts',
+15 -10
View File
@@ -17,13 +17,14 @@
"check:all": "pnpm typecheck && pnpm lint && pnpm format:check && pnpm build",
"db:generate": "drizzle-kit generate",
"cli:build": "node cli/build.js",
"cli:dev": "tsx cli/index.ts"
"cli:dev": "tsx cli/index.ts",
"test:unit": "vitest run --project unit"
},
"dependencies": {
"@eschricht/nuxt-color-mode": "^1.2.0",
"@heroicons/vue": "^2.2.0",
"@libsql/client": "^0.17.0",
"@nuxtjs/i18n": "^10.2.1",
"@nuxtjs/i18n": "^10.2.3",
"@nuxtjs/tailwindcss": "^6.14.0",
"@phc/format": "^1.0.0",
"@pinia/nuxt": "^0.11.3",
@@ -32,22 +33,22 @@
"@vueuse/nuxt": "^14.2.0",
"apexcharts": "^5.3.6",
"argon2": "^0.44.0",
"cidr-tools": "^11.0.5",
"cidr-tools": "^11.0.6",
"citty": "^0.2.0",
"consola": "^3.4.2",
"crc-32": "^1.2.2",
"debug": "^4.4.3",
"drizzle-orm": "^0.45.1",
"ip-bigint": "^8.2.3",
"ip-bigint": "^8.2.4",
"is-cidr": "^6.0.2",
"is-ip": "^5.0.1",
"js-sha256": "^0.11.1",
"nuxt": "^3.21.0",
"otpauth": "^9.4.1",
"nuxt": "^3.21.1",
"otpauth": "^9.5.0",
"pinia": "^3.0.4",
"qr": "^0.5.4",
"radix-vue": "^1.9.17",
"semver": "^7.7.3",
"semver": "^7.7.4",
"tailwindcss": "^3.4.19",
"timeago.js": "^4.0.2",
"vue": "latest",
@@ -55,19 +56,23 @@
"zod": "^4.3.6"
},
"devDependencies": {
"@nuxt/eslint": "^1.13.0",
"@nuxt/eslint": "^1.14.0",
"@nuxt/test-utils": "^3.23.0",
"@types/debug": "^4.1.12",
"@types/phc__format": "^1.0.1",
"@types/semver": "^7.7.1",
"@vitest/coverage-v8": "^4.0.18",
"@vitest/ui": "4.0.18",
"drizzle-kit": "^0.31.8",
"esbuild": "^0.27.2",
"esbuild": "^0.27.3",
"eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
"prettier": "^3.8.1",
"prettier-plugin-tailwindcss": "^0.7.2",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vitest": "^4.0.18",
"vue-tsc": "^3.2.4"
},
"packageManager": "pnpm@10.28.2"
"packageManager": "pnpm@10.29.2"
}
+1308 -780
View File
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
import { expect, test, describe } from 'vitest';
import {
hashPassword,
isPasswordValid,
isValidPasswordHash,
} from '../../server/utils/password';
describe('password', () => {
test('password', async () => {
const hash = await hashPassword('password');
await expect(isPasswordValid('password', hash)).resolves.toBe(true);
await expect(isPasswordValid('wrong', hash)).resolves.toBe(false);
expect(isValidPasswordHash('not a hash')).toBe(false);
expect(isValidPasswordHash(hash)).toBe(true);
expect(isValidPasswordHash(hash.replace('argon2', 'argon3'))).toBe(false);
});
});
+18
View File
@@ -0,0 +1,18 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
projects: [
{
test: {
name: 'unit',
include: ['test/unit/*.{test,spec}.ts'],
environment: 'node',
},
},
],
coverage: {
enabled: true,
},
},
});