From 6dda05f672893803898a5ab81547a68f28f90f65 Mon Sep 17 00:00:00 2001 From: Maurice <61554723+mauriceboe@users.noreply.github.com> Date: Fri, 7 Aug 2026 15:14:14 +0200 Subject: [PATCH] refactor(server): move the stateless helpers into nest/common (#1823) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eight files in services/ hold no state and touch no database: avatarUrl, conflictResult, demo, passwordPolicy, timezoneService, cookie, and the two crypto helpers. They are imported from 65 places, 62 of them already inside src/nest, so having them live in the legacy layer was pure inertia. They stay plain functions rather than becoming providers. Three importers sit outside the container and would have no way to reach an injectable one: db/migrations.ts runs before the app is built, and middleware/auth.ts and middleware/mfaPolicy.ts run beside it. Wrapping these in DI would buy ceremony and nothing else. mfaCrypto and apiKeyCrypto move together into common/crypto — they read the same ENCRYPTION_KEY, and the directory says so. services/ drops from 44 files to 36, 9,870 lines to 8,493. One trap worth recording: src/app-config and src/nest/app-config both exist. cookie.ts imported '../app-config' from services/, which resolved to the former; after the move the same string silently pointed at the latter, which has no readEnv. It is now explicit about which one it wants. Nothing else changes — no signatures, no behaviour, no tests rewritten beyond their import paths. --- server/src/db/migrations.ts | 2 +- server/src/middleware/auth.ts | 2 +- server/src/middleware/mfaPolicy.ts | 2 +- server/src/nest/admin/admin.service.ts | 6 +++--- server/src/nest/auth/auth-public.controller.ts | 2 +- server/src/nest/auth/auth.bridge.ts | 2 +- server/src/nest/auth/auth.controller.ts | 2 +- server/src/nest/auth/auth.helpers.ts | 2 +- server/src/nest/auth/auth.service.ts | 12 ++++++------ server/src/nest/auth/passkey.controller.ts | 2 +- server/src/nest/auth/passkey.service.ts | 2 +- server/src/nest/budget/budget.service.ts | 2 +- server/src/nest/collab/collab.service.ts | 2 +- .../src/nest/collections/collections.controller.ts | 2 +- server/src/{services => nest/common}/avatarUrl.ts | 0 .../src/{services => nest/common}/conflictResult.ts | 0 server/src/{services => nest/common}/cookie.ts | 4 ++-- .../{services => nest/common/crypto}/apiKeyCrypto.ts | 2 +- .../{services => nest/common/crypto}/mfaCrypto.ts | 2 +- server/src/{services => nest/common}/demo.ts | 0 .../src/{services => nest/common}/passwordPolicy.ts | 0 .../src/{services => nest/common}/timezoneService.ts | 0 server/src/nest/files/files.controller.ts | 2 +- server/src/nest/files/files.service.ts | 2 +- server/src/nest/maps/maps.service.ts | 2 +- .../src/nest/notifications/notifications.service.ts | 2 +- server/src/nest/oidc/oidc.controller.ts | 2 +- server/src/nest/oidc/oidc.service.ts | 4 ++-- server/src/nest/packing/packing.controller.ts | 2 +- server/src/nest/packing/packing.service.ts | 4 ++-- server/src/nest/places/places.controller.ts | 4 ++-- server/src/nest/places/places.service.ts | 2 +- .../nest/plugins/host/plugin-host-deps.factory.ts | 4 ++-- server/src/nest/plugins/plugin-oauth.service.ts | 2 +- server/src/nest/plugins/plugin-runtime.service.ts | 2 +- server/src/nest/plugins/plugins.service.ts | 2 +- server/src/nest/reservations/reservations.service.ts | 2 +- server/src/nest/settings/settings.service.ts | 2 +- server/src/nest/transit/transit-itinerary.helpers.ts | 2 +- server/src/nest/trips/trips.controller.ts | 2 +- server/src/nest/trips/trips.service.ts | 4 ++-- server/src/services/airtrail/airtrailMapper.ts | 2 +- server/src/services/airtrail/airtrailService.ts | 2 +- server/src/services/journeyService.ts | 2 +- server/src/services/llmConfig.ts | 2 +- server/src/services/memories/helpersService.ts | 2 +- server/src/services/memories/immichService.ts | 2 +- server/src/services/memories/photoResolverService.ts | 2 +- server/src/services/memories/synologyService.ts | 2 +- server/src/services/memories/unifiedService.ts | 2 +- server/src/services/notifications.ts | 2 +- server/src/services/unsplashService.ts | 2 +- server/tests/e2e/files.e2e.test.ts | 2 +- server/tests/e2e/trips.e2e.test.ts | 2 +- server/tests/helpers/factories.ts | 4 ++-- server/tests/integration/memories-synology.test.ts | 4 ++-- server/tests/unit/nest/admin.service.test.ts | 2 +- server/tests/unit/nest/auth-guard.test.ts | 4 ++-- server/tests/unit/nest/auth.controller.test.ts | 4 ++-- server/tests/unit/nest/auth.helpers.test.ts | 4 ++-- server/tests/unit/nest/auth.service.test.ts | 4 ++-- server/tests/unit/nest/collab.service.test.ts | 2 +- server/tests/unit/nest/files.controller.test.ts | 4 ++-- server/tests/unit/nest/maps.service.test.ts | 2 +- server/tests/unit/nest/notifications.service.test.ts | 2 +- server/tests/unit/nest/oidc.service.test.ts | 8 ++++---- server/tests/unit/nest/passkey.service.test.ts | 4 ++-- server/tests/unit/nest/settings.service.test.ts | 2 +- server/tests/unit/nest/trips.controller.test.ts | 2 +- .../unit/plugins/plugin-host-deps.factory.test.ts | 2 +- .../tests/unit/plugins/plugin-oauth.service.test.ts | 2 +- .../tests/unit/plugins/plugin-user-settings.test.ts | 2 +- server/tests/unit/services/apiKeyCrypto.test.ts | 2 +- server/tests/unit/services/avatarUrl.test.ts | 2 +- server/tests/unit/services/channelOverride.test.ts | 2 +- server/tests/unit/services/conflictUpdate.test.ts | 2 +- server/tests/unit/services/cookie.test.ts | 2 +- server/tests/unit/services/mfaCrypto.test.ts | 2 +- .../services/notificationPreferencesService.test.ts | 2 +- server/tests/unit/services/notifications.test.ts | 2 +- server/tests/unit/services/oauthService.test.ts | 2 +- server/tests/unit/services/passwordPolicy.test.ts | 2 +- server/tests/unit/services/timezoneService.test.ts | 2 +- server/tests/unit/services/unsplashService.test.ts | 2 +- 84 files changed, 103 insertions(+), 103 deletions(-) rename server/src/{services => nest/common}/avatarUrl.ts (100%) rename server/src/{services => nest/common}/conflictResult.ts (100%) rename server/src/{services => nest/common}/cookie.ts (98%) rename server/src/{services => nest/common/crypto}/apiKeyCrypto.ts (96%) rename server/src/{services => nest/common/crypto}/mfaCrypto.ts (94%) rename server/src/{services => nest/common}/demo.ts (100%) rename server/src/{services => nest/common}/passwordPolicy.ts (100%) rename server/src/{services => nest/common}/timezoneService.ts (100%) diff --git a/server/src/db/migrations.ts b/server/src/db/migrations.ts index bbf68c0d2..154ad0686 100644 --- a/server/src/db/migrations.ts +++ b/server/src/db/migrations.ts @@ -1,5 +1,5 @@ import { readEnv } from '../app-config'; -import { encrypt_api_key } from '../services/apiKeyCrypto'; +import { encrypt_api_key } from '../nest/common/crypto/apiKeyCrypto'; import Database from 'better-sqlite3'; import fs from 'fs'; diff --git a/server/src/middleware/auth.ts b/server/src/middleware/auth.ts index e5ab0482c..d485f4e80 100644 --- a/server/src/middleware/auth.ts +++ b/server/src/middleware/auth.ts @@ -5,7 +5,7 @@ import { db } from '../db/database'; import { JWT_SECRET } from '../config'; import { AuthRequest, OptionalAuthRequest, User } from '../types'; import { applyIdempotency } from './idempotency'; -import { isDemoEmail } from '../services/demo'; +import { isDemoEmail } from '../nest/common/demo'; export function extractToken(req: Request): string | null { // Prefer httpOnly cookie; fall back to Authorization: Bearer (MCP, API clients) diff --git a/server/src/middleware/mfaPolicy.ts b/server/src/middleware/mfaPolicy.ts index dad4a7b6c..2d09f9b90 100644 --- a/server/src/middleware/mfaPolicy.ts +++ b/server/src/middleware/mfaPolicy.ts @@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from 'express'; import { readEnv } from '../app-config'; import { db } from '../db/database'; import { extractToken, verifyJwtAndLoadUser } from './auth'; -import { DEMO_EMAILS } from '../services/demo'; +import { DEMO_EMAILS } from '../nest/common/demo'; /** Paths that never require MFA (public or pre-auth). */ export function isPublicApiPath(method: string, pathNoQuery: string): boolean { diff --git a/server/src/nest/admin/admin.service.ts b/server/src/nest/admin/admin.service.ts index f108b274c..ba2194b83 100644 --- a/server/src/nest/admin/admin.service.ts +++ b/server/src/nest/admin/admin.service.ts @@ -15,11 +15,11 @@ import { revokeUserSessions, revokeUserSessionsForClient } from '../../mcp/sessi import { invalidateMcpSessions } from '../../mcp'; import { emitUserDeleted } from '../../plugin-user-lifecycle'; import type { User, Addon } from '../../types'; -import { maybe_encrypt_api_key, decrypt_api_key } from '../../services/apiKeyCrypto'; -import { avatarUrl } from '../../services/avatarUrl'; +import { maybe_encrypt_api_key, decrypt_api_key } from '../common/crypto/apiKeyCrypto'; +import { avatarUrl } from '../common/avatarUrl'; import { prepareLlmAddonConfigForWrite, maskLlmAddonConfig } from '../../services/llmConfig'; import { getPhotoProviderConfig } from '../../services/memories/helpersService'; -import { validatePassword } from '../../services/passwordPolicy'; +import { validatePassword } from '../common/passwordPolicy'; import { deleteUserCompletely } from '../../services/userCleanupService'; import { getPreferencesMatrix, setAdminPreferences } from '../../services/notificationPreferencesService'; import { DatabaseService } from '../database/database.service'; diff --git a/server/src/nest/auth/auth-public.controller.ts b/server/src/nest/auth/auth-public.controller.ts index faf9d010b..2fae17540 100644 --- a/server/src/nest/auth/auth-public.controller.ts +++ b/server/src/nest/auth/auth-public.controller.ts @@ -6,7 +6,7 @@ import { RateLimitService } from '../common/rate-limit.service'; import { OptionalJwtGuard } from './optional-jwt.guard'; import { getClientIp } from '../audit/client-ip'; import { AuditService } from '../audit/audit.service'; -import { willDropSecureCookie } from '../../services/cookie'; +import { willDropSecureCookie } from '../common/cookie'; import type { User } from '../../types'; const WINDOW = 15 * 60 * 1000; diff --git a/server/src/nest/auth/auth.bridge.ts b/server/src/nest/auth/auth.bridge.ts index 12f2f4308..f712d6cd6 100644 --- a/server/src/nest/auth/auth.bridge.ts +++ b/server/src/nest/auth/auth.bridge.ts @@ -35,7 +35,7 @@ const auth = new AuthService( ); export { stripUserForClient } from './auth.helpers'; -export { avatarUrl } from '../../services/avatarUrl'; +export { avatarUrl } from '../common/avatarUrl'; export function isDemoUser(userId: number): boolean { return auth.isDemoUser(userId); diff --git a/server/src/nest/auth/auth.controller.ts b/server/src/nest/auth/auth.controller.ts index f44edb345..e5b0eb432 100644 --- a/server/src/nest/auth/auth.controller.ts +++ b/server/src/nest/auth/auth.controller.ts @@ -39,7 +39,7 @@ import { JwtAuthGuard } from './jwt-auth.guard'; import { CurrentUser } from './current-user.decorator'; import { getClientIp } from '../audit/client-ip'; import { AuditService } from '../audit/audit.service'; -import { isDemoEmail } from '../../services/demo'; +import { isDemoEmail } from '../common/demo'; import type { User } from '../../types'; const WINDOW = 15 * 60 * 1000; diff --git a/server/src/nest/auth/auth.helpers.ts b/server/src/nest/auth/auth.helpers.ts index 43cb5911f..fe646d357 100644 --- a/server/src/nest/auth/auth.helpers.ts +++ b/server/src/nest/auth/auth.helpers.ts @@ -3,7 +3,7 @@ import crypto from 'crypto'; import path from 'path'; import fs from 'fs'; import { User } from '../../types'; -import { decrypt_api_key } from '../../services/apiKeyCrypto'; +import { decrypt_api_key } from '../common/crypto/apiKeyCrypto'; /** * Pure half of the auth domain (no DB, no injected deps) — the DB half lives diff --git a/server/src/nest/auth/auth.service.ts b/server/src/nest/auth/auth.service.ts index ef225c70f..5e8a1bd62 100644 --- a/server/src/nest/auth/auth.service.ts +++ b/server/src/nest/auth/auth.service.ts @@ -13,9 +13,9 @@ import { DatabaseService } from '../database/database.service'; import { PermissionsService } from '../permissions/permissions.service'; import { AtlasService } from '../atlas/atlas.service'; import { getCountryFromCoords } from '../atlas/atlas-geo'; -import { validatePassword } from '../../services/passwordPolicy'; -import { encryptMfaSecret, decryptMfaSecret } from '../../services/mfaCrypto'; -import { decrypt_api_key, maybe_encrypt_api_key, encrypt_api_key } from '../../services/apiKeyCrypto'; +import { validatePassword } from '../common/passwordPolicy'; +import { encryptMfaSecret, decryptMfaSecret } from '../common/crypto/mfaCrypto'; +import { decrypt_api_key, maybe_encrypt_api_key, encrypt_api_key } from '../common/crypto/apiKeyCrypto'; import { createEphemeralToken } from '../../services/ephemeralTokens'; // Import from sessionManager directly, NOT the ../../mcp barrel: the barrel pulls // the whole tools fan-out (and via the domain bridges, the Nest services) into @@ -27,11 +27,11 @@ import { emitUserDeleted } from '../../plugin-user-lifecycle'; import { getFlightDistanceKm } from '../../services/distanceService'; import { verifyJwtAndLoadUser } from '../../middleware/auth'; import { User } from '../../types'; -import { DEMO_EMAIL_PRIMARY, isDemoEmail } from '../../services/demo'; -import { avatarUrl } from '../../services/avatarUrl'; +import { DEMO_EMAIL_PRIMARY, isDemoEmail } from '../common/demo'; +import { avatarUrl } from '../common/avatarUrl'; import { joinTripAsMember } from '../../services/tripMembership'; import { isPasskeyConfigured } from '../../services/webauthnConfig'; -import { setAuthCookie, clearAuthCookie } from '../../services/cookie'; +import { setAuthCookie, clearAuthCookie } from '../common/cookie'; import { sendPasswordResetEmail } from '../../services/notifications'; import { getAppUrl } from '../../app-config'; import { diff --git a/server/src/nest/auth/passkey.controller.ts b/server/src/nest/auth/passkey.controller.ts index 4993ff77f..f2b1982dd 100644 --- a/server/src/nest/auth/passkey.controller.ts +++ b/server/src/nest/auth/passkey.controller.ts @@ -4,7 +4,7 @@ import { RateLimitService } from '../common/rate-limit.service'; import { JwtAuthGuard } from './jwt-auth.guard'; import { PasskeyEnabledGuard } from './passkey-enabled.guard'; import { CurrentUser } from './current-user.decorator'; -import { setAuthCookie } from '../../services/cookie'; +import { setAuthCookie } from '../common/cookie'; import { getClientIp } from '../audit/client-ip'; import { AuditService } from '../audit/audit.service'; import { PasskeyService } from './passkey.service'; diff --git a/server/src/nest/auth/passkey.service.ts b/server/src/nest/auth/passkey.service.ts index 60ce165e2..ea944599a 100644 --- a/server/src/nest/auth/passkey.service.ts +++ b/server/src/nest/auth/passkey.service.ts @@ -8,7 +8,7 @@ import { type AuthenticatorTransportFuture, } from '@simplewebauthn/server'; import { resolveWebauthnConfig } from '../../services/webauthnConfig'; -import { avatarUrl } from '../../services/avatarUrl'; +import { avatarUrl } from '../common/avatarUrl'; import { stripUserForClient } from './auth.helpers'; import { AuthService } from './auth.service'; import { DatabaseService } from '../database/database.service'; diff --git a/server/src/nest/budget/budget.service.ts b/server/src/nest/budget/budget.service.ts index 139fa7db1..3a97ba961 100644 --- a/server/src/nest/budget/budget.service.ts +++ b/server/src/nest/budget/budget.service.ts @@ -4,7 +4,7 @@ import type { TrekWsPayload, TrekWsTripEventName } from '@trek/shared'; import { RealtimeService } from '../realtime/realtime.service'; import { PermissionsService } from '../permissions/permissions.service'; import { verifyTripAccess } from '../../services/tripAccess'; -import { avatarUrl } from '../../services/avatarUrl'; +import { avatarUrl } from '../common/avatarUrl'; import type { User, BudgetItem, BudgetItemMember, BudgetItemPayer } from '../../types'; import { ExchangeRatesService } from './exchange-rates.service'; diff --git a/server/src/nest/collab/collab.service.ts b/server/src/nest/collab/collab.service.ts index cf6a4d17b..32bb005b3 100644 --- a/server/src/nest/collab/collab.service.ts +++ b/server/src/nest/collab/collab.service.ts @@ -6,7 +6,7 @@ import type { TrekWsPayload, TrekWsTripEventName } from '@trek/shared'; import { RealtimeService } from '../realtime/realtime.service'; import { PermissionsService } from '../permissions/permissions.service'; import { verifyTripAccess } from '../../services/tripAccess'; -import { avatarUrl } from '../../services/avatarUrl'; +import { avatarUrl } from '../common/avatarUrl'; import { checkSsrf, createPinnedDispatcher } from '../../utils/ssrfGuard'; import type { CollabNote, CollabPoll, CollabMessage, TripFile, User } from '../../types'; diff --git a/server/src/nest/collections/collections.controller.ts b/server/src/nest/collections/collections.controller.ts index 45d23955c..02a704159 100644 --- a/server/src/nest/collections/collections.controller.ts +++ b/server/src/nest/collections/collections.controller.ts @@ -29,7 +29,7 @@ import { JwtAuthGuard } from '../auth/jwt-auth.guard'; import { CurrentUser } from '../auth/current-user.decorator'; import { PLACE_IMAGE_UPLOAD } from '../common/place-image-upload'; import { placeImageUrl } from '../../services/placeImage'; -import { isDemoEmail } from '../../services/demo'; +import { isDemoEmail } from '../common/demo'; import { CollectionCreateDto, CollectionUpdateDto, diff --git a/server/src/services/avatarUrl.ts b/server/src/nest/common/avatarUrl.ts similarity index 100% rename from server/src/services/avatarUrl.ts rename to server/src/nest/common/avatarUrl.ts diff --git a/server/src/services/conflictResult.ts b/server/src/nest/common/conflictResult.ts similarity index 100% rename from server/src/services/conflictResult.ts rename to server/src/nest/common/conflictResult.ts diff --git a/server/src/services/cookie.ts b/server/src/nest/common/cookie.ts similarity index 98% rename from server/src/services/cookie.ts rename to server/src/nest/common/cookie.ts index abb586c2b..76ce00226 100644 --- a/server/src/services/cookie.ts +++ b/server/src/nest/common/cookie.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express'; -import { readEnv } from '../app-config'; -import { SESSION_DURATION_MS, SESSION_DURATION_REMEMBER_MS } from '../config'; +import { readEnv } from '../../app-config'; +import { SESSION_DURATION_MS, SESSION_DURATION_REMEMBER_MS } from '../../config'; const COOKIE_NAME = 'trek_session'; diff --git a/server/src/services/apiKeyCrypto.ts b/server/src/nest/common/crypto/apiKeyCrypto.ts similarity index 96% rename from server/src/services/apiKeyCrypto.ts rename to server/src/nest/common/crypto/apiKeyCrypto.ts index 6dc0b0bdf..96eccea5c 100644 --- a/server/src/services/apiKeyCrypto.ts +++ b/server/src/nest/common/crypto/apiKeyCrypto.ts @@ -1,5 +1,5 @@ import * as crypto from 'node:crypto'; -import { ENCRYPTION_KEY } from '../config'; +import { ENCRYPTION_KEY } from '../../../config'; const ENCRYPTED_PREFIX = 'enc:v1:'; diff --git a/server/src/services/mfaCrypto.ts b/server/src/nest/common/crypto/mfaCrypto.ts similarity index 94% rename from server/src/services/mfaCrypto.ts rename to server/src/nest/common/crypto/mfaCrypto.ts index 2a64743ff..214933b9f 100644 --- a/server/src/services/mfaCrypto.ts +++ b/server/src/nest/common/crypto/mfaCrypto.ts @@ -1,5 +1,5 @@ import crypto from 'crypto'; -import { ENCRYPTION_KEY } from '../config'; +import { ENCRYPTION_KEY } from '../../../config'; function getKey(): Buffer { return crypto.createHash('sha256').update(`${ENCRYPTION_KEY}:mfa:v1`).digest(); diff --git a/server/src/services/demo.ts b/server/src/nest/common/demo.ts similarity index 100% rename from server/src/services/demo.ts rename to server/src/nest/common/demo.ts diff --git a/server/src/services/passwordPolicy.ts b/server/src/nest/common/passwordPolicy.ts similarity index 100% rename from server/src/services/passwordPolicy.ts rename to server/src/nest/common/passwordPolicy.ts diff --git a/server/src/services/timezoneService.ts b/server/src/nest/common/timezoneService.ts similarity index 100% rename from server/src/services/timezoneService.ts rename to server/src/nest/common/timezoneService.ts diff --git a/server/src/nest/files/files.controller.ts b/server/src/nest/files/files.controller.ts index 372348062..c637d722d 100644 --- a/server/src/nest/files/files.controller.ts +++ b/server/src/nest/files/files.controller.ts @@ -28,7 +28,7 @@ import { CurrentUser } from '../auth/current-user.decorator'; import { MAX_FILE_SIZE, MAX_VIDEO_SIZE, BLOCKED_EXTENSIONS, filesDir, isVideoExtension } from './files.constants'; import { getAllowedExtensions } from './files.bridge'; import { FileUploadDto, FileUpdateDto, FileLinkDto } from './files.dto'; -import { isDemoEmail } from '../../services/demo'; +import { isDemoEmail } from '../common/demo'; const UPLOAD = { storage: diskStorage({ diff --git a/server/src/nest/files/files.service.ts b/server/src/nest/files/files.service.ts index 787cc40ab..f58cc71a2 100644 --- a/server/src/nest/files/files.service.ts +++ b/server/src/nest/files/files.service.ts @@ -5,7 +5,7 @@ import type { Request } from 'express'; import type { TrekWsPayload, TrekWsTripEventName } from '@trek/shared'; import { RealtimeService } from '../realtime/realtime.service'; import { PermissionsService } from '../permissions/permissions.service'; -import { avatarUrl } from '../../services/avatarUrl'; +import { avatarUrl } from '../common/avatarUrl'; import { consumeEphemeralToken } from '../../services/ephemeralTokens'; import { verifyJwtAndLoadUser } from '../../middleware/auth'; import type { User, TripFile } from '../../types'; diff --git a/server/src/nest/maps/maps.service.ts b/server/src/nest/maps/maps.service.ts index ba1d172d6..a91f9bdd0 100644 --- a/server/src/nest/maps/maps.service.ts +++ b/server/src/nest/maps/maps.service.ts @@ -9,7 +9,7 @@ import type { } from '@trek/shared'; import { readEnv, getAppUrl } from '../../app-config'; import { safeFetchFollow, SsrfBlockedError } from '../../utils/ssrfGuard'; -import { decrypt_api_key } from '../../services/apiKeyCrypto'; +import { decrypt_api_key } from '../common/crypto/apiKeyCrypto'; // ── Photo cache (disk-backed) ──────────────────────────────────────────────── import * as placePhotoCache from '../../services/placePhotoCache'; import { DatabaseService } from '../database/database.service'; diff --git a/server/src/nest/notifications/notifications.service.ts b/server/src/nest/notifications/notifications.service.ts index 66dbf7f16..99542981c 100644 --- a/server/src/nest/notifications/notifications.service.ts +++ b/server/src/nest/notifications/notifications.service.ts @@ -25,7 +25,7 @@ import { } from '../../services/notificationPreferencesService'; import { getChannel, listChannels, type ChannelMessage, type ExternalChannel } from '../../services/notifications/channelRegistry'; import { getAction } from '../../services/inAppNotificationActions'; -import { avatarUrl } from '../../services/avatarUrl'; +import { avatarUrl } from '../common/avatarUrl'; import { DatabaseService } from '../database/database.service'; import { RealtimeService } from '../realtime/realtime.service'; diff --git a/server/src/nest/oidc/oidc.controller.ts b/server/src/nest/oidc/oidc.controller.ts index da14496d3..bae630917 100644 --- a/server/src/nest/oidc/oidc.controller.ts +++ b/server/src/nest/oidc/oidc.controller.ts @@ -2,7 +2,7 @@ import { Controller, Get, Query, Req, Res } from '@nestjs/common'; import type { Request, Response } from 'express'; import { readEnv } from '../../app-config'; import { OidcService, OIDC_STATE_TTL_MS } from './oidc.service'; -import { cookieOptions } from '../../services/cookie'; +import { cookieOptions } from '../common/cookie'; const OIDC_STATE_COOKIE = 'trek_oidc_state'; diff --git a/server/src/nest/oidc/oidc.service.ts b/server/src/nest/oidc/oidc.service.ts index 9fa964106..02f1a5bb5 100644 --- a/server/src/nest/oidc/oidc.service.ts +++ b/server/src/nest/oidc/oidc.service.ts @@ -8,9 +8,9 @@ import type { Request, Response } from 'express'; import { readEnv, getAppUrl } from '../../app-config'; import { JWT_SECRET, SESSION_DURATION_SECONDS } from '../../config'; import { User } from '../../types'; -import { decrypt_api_key } from '../../services/apiKeyCrypto'; +import { decrypt_api_key } from '../common/crypto/apiKeyCrypto'; import { joinTripAsMember } from '../../services/tripMembership'; -import { setAuthCookie } from '../../services/cookie'; +import { setAuthCookie } from '../common/cookie'; import { AuthService } from '../auth/auth.service'; import { DatabaseService } from '../database/database.service'; diff --git a/server/src/nest/packing/packing.controller.ts b/server/src/nest/packing/packing.controller.ts index 35a66fb6d..fc2f92259 100644 --- a/server/src/nest/packing/packing.controller.ts +++ b/server/src/nest/packing/packing.controller.ts @@ -14,7 +14,7 @@ import { import type { TrekWsPayload, TrekWsTripEventName } from '@trek/shared'; import type { User } from '../../types'; import { PackingService } from './packing.service'; -import { isUpdateConflict } from '../../services/conflictResult'; +import { isUpdateConflict } from '../common/conflictResult'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; import { CurrentUser } from '../auth/current-user.decorator'; import { diff --git a/server/src/nest/packing/packing.service.ts b/server/src/nest/packing/packing.service.ts index 8bd60ff65..b6fb013c9 100644 --- a/server/src/nest/packing/packing.service.ts +++ b/server/src/nest/packing/packing.service.ts @@ -3,8 +3,8 @@ import type { TrekWsPayload, TrekWsTripEventName } from '@trek/shared'; import { RealtimeService } from '../realtime/realtime.service'; import { PermissionsService } from '../permissions/permissions.service'; import { verifyTripAccess } from '../../services/tripAccess'; -import { avatarUrl } from '../../services/avatarUrl'; -import type { UpdateConflict } from '../../services/conflictResult'; +import { avatarUrl } from '../common/avatarUrl'; +import type { UpdateConflict } from '../common/conflictResult'; import type { User } from '../../types'; import { DatabaseService } from '../database/database.service'; diff --git a/server/src/nest/places/places.controller.ts b/server/src/nest/places/places.controller.ts index e1b3cb0ff..79761a493 100644 --- a/server/src/nest/places/places.controller.ts +++ b/server/src/nest/places/places.controller.ts @@ -20,12 +20,12 @@ import { hexColorSchema } from '@trek/shared'; import { readEnv } from '../../app-config'; import type { User } from '../../types'; import { PlacesService } from './places.service'; -import { isUpdateConflict } from '../../services/conflictResult'; +import { isUpdateConflict } from '../common/conflictResult'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; import { CurrentUser } from '../auth/current-user.decorator'; import { PLACE_IMAGE_UPLOAD } from '../common/place-image-upload'; import { placeImageUrl } from '../../services/placeImage'; -import { isDemoEmail } from '../../services/demo'; +import { isDemoEmail } from '../common/demo'; import { PlaceBulkDeleteDto, PlaceBulkUpdateDto, diff --git a/server/src/nest/places/places.service.ts b/server/src/nest/places/places.service.ts index 160b99543..5b6d45129 100644 --- a/server/src/nest/places/places.service.ts +++ b/server/src/nest/places/places.service.ts @@ -19,7 +19,7 @@ import { resolveCategoryIdForFolder, } from '../../services/kmlImport'; import { searchUnsplashPhotos, getUnsplashKey } from '../../services/unsplashService'; -import { type UpdateConflict, isUpdateConflict } from '../../services/conflictResult'; +import { type UpdateConflict, isUpdateConflict } from '../common/conflictResult'; import { reclaimPlaceImage } from '../../services/placeImage'; import { onPlaceCreated, onPlaceUpdated, onPlaceDeleted } from '../../services/journeyService'; import { diff --git a/server/src/nest/plugins/host/plugin-host-deps.factory.ts b/server/src/nest/plugins/host/plugin-host-deps.factory.ts index a92c7b0f0..7a322af33 100644 --- a/server/src/nest/plugins/host/plugin-host-deps.factory.ts +++ b/server/src/nest/plugins/host/plugin-host-deps.factory.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import type { TrekWsPayload, TrekWsTripEventName } from '@trek/shared'; import { readEnv } from '../../../app-config'; import { RealtimeService } from '../../realtime/realtime.service'; -import { isUpdateConflict } from '../../../services/conflictResult'; +import { isUpdateConflict } from '../../common/conflictResult'; import { getWeather } from '../../../services/weatherService'; import { BLOCKED_EXTENSIONS, filesDir } from '../../files/files.constants'; import { joinTripAsMember } from '../../../services/tripMembership'; @@ -17,7 +17,7 @@ import { PermissionsService } from '../../permissions/permissions.service'; import { TripsService, NotFoundError, ValidationError } from '../../trips/trips.service'; import { PlacesService, type PlaceCreateInput, type PlaceUpdateInput } from '../../places/places.service'; import { AddonsService } from '../../addons/addons.service'; -import { isDemoEmail } from '../../../services/demo'; +import { isDemoEmail } from '../../common/demo'; import { ADDON_IDS } from '../../../addons'; import { listJourneys, listEntries as listJournalEntriesSvc, createEntry as createJournalEntrySvc, updateEntry as updateJournalEntrySvc, deleteEntry as deleteJournalEntrySvc, createJourney as createJourneySvc, deleteJourney as deleteJourneySvc, onPlaceCreated, onPlaceUpdated, onPlaceDeleted } from '../../../services/journeyService'; import { AtlasService } from '../../atlas/atlas.service'; diff --git a/server/src/nest/plugins/plugin-oauth.service.ts b/server/src/nest/plugins/plugin-oauth.service.ts index bba838a46..3bca14715 100644 --- a/server/src/nest/plugins/plugin-oauth.service.ts +++ b/server/src/nest/plugins/plugin-oauth.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import crypto from 'node:crypto'; import { DatabaseService } from '../database/database.service'; -import { encrypt_api_key, decrypt_api_key } from '../../services/apiKeyCrypto'; +import { encrypt_api_key, decrypt_api_key } from '../common/crypto/apiKeyCrypto'; import { getAppUrl } from '../../app-config'; import { isPrivateIp } from './install/safe-fetch'; import { safeFetchLlm } from '../../utils/ssrfGuard'; diff --git a/server/src/nest/plugins/plugin-runtime.service.ts b/server/src/nest/plugins/plugin-runtime.service.ts index aeeb84f1a..3be09f5c2 100644 --- a/server/src/nest/plugins/plugin-runtime.service.ts +++ b/server/src/nest/plugins/plugin-runtime.service.ts @@ -9,7 +9,7 @@ import { readUserSettingsDecrypted, hasRequiredUserSettings } from './plugins.se import { PLUGIN_CHANNEL_EVENTS } from './install/manifest'; import { stripEmoji } from './text-sanitize'; import { applyStagedPluginTrees, setStagedRestoreApplier } from './plugin-backup'; -import { decrypt_api_key } from '../../services/apiKeyCrypto'; +import { decrypt_api_key } from '../common/crypto/apiKeyCrypto'; import { PluginSupervisor, type PluginRouteInfo } from './supervisor/plugin-supervisor'; import fs from 'node:fs'; import path from 'node:path'; diff --git a/server/src/nest/plugins/plugins.service.ts b/server/src/nest/plugins/plugins.service.ts index 5544ca49a..b19e355b7 100644 --- a/server/src/nest/plugins/plugins.service.ts +++ b/server/src/nest/plugins/plugins.service.ts @@ -3,7 +3,7 @@ import { db } from '../../db/database'; import { DatabaseService } from '../database/database.service'; import { pluginsEnabled } from './kill-switch'; import { devLinkEnabled } from './dev-link'; -import { maybe_encrypt_api_key, decrypt_api_key } from '../../services/apiKeyCrypto'; +import { maybe_encrypt_api_key, decrypt_api_key } from '../common/crypto/apiKeyCrypto'; import { readAudit } from './host/plugin-audit'; import { keyFingerprint } from './signature-status'; import { pluginBudgetUsage } from './host/plugin-host-state'; diff --git a/server/src/nest/reservations/reservations.service.ts b/server/src/nest/reservations/reservations.service.ts index 1c4867122..99c55c9c2 100644 --- a/server/src/nest/reservations/reservations.service.ts +++ b/server/src/nest/reservations/reservations.service.ts @@ -4,7 +4,7 @@ import type { TrekWsPayload, TrekWsTripEventName } from '@trek/shared'; import { RealtimeService } from '../realtime/realtime.service'; import { PermissionsService } from '../permissions/permissions.service'; import { verifyTripAccess } from '../../services/tripAccess'; -import { avatarUrl } from '../../services/avatarUrl'; +import { avatarUrl } from '../common/avatarUrl'; import type { Reservation, User } from '../../types'; import { BudgetService } from '../budget/budget.service'; import { typeToCostCategory } from '@trek/shared'; diff --git a/server/src/nest/settings/settings.service.ts b/server/src/nest/settings/settings.service.ts index bab2f165e..acd8c9140 100644 --- a/server/src/nest/settings/settings.service.ts +++ b/server/src/nest/settings/settings.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { DatabaseService } from '../database/database.service'; -import { decrypt_api_key, maybe_encrypt_api_key } from '../../services/apiKeyCrypto'; +import { decrypt_api_key, maybe_encrypt_api_key } from '../common/crypto/apiKeyCrypto'; import { MASKED_SETTING_VALUE, normalizeAppearance } from '@trek/shared'; const ENCRYPTED_SETTING_KEYS = new Set(['webhook_url', 'ntfy_token', 'mapbox_access_token', 'llm_api_key']); diff --git a/server/src/nest/transit/transit-itinerary.helpers.ts b/server/src/nest/transit/transit-itinerary.helpers.ts index b3a0e44e6..bb75fe3b2 100644 --- a/server/src/nest/transit/transit-itinerary.helpers.ts +++ b/server/src/nest/transit/transit-itinerary.helpers.ts @@ -9,7 +9,7 @@ */ import { haversineKm } from '../../services/distanceService'; import type { EndpointInput } from '../reservations/reservations.service'; -import { localParts, resolveTimeZone } from '../../services/timezoneService'; +import { localParts, resolveTimeZone } from '../common/timezoneService'; import { deriveTransitStats, type TransitItinerary, type TransitLeg } from './transit.helpers'; import { z } from 'zod'; diff --git a/server/src/nest/trips/trips.controller.ts b/server/src/nest/trips/trips.controller.ts index 3033e0d74..51c2694c6 100644 --- a/server/src/nest/trips/trips.controller.ts +++ b/server/src/nest/trips/trips.controller.ts @@ -30,7 +30,7 @@ import { CurrentUser } from '../auth/current-user.decorator'; import { getClientIp } from '../audit/client-ip'; import { logInfo } from '../audit/audit-log.logger'; import { AuditService } from '../audit/audit.service'; -import { isDemoEmail } from '../../services/demo'; +import { isDemoEmail } from '../common/demo'; import { NotFoundError, ValidationError } from './trips.service'; import { TripCreateDto, TripUpdateDto, TripCopyDto, TripAddMemberDto, TripTransferOwnershipDto, TripCreateGuestDto, TripRenameGuestDto } from './trips.dto'; import { saveUnsplashCover, isUnsplashCoverUrl } from '../../services/unsplashService'; diff --git a/server/src/nest/trips/trips.service.ts b/server/src/nest/trips/trips.service.ts index b28812a96..2ddf230dd 100644 --- a/server/src/nest/trips/trips.service.ts +++ b/server/src/nest/trips/trips.service.ts @@ -7,10 +7,10 @@ import type { TrekWsPayload, TrekWsTripEventName } from '@trek/shared'; import { RealtimeService } from '../realtime/realtime.service'; import { PermissionsService } from '../permissions/permissions.service'; import type { Trip, User } from '../../types'; -import { avatarUrl } from '../../services/avatarUrl'; +import { avatarUrl } from '../common/avatarUrl'; import { erasePluginUserData } from '../../services/userCleanupService'; import { emitUserDeleted } from '../../plugin-user-lifecycle'; -import { resolveTimeZone } from '../../services/timezoneService'; +import { resolveTimeZone } from '../common/timezoneService'; import { PlacesService } from '../places/places.service'; import { DaysService, addDays } from '../days/days.service'; import { PackingService } from '../packing/packing.service'; diff --git a/server/src/services/airtrail/airtrailMapper.ts b/server/src/services/airtrail/airtrailMapper.ts index ede21172d..4a9c32df2 100644 --- a/server/src/services/airtrail/airtrailMapper.ts +++ b/server/src/services/airtrail/airtrailMapper.ts @@ -1,4 +1,4 @@ -import { localParts } from '../timezoneService'; +import { localParts } from '../../nest/common/timezoneService'; import type { AirtrailAirport, AirtrailFlightRaw, AirtrailNamedCode } from './airtrailClient'; import type { AirtrailFlight } from '@trek/shared'; diff --git a/server/src/services/airtrail/airtrailService.ts b/server/src/services/airtrail/airtrailService.ts index b8d2ebafd..4f5ab4194 100644 --- a/server/src/services/airtrail/airtrailService.ts +++ b/server/src/services/airtrail/airtrailService.ts @@ -1,6 +1,6 @@ import type { AirtrailFlight } from '@trek/shared'; import { db } from '../../db/database'; -import { maybe_encrypt_api_key, decrypt_api_key } from '../apiKeyCrypto'; +import { maybe_encrypt_api_key, decrypt_api_key } from '../../nest/common/crypto/apiKeyCrypto'; import { checkSsrf } from '../../utils/ssrfGuard'; import { writeAudit } from '../../nest/audit/audit.bridge'; import { AirtrailAuthError, AirtrailCreds, AirtrailRequestError, listFlights } from './airtrailClient'; diff --git a/server/src/services/journeyService.ts b/server/src/services/journeyService.ts index 23428b607..c845c37fd 100644 --- a/server/src/services/journeyService.ts +++ b/server/src/services/journeyService.ts @@ -1,5 +1,5 @@ import { db, canAccessTrip } from '../db/database'; -import { avatarUrl } from './avatarUrl'; +import { avatarUrl } from '../nest/common/avatarUrl'; import type { Journey, JourneyEntry, JourneyPhoto, JourneyContributor } from '../types'; import { broadcastToUser } from '../websocket'; import { diff --git a/server/src/services/llmConfig.ts b/server/src/services/llmConfig.ts index a34960bb0..6cb290b50 100644 --- a/server/src/services/llmConfig.ts +++ b/server/src/services/llmConfig.ts @@ -1,4 +1,4 @@ -import { maybe_encrypt_api_key, decrypt_api_key } from './apiKeyCrypto'; +import { maybe_encrypt_api_key, decrypt_api_key } from '../nest/common/crypto/apiKeyCrypto'; /** * Shared types + helpers for the `llm_parsing` addon configuration. diff --git a/server/src/services/memories/helpersService.ts b/server/src/services/memories/helpersService.ts index 7a8a16a62..6ce0dd412 100644 --- a/server/src/services/memories/helpersService.ts +++ b/server/src/services/memories/helpersService.ts @@ -3,7 +3,7 @@ import { Readable } from 'node:stream'; import { Response } from 'express'; import { canAccessTrip, db } from "../../db/database"; import { safeFetch, SsrfBlockedError, type SafeFetchOptions } from '../../utils/ssrfGuard'; -import { decrypt_api_key } from '../apiKeyCrypto'; +import { decrypt_api_key } from '../../nest/common/crypto/apiKeyCrypto'; // helpers for handling return types diff --git a/server/src/services/memories/immichService.ts b/server/src/services/memories/immichService.ts index 9e797e1b0..717d3c830 100644 --- a/server/src/services/memories/immichService.ts +++ b/server/src/services/memories/immichService.ts @@ -1,6 +1,6 @@ import { Response } from 'express'; import { db } from '../../db/database'; -import { maybe_encrypt_api_key, decrypt_api_key } from '../apiKeyCrypto'; +import { maybe_encrypt_api_key, decrypt_api_key } from '../../nest/common/crypto/apiKeyCrypto'; import { checkSsrf, safeFetch } from '../../utils/ssrfGuard'; import { writeAudit } from '../../nest/audit/audit.bridge'; import { addTripPhotos} from './unifiedService'; diff --git a/server/src/services/memories/photoResolverService.ts b/server/src/services/memories/photoResolverService.ts index 6d5c8222c..05750cdfa 100644 --- a/server/src/services/memories/photoResolverService.ts +++ b/server/src/services/memories/photoResolverService.ts @@ -7,7 +7,7 @@ import { streamImmichAsset, fetchImmichThumbnailBytes, getAssetInfo as getImmich import { streamSynologyAsset, fetchSynologyThumbnailBytes, getSynologyAssetInfo } from './synologyService'; import type { ServiceResult, AssetInfo } from './helpersService'; import { fail, success } from './helpersService'; -import { encrypt_api_key, decrypt_api_key } from '../apiKeyCrypto'; +import { encrypt_api_key, decrypt_api_key } from '../../nest/common/crypto/apiKeyCrypto'; import * as photoCache from './trekPhotoCache'; import { ensureLocalThumbnail } from './thumbnailService'; diff --git a/server/src/services/memories/synologyService.ts b/server/src/services/memories/synologyService.ts index f0972ee5c..39dbf1636 100644 --- a/server/src/services/memories/synologyService.ts +++ b/server/src/services/memories/synologyService.ts @@ -1,7 +1,7 @@ import { Response } from 'express'; import { db } from '../../db/database'; -import { decrypt_api_key, encrypt_api_key, maybe_encrypt_api_key } from '../apiKeyCrypto'; +import { decrypt_api_key, encrypt_api_key, maybe_encrypt_api_key } from '../../nest/common/crypto/apiKeyCrypto'; import { safeFetch, SsrfBlockedError, checkSsrf } from '../../utils/ssrfGuard'; import { addTripPhotos } from './unifiedService'; import { diff --git a/server/src/services/memories/unifiedService.ts b/server/src/services/memories/unifiedService.ts index 821223288..668ed1a0e 100644 --- a/server/src/services/memories/unifiedService.ts +++ b/server/src/services/memories/unifiedService.ts @@ -9,7 +9,7 @@ import { Selection, } from './helpersService'; import { getOrCreateTrekPhoto, deleteTrekPhotoIfOrphan } from './photoResolverService'; -import { encrypt_api_key } from '../apiKeyCrypto'; +import { encrypt_api_key } from '../../nest/common/crypto/apiKeyCrypto'; function _providers(): Array<{id: string; enabled: boolean}> { diff --git a/server/src/services/notifications.ts b/server/src/services/notifications.ts index d31dc5313..e0eb63fc8 100644 --- a/server/src/services/notifications.ts +++ b/server/src/services/notifications.ts @@ -1,7 +1,7 @@ import { getAppUrl, readEnv } from '../app-config'; import { db } from '../db/database'; import { checkSsrf, createPinnedDispatcher } from '../utils/ssrfGuard'; -import { decrypt_api_key } from './apiKeyCrypto'; +import { decrypt_api_key } from '../nest/common/crypto/apiKeyCrypto'; import { logInfo, logDebug, logError } from '../nest/audit/audit-log.logger'; // ── Types ────────────────────────────────────────────────────────────────── diff --git a/server/src/services/unsplashService.ts b/server/src/services/unsplashService.ts index d1062b0a7..c5b2ae31c 100644 --- a/server/src/services/unsplashService.ts +++ b/server/src/services/unsplashService.ts @@ -4,7 +4,7 @@ import { v4 as uuidv4 } from 'uuid'; import { readEnv } from '../app-config'; import { safeFetch } from '../utils/ssrfGuard'; import { db } from '../db/database'; -import { decrypt_api_key } from './apiKeyCrypto'; +import { decrypt_api_key } from '../nest/common/crypto/apiKeyCrypto'; interface UnsplashSearchResponse { results?: { diff --git a/server/tests/e2e/files.e2e.test.ts b/server/tests/e2e/files.e2e.test.ts index 7690e20f1..f323012ab 100644 --- a/server/tests/e2e/files.e2e.test.ts +++ b/server/tests/e2e/files.e2e.test.ts @@ -45,7 +45,7 @@ vi.mock('../../src/db/database', () => ({ db, canAccessTrip, isOwner: vi.fn(() => true), getPlaceWithTags: vi.fn(), closeDb: () => {}, reinitialize: () => {}, })); vi.mock('../../src/websocket', () => ({ broadcast: vi.fn() })); -vi.mock('../../src/services/demo', () => ({ isDemoEmail: vi.fn(() => false) })); +vi.mock('../../src/nest/common/demo', () => ({ isDemoEmail: vi.fn(() => false) })); import { PermissionsService } from '../../src/nest/permissions/permissions.service'; diff --git a/server/tests/e2e/trips.e2e.test.ts b/server/tests/e2e/trips.e2e.test.ts index 8fccce0a1..6e435161a 100644 --- a/server/tests/e2e/trips.e2e.test.ts +++ b/server/tests/e2e/trips.e2e.test.ts @@ -108,7 +108,7 @@ vi.mock('../../src/nest/notifications/notifications.bridge', () => ({ send: vi.f // The audit domain is DI-native now: writeAudit runs for real against the temp // db's audit_log table; only the file logger is silenced. vi.mock('../../src/nest/audit/audit-log.logger', () => ({ LOG_LEVEL: 'error', logInfo: vi.fn(), logDebug: vi.fn(), logError: vi.fn(), logWarn: vi.fn() })); -vi.mock('../../src/services/demo', () => ({ isDemoEmail: vi.fn(() => false) })); +vi.mock('../../src/nest/common/demo', () => ({ isDemoEmail: vi.fn(() => false) })); import { PermissionsService } from '../../src/nest/permissions/permissions.service'; diff --git a/server/tests/helpers/factories.ts b/server/tests/helpers/factories.ts index 7acb2c521..a2f3704f8 100644 --- a/server/tests/helpers/factories.ts +++ b/server/tests/helpers/factories.ts @@ -6,8 +6,8 @@ import Database from 'better-sqlite3'; import bcrypt from 'bcryptjs'; -import { encryptMfaSecret } from '../../src/services/mfaCrypto'; -import { encrypt_api_key } from '../../src/services/apiKeyCrypto'; +import { encryptMfaSecret } from '../../src/nest/common/crypto/mfaCrypto'; +import { encrypt_api_key } from '../../src/nest/common/crypto/apiKeyCrypto'; let _userSeq = 0; let _tripSeq = 0; diff --git a/server/tests/integration/memories-synology.test.ts b/server/tests/integration/memories-synology.test.ts index cff8e932d..befa14368 100644 --- a/server/tests/integration/memories-synology.test.ts +++ b/server/tests/integration/memories-synology.test.ts @@ -704,7 +704,7 @@ describe('Synology auth checks', () => { // ── Album sync ──────────────────────────────────────────────────────────────── import { addAlbumLink } from '../helpers/factories'; -import { encrypt_api_key } from '../../src/services/apiKeyCrypto'; +import { encrypt_api_key } from '../../src/nest/common/crypto/apiKeyCrypto'; describe('Synology syncSynologyAlbumLink', () => { it('SYNO-050 — POST sync happy path: trip owner with album link saves photos to DB', async () => { @@ -1187,7 +1187,7 @@ describe('Synology SSRF blocked error handling', () => { // ── Passphrase persistence fixes ───────────────────────────────────────────── import { getOrCreateTrekPhoto, deleteTrekPhotoIfOrphan } from '../../src/services/memories/photoResolverService'; -import { decrypt_api_key } from '../../src/services/apiKeyCrypto'; +import { decrypt_api_key } from '../../src/nest/common/crypto/apiKeyCrypto'; describe('trek_photos passphrase healing (SYNO-090)', () => { it('SYNO-090 — getOrCreateTrekPhoto overwrites an existing bad passphrase when a new one is supplied', () => { diff --git a/server/tests/unit/nest/admin.service.test.ts b/server/tests/unit/nest/admin.service.test.ts index f295bb5b8..03731278f 100644 --- a/server/tests/unit/nest/admin.service.test.ts +++ b/server/tests/unit/nest/admin.service.test.ts @@ -35,7 +35,7 @@ vi.mock('../../../src/config', () => ({ ENCRYPTION_KEY: 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2', updateJwtSecret: () => {}, })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ encrypt_api_key: (v: string) => v, decrypt_api_key: (v: string) => v, maybe_encrypt_api_key: (v: string) => v, diff --git a/server/tests/unit/nest/auth-guard.test.ts b/server/tests/unit/nest/auth-guard.test.ts index 372971cb8..646b2f665 100644 --- a/server/tests/unit/nest/auth-guard.test.ts +++ b/server/tests/unit/nest/auth-guard.test.ts @@ -3,7 +3,7 @@ import { HttpException } from '@nestjs/common'; import type { Request } from 'express'; vi.mock('../../../src/middleware/auth', () => ({ extractToken: vi.fn(), verifyJwtAndLoadUser: vi.fn() })); -vi.mock('../../../src/services/cookie', () => ({ setAuthCookie: vi.fn() })); +vi.mock('../../../src/nest/common/cookie', () => ({ setAuthCookie: vi.fn() })); vi.mock('../../../src/nest/audit/client-ip', () => ({ getClientIp: vi.fn(() => '1.2.3.4') })); vi.mock('../../../src/nest/audit/audit-log.logger', () => ({ LOG_LEVEL: 'error', logInfo: vi.fn(), logDebug: vi.fn(), logError: vi.fn(), logWarn: vi.fn() })); @@ -35,7 +35,7 @@ import { CurrentUser } from '../../../src/nest/auth/current-user.decorator'; import { extractToken, verifyJwtAndLoadUser } from '../../../src/middleware/auth'; import type { AuthService } from '../../../src/nest/auth/auth.service'; import type { PasskeyService } from '../../../src/nest/auth/passkey.service'; -import { setAuthCookie } from '../../../src/services/cookie'; +import { setAuthCookie } from '../../../src/nest/common/cookie'; import type { AuditService } from '../../../src/nest/audit/audit.service'; import type { User } from '../../../src/types'; diff --git a/server/tests/unit/nest/auth.controller.test.ts b/server/tests/unit/nest/auth.controller.test.ts index 467922802..a78817865 100644 --- a/server/tests/unit/nest/auth.controller.test.ts +++ b/server/tests/unit/nest/auth.controller.test.ts @@ -4,14 +4,14 @@ import type { Request, Response } from 'express'; vi.mock('../../../src/nest/audit/client-ip', () => ({ getClientIp: vi.fn(() => '1.2.3.4') })); vi.mock('../../../src/nest/audit/audit-log.logger', () => ({ LOG_LEVEL: 'error', logInfo: vi.fn(), logDebug: vi.fn(), logError: vi.fn(), logWarn: vi.fn() })); -vi.mock('../../../src/services/demo', () => ({ isDemoEmail: vi.fn(() => false) })); +vi.mock('../../../src/nest/common/demo', () => ({ isDemoEmail: vi.fn(() => false) })); import { AuthPublicController } from '../../../src/nest/auth/auth-public.controller'; import { AuthController } from '../../../src/nest/auth/auth.controller'; import { RateLimitService } from '../../../src/nest/common/rate-limit.service'; import type { AuthService } from '../../../src/nest/auth/auth.service'; import type { AuditService } from '../../../src/nest/audit/audit.service'; -import { isDemoEmail } from '../../../src/services/demo'; +import { isDemoEmail } from '../../../src/nest/common/demo'; import type { User } from '../../../src/types'; const user = { id: 1, username: 'u', role: 'user', email: 'u@example.test' } as User; diff --git a/server/tests/unit/nest/auth.helpers.test.ts b/server/tests/unit/nest/auth.helpers.test.ts index 6f9aeecbc..3ca74b2e2 100644 --- a/server/tests/unit/nest/auth.helpers.test.ts +++ b/server/tests/unit/nest/auth.helpers.test.ts @@ -10,7 +10,7 @@ import { describe, it, expect, vi } from 'vitest'; vi.mock('../../../src/config', () => ({ JWT_SECRET: 'test-secret', ENCRYPTION_KEY: '0'.repeat(64) })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: vi.fn((v) => v), maybe_encrypt_api_key: vi.fn((v) => v), encrypt_api_key: vi.fn((v) => v), @@ -25,7 +25,7 @@ import { generateBackupCodes, parseBackupCodeHashes, } from '../../../src/nest/auth/auth.helpers'; -import { avatarUrl } from '../../../src/services/avatarUrl'; +import { avatarUrl } from '../../../src/nest/common/avatarUrl'; import type { User } from '../../../src/types'; // ── utcSuffix ──────────────────────────────────────────────────────────────── diff --git a/server/tests/unit/nest/auth.service.test.ts b/server/tests/unit/nest/auth.service.test.ts index 2ade03f20..1f9a4dd63 100644 --- a/server/tests/unit/nest/auth.service.test.ts +++ b/server/tests/unit/nest/auth.service.test.ts @@ -43,11 +43,11 @@ vi.mock('../../../src/config', () => ({ SESSION_DURATION_REMEMBER_SECONDS: 2592000, updateJwtSecret: () => {}, })); -vi.mock('../../../src/services/mfaCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/mfaCrypto', () => ({ encryptMfaSecret: vi.fn((s) => `enc:${s}`), decryptMfaSecret: vi.fn((s: string) => s.replace('enc:', '')), })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: vi.fn((v) => v), maybe_encrypt_api_key: vi.fn((v) => v), mask_stored_api_key: vi.fn((v: string | null | undefined) => (v ? '••••••••' : null)), diff --git a/server/tests/unit/nest/collab.service.test.ts b/server/tests/unit/nest/collab.service.test.ts index e1e225994..85b0f2f6d 100644 --- a/server/tests/unit/nest/collab.service.test.ts +++ b/server/tests/unit/nest/collab.service.test.ts @@ -57,7 +57,7 @@ import { createTables } from '../../../src/db/schema'; import { runMigrations } from '../../../src/db/migrations'; import { resetTestDb } from '../../helpers/test-db'; import { createUser, createTrip } from '../../helpers/factories'; -import { avatarUrl } from '../../../src/services/avatarUrl'; +import { avatarUrl } from '../../../src/nest/common/avatarUrl'; import { DatabaseService } from '../../../src/nest/database/database.service'; import { PermissionsService } from '../../../src/nest/permissions/permissions.service'; import { CollabService } from '../../../src/nest/collab/collab.service'; diff --git a/server/tests/unit/nest/files.controller.test.ts b/server/tests/unit/nest/files.controller.test.ts index ffdc15cb2..32009764c 100644 --- a/server/tests/unit/nest/files.controller.test.ts +++ b/server/tests/unit/nest/files.controller.test.ts @@ -5,14 +5,14 @@ import os from 'os'; import path from 'path'; import fs from 'fs'; -vi.mock('../../../src/services/demo', () => ({ isDemoEmail: vi.fn(() => false) })); +vi.mock('../../../src/nest/common/demo', () => ({ isDemoEmail: vi.fn(() => false) })); import { FilesController } from '../../../src/nest/files/files.controller'; import { FilesDownloadController } from '../../../src/nest/files/files-download.controller'; import { PhotosController } from '../../../src/nest/photos/photos.controller'; import type { FilesService } from '../../../src/nest/files/files.service'; import type { PhotosService } from '../../../src/nest/photos/photos.service'; -import { isDemoEmail } from '../../../src/services/demo'; +import { isDemoEmail } from '../../../src/nest/common/demo'; import type { User } from '../../../src/types'; const user = { id: 1, username: 'u', role: 'user', email: 'u@example.test' } as User; diff --git a/server/tests/unit/nest/maps.service.test.ts b/server/tests/unit/nest/maps.service.test.ts index d9b55f9b9..266098f8c 100644 --- a/server/tests/unit/nest/maps.service.test.ts +++ b/server/tests/unit/nest/maps.service.test.ts @@ -79,7 +79,7 @@ vi.mock('../../../src/utils/ssrfGuard', () => { }; }); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: (v: string | null) => v, })); diff --git a/server/tests/unit/nest/notifications.service.test.ts b/server/tests/unit/nest/notifications.service.test.ts index a19e57f19..fc455ba93 100644 --- a/server/tests/unit/nest/notifications.service.test.ts +++ b/server/tests/unit/nest/notifications.service.test.ts @@ -31,7 +31,7 @@ vi.mock('../../../src/config', () => ({ ENCRYPTION_KEY: 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2', updateJwtSecret: () => {}, })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: (v: string | null) => v, maybe_encrypt_api_key: (v: string) => v, encrypt_api_key: (v: string) => v, diff --git a/server/tests/unit/nest/oidc.service.test.ts b/server/tests/unit/nest/oidc.service.test.ts index ca723e8e1..0da50481d 100644 --- a/server/tests/unit/nest/oidc.service.test.ts +++ b/server/tests/unit/nest/oidc.service.test.ts @@ -51,11 +51,11 @@ vi.mock('../../../src/config', () => ({ // as auth.service.test.ts) — services/tripMembership is deliberately NOT // mocked: OIDC-SVC-045 asserts the real trip_members row a trip-bound invite // creates. -vi.mock('../../../src/services/mfaCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/mfaCrypto', () => ({ encryptMfaSecret: vi.fn((s) => `enc:${s}`), decryptMfaSecret: vi.fn((s: string) => s.replace('enc:', '')), })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: vi.fn((v) => v), maybe_encrypt_api_key: vi.fn((v) => v), mask_stored_api_key: vi.fn((v: string | null | undefined) => (v ? '••••••••' : null)), @@ -78,8 +78,8 @@ vi.mock('../../../src/app-config', async (importOriginal) => { }); const { setAuthCookieMock } = vi.hoisted(() => ({ setAuthCookieMock: vi.fn() })); -vi.mock('../../../src/services/cookie', async (importOriginal) => { - const actual = await importOriginal(); +vi.mock('../../../src/nest/common/cookie', async (importOriginal) => { + const actual = await importOriginal(); return { ...actual, setAuthCookie: setAuthCookieMock }; }); diff --git a/server/tests/unit/nest/passkey.service.test.ts b/server/tests/unit/nest/passkey.service.test.ts index 20000ccea..8630480b1 100644 --- a/server/tests/unit/nest/passkey.service.test.ts +++ b/server/tests/unit/nest/passkey.service.test.ts @@ -43,11 +43,11 @@ vi.mock('../../../src/config', () => ({ // Construction insurance for the injected AuthService's import graph (same set // as oidc.service.test.ts / auth.service.test.ts). -vi.mock('../../../src/services/mfaCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/mfaCrypto', () => ({ encryptMfaSecret: vi.fn((s) => `enc:${s}`), decryptMfaSecret: vi.fn((s: string) => s.replace('enc:', '')), })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: vi.fn((v) => v), maybe_encrypt_api_key: vi.fn((v) => v), mask_stored_api_key: vi.fn((v: string | null | undefined) => (v ? '••••••••' : null)), diff --git a/server/tests/unit/nest/settings.service.test.ts b/server/tests/unit/nest/settings.service.test.ts index e01280c52..efc704c16 100644 --- a/server/tests/unit/nest/settings.service.test.ts +++ b/server/tests/unit/nest/settings.service.test.ts @@ -35,7 +35,7 @@ vi.mock('../../../src/config', () => ({ })); // Passthrough crypto — value comes back unchanged for most tests -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ maybe_encrypt_api_key: (v: string) => v, decrypt_api_key: (v: string) => v, })); diff --git a/server/tests/unit/nest/trips.controller.test.ts b/server/tests/unit/nest/trips.controller.test.ts index 63fa47824..916159dc0 100644 --- a/server/tests/unit/nest/trips.controller.test.ts +++ b/server/tests/unit/nest/trips.controller.test.ts @@ -5,7 +5,7 @@ import type { Request } from 'express'; vi.mock('../../../src/nest/audit/client-ip', () => ({ getClientIp: vi.fn(() => '1.2.3.4') })); vi.mock('../../../src/nest/audit/audit-log.logger', () => ({ LOG_LEVEL: 'error', logInfo: vi.fn(), logDebug: vi.fn(), logError: vi.fn(), logWarn: vi.fn() })); const { isDemoEmail } = vi.hoisted(() => ({ isDemoEmail: vi.fn(() => false) })); -vi.mock('../../../src/services/demo', () => ({ isDemoEmail })); +vi.mock('../../../src/nest/common/demo', () => ({ isDemoEmail })); // Mock the Unsplash cover internalisation so the controller test never hits the // network; isUnsplashCoverUrl keeps its real (host-based) logic. vi.mock('../../../src/services/unsplashService', () => ({ diff --git a/server/tests/unit/plugins/plugin-host-deps.factory.test.ts b/server/tests/unit/plugins/plugin-host-deps.factory.test.ts index 64f3db383..bd1e794a6 100644 --- a/server/tests/unit/plugins/plugin-host-deps.factory.test.ts +++ b/server/tests/unit/plugins/plugin-host-deps.factory.test.ts @@ -148,7 +148,7 @@ const packingStub = { deleteBag: vi.fn((_tid: number | string, bagId: string) => Number(bagId) !== 404), setBagMembers: vi.fn((_tid: number | string, bagId: string, userIds: number[]) => (Number(bagId) === 404 ? null : userIds.map((u) => ({ user_id: u })))), } as unknown as PackingService; -vi.mock('../../../src/services/conflictResult', () => ({ isUpdateConflict: (r: unknown) => !!(r as { conflict?: boolean })?.conflict })); +vi.mock('../../../src/nest/common/conflictResult', () => ({ isUpdateConflict: (r: unknown) => !!(r as { conflict?: boolean })?.conflict })); vi.mock('../../../src/services/weatherService', () => ({ getWeather: vi.fn(async (lat: string, lng: string) => ({ lat, lng, temp: 20 })) })); const categoriesStub = { list: vi.fn(() => [{ id: 1, name: 'Food' }]) } as unknown as CategoriesService; const tagsStub = { diff --git a/server/tests/unit/plugins/plugin-oauth.service.test.ts b/server/tests/unit/plugins/plugin-oauth.service.test.ts index 267d00401..d7f814459 100644 --- a/server/tests/unit/plugins/plugin-oauth.service.test.ts +++ b/server/tests/unit/plugins/plugin-oauth.service.test.ts @@ -6,7 +6,7 @@ */ import { describe, it, expect, beforeEach, vi } from 'vitest'; -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ encrypt_api_key: (v: unknown) => (typeof v === 'string' ? `enc:${v}` : v), decrypt_api_key: (v: unknown) => (typeof v === 'string' && v.startsWith('enc:') ? v.slice(4) : v), })); diff --git a/server/tests/unit/plugins/plugin-user-settings.test.ts b/server/tests/unit/plugins/plugin-user-settings.test.ts index 8d1920e9a..e1e43732c 100644 --- a/server/tests/unit/plugins/plugin-user-settings.test.ts +++ b/server/tests/unit/plugins/plugin-user-settings.test.ts @@ -8,7 +8,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; // Reversible crypto stub so we can assert encrypt-at-rest without a real key env. -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ maybe_encrypt_api_key: (v: unknown) => (typeof v === 'string' ? `enc:${v}` : v), decrypt_api_key: (v: unknown) => (typeof v === 'string' && v.startsWith('enc:') ? v.slice(4) : v), })); diff --git a/server/tests/unit/services/apiKeyCrypto.test.ts b/server/tests/unit/services/apiKeyCrypto.test.ts index 40357ee58..8434ffb57 100644 --- a/server/tests/unit/services/apiKeyCrypto.test.ts +++ b/server/tests/unit/services/apiKeyCrypto.test.ts @@ -7,7 +7,7 @@ vi.mock('../../../src/config', () => ({ updateJwtSecret: () => {}, })); -import { encrypt_api_key, decrypt_api_key, maybe_encrypt_api_key } from '../../../src/services/apiKeyCrypto'; +import { encrypt_api_key, decrypt_api_key, maybe_encrypt_api_key } from '../../../src/nest/common/crypto/apiKeyCrypto'; describe('apiKeyCrypto', () => { const PLAINTEXT_KEY = 'my-secret-api-key-12345'; diff --git a/server/tests/unit/services/avatarUrl.test.ts b/server/tests/unit/services/avatarUrl.test.ts index 5a4e1c21f..bdc9b46c6 100644 --- a/server/tests/unit/services/avatarUrl.test.ts +++ b/server/tests/unit/services/avatarUrl.test.ts @@ -4,7 +4,7 @@ * an OIDC `picture` claim (#1399); the helper resolves both to a renderable src. */ import { describe, it, expect } from 'vitest'; -import { avatarUrl } from '../../../src/services/avatarUrl'; +import { avatarUrl } from '../../../src/nest/common/avatarUrl'; describe('avatarUrl', () => { it('AVATAR-URL-001: prefixes an uploaded file name with the avatars path', () => { diff --git a/server/tests/unit/services/channelOverride.test.ts b/server/tests/unit/services/channelOverride.test.ts index ba5896be3..71092dbf8 100644 --- a/server/tests/unit/services/channelOverride.test.ts +++ b/server/tests/unit/services/channelOverride.test.ts @@ -16,7 +16,7 @@ const { testDb, dbMock } = vi.hoisted(() => { }); vi.mock('../../../src/db/database', () => dbMock); vi.mock('../../../src/config', () => ({ JWT_SECRET: 'x'.repeat(40), ENCRYPTION_KEY: 'a'.repeat(64), updateJwtSecret: () => {} })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ decrypt_api_key: (v: string) => v, maybe_encrypt_api_key: (v: string) => v, encrypt_api_key: (v: string) => v })); +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: (v: string) => v, maybe_encrypt_api_key: (v: string) => v, encrypt_api_key: (v: string) => v })); const { sendMailMock } = vi.hoisted(() => ({ sendMailMock: vi.fn().mockResolvedValue({ accepted: ['a@b.c'] }) })); vi.mock('nodemailer', () => ({ default: { createTransport: vi.fn(() => ({ sendMail: sendMailMock, verify: vi.fn() })) } })); vi.stubGlobal('fetch', vi.fn()); diff --git a/server/tests/unit/services/conflictUpdate.test.ts b/server/tests/unit/services/conflictUpdate.test.ts index a7ad359f8..3e3bcd93b 100644 --- a/server/tests/unit/services/conflictUpdate.test.ts +++ b/server/tests/unit/services/conflictUpdate.test.ts @@ -38,7 +38,7 @@ import { createTables } from '../../../src/db/schema'; import { runMigrations } from '../../../src/db/migrations'; import { resetTestDb } from '../../helpers/test-db'; import { createUser, createTrip } from '../../helpers/factories'; -import { isUpdateConflict } from '../../../src/services/conflictResult'; +import { isUpdateConflict } from '../../../src/nest/common/conflictResult'; import { DatabaseService } from '../../../src/nest/database/database.service'; import { PackingService } from '../../../src/nest/packing/packing.service'; import { PlacesService } from '../../../src/nest/places/places.service'; diff --git a/server/tests/unit/services/cookie.test.ts b/server/tests/unit/services/cookie.test.ts index 97823f718..494f111c7 100644 --- a/server/tests/unit/services/cookie.test.ts +++ b/server/tests/unit/services/cookie.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import { cookieOptions } from '../../../src/services/cookie'; +import { cookieOptions } from '../../../src/nest/common/cookie'; import { SESSION_DURATION_MS, SESSION_DURATION_REMEMBER_MS } from '../../../src/config'; describe('cookieOptions', () => { diff --git a/server/tests/unit/services/mfaCrypto.test.ts b/server/tests/unit/services/mfaCrypto.test.ts index 03b5c4266..a19dedc8b 100644 --- a/server/tests/unit/services/mfaCrypto.test.ts +++ b/server/tests/unit/services/mfaCrypto.test.ts @@ -7,7 +7,7 @@ vi.mock('../../../src/config', () => ({ updateJwtSecret: () => {}, })); -import { encryptMfaSecret, decryptMfaSecret } from '../../../src/services/mfaCrypto'; +import { encryptMfaSecret, decryptMfaSecret } from '../../../src/nest/common/crypto/mfaCrypto'; describe('mfaCrypto', () => { const TOTP_SECRET = 'JBSWY3DPEHPK3PXP'; // typical base32 TOTP secret diff --git a/server/tests/unit/services/notificationPreferencesService.test.ts b/server/tests/unit/services/notificationPreferencesService.test.ts index ae8a058de..51d591b45 100644 --- a/server/tests/unit/services/notificationPreferencesService.test.ts +++ b/server/tests/unit/services/notificationPreferencesService.test.ts @@ -26,7 +26,7 @@ vi.mock('../../../src/config', () => ({ ENCRYPTION_KEY: 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2', updateJwtSecret: () => {}, })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: (v: string | null) => v, maybe_encrypt_api_key: (v: string) => v, encrypt_api_key: (v: string) => v, diff --git a/server/tests/unit/services/notifications.test.ts b/server/tests/unit/services/notifications.test.ts index c115b7a91..716597c5d 100644 --- a/server/tests/unit/services/notifications.test.ts +++ b/server/tests/unit/services/notifications.test.ts @@ -3,7 +3,7 @@ import { describe, it, expect, vi, afterEach, afterAll, beforeEach } from 'vites vi.mock('../../../src/db/database', () => ({ db: { prepare: () => ({ get: vi.fn(() => undefined), all: vi.fn(() => []) }) }, })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: vi.fn((v) => v), maybe_encrypt_api_key: vi.fn((v) => v), })); diff --git a/server/tests/unit/services/oauthService.test.ts b/server/tests/unit/services/oauthService.test.ts index 7020cd62f..0b97c9759 100644 --- a/server/tests/unit/services/oauthService.test.ts +++ b/server/tests/unit/services/oauthService.test.ts @@ -29,7 +29,7 @@ vi.mock('../../../src/config', () => ({ ENCRYPTION_KEY: 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2', updateJwtSecret: () => {}, })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ encrypt_api_key: (v: string) => v, decrypt_api_key: (v: string) => v, maybe_encrypt_api_key: (v: string) => v, diff --git a/server/tests/unit/services/passwordPolicy.test.ts b/server/tests/unit/services/passwordPolicy.test.ts index 65b5471a1..6f5eff3f7 100644 --- a/server/tests/unit/services/passwordPolicy.test.ts +++ b/server/tests/unit/services/passwordPolicy.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { validatePassword } from '../../../src/services/passwordPolicy'; +import { validatePassword } from '../../../src/nest/common/passwordPolicy'; describe('validatePassword', () => { // AUTH-006 — Registration with weak password diff --git a/server/tests/unit/services/timezoneService.test.ts b/server/tests/unit/services/timezoneService.test.ts index fff57e6a1..29a31ef19 100644 --- a/server/tests/unit/services/timezoneService.test.ts +++ b/server/tests/unit/services/timezoneService.test.ts @@ -1,4 +1,4 @@ -import { localParts, resolveTimeZone } from '../../../src/services/timezoneService'; +import { localParts, resolveTimeZone } from '../../../src/nest/common/timezoneService'; import { describe, expect, it } from 'vitest'; diff --git a/server/tests/unit/services/unsplashService.test.ts b/server/tests/unit/services/unsplashService.test.ts index bf4c90879..ab734187b 100644 --- a/server/tests/unit/services/unsplashService.test.ts +++ b/server/tests/unit/services/unsplashService.test.ts @@ -11,7 +11,7 @@ vi.mock('../../../src/utils/ssrfGuard', () => ({ safeFetch })); vi.mock('../../../src/db/database', () => ({ db: { prepare: () => ({ get: mockDbGet, all: vi.fn(() => []), run: vi.fn() }) }, })); -vi.mock('../../../src/services/apiKeyCrypto', () => ({ decrypt_api_key: (v: string | null) => v })); +vi.mock('../../../src/nest/common/crypto/apiKeyCrypto', () => ({ decrypt_api_key: (v: string | null) => v })); import { searchUnsplashPhotos, getUnsplashKey, saveUnsplashCover, isUnsplashCoverUrl } from '../../../src/services/unsplashService';