diff --git a/apps/backend/src/__tests__/event.test.ts b/apps/backend/src/__tests__/event.test.ts index b921fb25..15124f61 100644 --- a/apps/backend/src/__tests__/event.test.ts +++ b/apps/backend/src/__tests__/event.test.ts @@ -1,8 +1,10 @@ +import Fastify, { type FastifyInstance } from 'fastify'; import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import Fastify, { FastifyInstance } from 'fastify'; -import { PrismaClient } from '@prisma/client'; + import { eventRoutes } from '../routes/event'; +import type { PrismaClient } from '@prisma/client'; + // ─── Shared mock data ──────────────────────────────────────────────────────── const MOCK_USER_ID = 'user-uuid-001'; @@ -64,7 +66,7 @@ const prismaMock = { // // This mirrors the real app setup without touching a real DB or real JWT keys. -let mockJwtVerify = vi.fn(); +const mockJwtVerify = vi.fn(); async function buildApp(): Promise { const app = Fastify({ logger: false }); diff --git a/apps/backend/src/__tests__/profiles.test.ts b/apps/backend/src/__tests__/profiles.test.ts index b6630a7a..7beee1c7 100644 --- a/apps/backend/src/__tests__/profiles.test.ts +++ b/apps/backend/src/__tests__/profiles.test.ts @@ -1,5 +1,6 @@ -import { describe, it, expect, beforeEach, vi } from 'vitest'; import Fastify from 'fastify'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; + import { profileRoutes } from '../routes/profiles.js'; import type { PrismaClient } from '@prisma/client'; diff --git a/apps/backend/src/app.ts b/apps/backend/src/app.ts index 2471a92d..77d8504d 100644 --- a/apps/backend/src/app.ts +++ b/apps/backend/src/app.ts @@ -1,25 +1,29 @@ -import Fastify from 'fastify'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import cookie from '@fastify/cookie'; import cors from '@fastify/cors'; import helmet from '@fastify/helmet'; import jwt from '@fastify/jwt'; -import cookie from '@fastify/cookie'; import multipart from '@fastify/multipart'; import fastifyStatic from '@fastify/static'; +import Fastify from 'fastify'; import rateLimit from '@fastify/rate-limit'; import path from 'path'; import { fileURLToPath } from 'url'; import { prismaPlugin } from './plugins/prisma.js'; import { redisPlugin } from './plugins/redis.js'; +import { analyticsRoutes } from './routes/analytics.js'; import { authRoutes } from './routes/auth.js'; -import { profileRoutes } from './routes/profiles.js'; import { cardRoutes } from './routes/cards.js'; -import { publicRoutes } from './routes/public.js'; -import { followRoutes } from './routes/follow.js'; import { connectRoutes } from './routes/connect.js'; import { analyticsRoutes } from './routes/analytics.js'; import { nfcRoutes } from './routes/nfc.js'; import { eventRoutes } from './routes/event.js'; +import { followRoutes } from './routes/follow.js'; +import { profileRoutes } from './routes/profiles.js'; +import { publicRoutes } from './routes/public.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); diff --git a/apps/backend/src/env.ts b/apps/backend/src/env.ts index 5902853d..a3ad0507 100644 --- a/apps/backend/src/env.ts +++ b/apps/backend/src/env.ts @@ -1,6 +1,7 @@ -import process from 'node:process'; import path from 'node:path'; +import process from 'node:process'; import { fileURLToPath } from 'node:url'; + import dotenv from 'dotenv'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); diff --git a/apps/backend/src/plugins/prisma.ts b/apps/backend/src/plugins/prisma.ts index f6ebede8..ca683e0c 100644 --- a/apps/backend/src/plugins/prisma.ts +++ b/apps/backend/src/plugins/prisma.ts @@ -1,5 +1,5 @@ -import fp from 'fastify-plugin'; import { PrismaClient } from '@prisma/client'; +import fp from 'fastify-plugin'; import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; declare module 'fastify' { diff --git a/apps/backend/src/plugins/redis.ts b/apps/backend/src/plugins/redis.ts index c7b6f94d..8b0f4b24 100644 --- a/apps/backend/src/plugins/redis.ts +++ b/apps/backend/src/plugins/redis.ts @@ -1,5 +1,6 @@ import fp from 'fastify-plugin'; import Redis from 'ioredis'; + import type { FastifyInstance } from 'fastify'; declare module 'fastify' { diff --git a/apps/backend/src/routes/auth.ts b/apps/backend/src/routes/auth.ts index 3dc9166a..48dd39ac 100644 --- a/apps/backend/src/routes/auth.ts +++ b/apps/backend/src/routes/auth.ts @@ -1,3 +1,5 @@ +import { randomBytes } from 'node:crypto'; + import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; import { randomBytes } from 'crypto'; import { encrypt } from '../utils/encryption.js'; diff --git a/apps/backend/src/routes/cards.ts b/apps/backend/src/routes/cards.ts index 7da682b9..36f02c79 100644 --- a/apps/backend/src/routes/cards.ts +++ b/apps/backend/src/routes/cards.ts @@ -1,6 +1,7 @@ -import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; import { createCardSchema, updateCardSchema } from '../utils/validators.js'; +import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; + export async function cardRoutes(app: FastifyInstance) { app.addHook('preHandler', app.authenticate); diff --git a/apps/backend/src/routes/event.ts b/apps/backend/src/routes/event.ts index 4e2f7d0a..9bd17836 100644 --- a/apps/backend/src/routes/event.ts +++ b/apps/backend/src/routes/event.ts @@ -1,6 +1,7 @@ -import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; import { createEventSchema, joinEventSchema} from '../validations/event.validation'; +import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; + type EventDetails = { id: string; name: string; @@ -59,7 +60,7 @@ export async function eventRoutes(app:FastifyInstance) { const {name, description, startDate, endDate, isPublic ,location} = parsed.data - let cleanSlug = name.toLowerCase().trim().replace(/\s+/g, '-').replace(/[^a-z0-9-]+/g, '').replace(/-+/g, '-').replace(/^-+|-+$/g, '') + const cleanSlug = name.toLowerCase().trim().replace(/\s+/g, '-').replace(/[^a-z0-9-]+/g, '').replace(/-+/g, '-').replace(/^-+|-+$/g, '') let finalSlug = cleanSlug; while(true){ @@ -68,7 +69,7 @@ export async function eventRoutes(app:FastifyInstance) { if(!existing){ break; } - const randomSuffix = Math.random().toString(36).substring(2,6); + const randomSuffix = Math.random().toString(36).slice(2,6); finalSlug = `${cleanSlug}-${randomSuffix}` } @@ -81,7 +82,7 @@ export async function eventRoutes(app:FastifyInstance) { name, description, slug: finalSlug, - location: location, + location, startDate: startDateObj, endDate: endDateObj, isPublic: isPublic ?? true, @@ -156,7 +157,7 @@ export async function eventRoutes(app:FastifyInstance) { await app.prisma.eventAttendee.create({ data: { eventId: event.id, - userId: userId, + userId, joinedAt: new Date() } }) @@ -196,7 +197,7 @@ export async function eventRoutes(app:FastifyInstance) { await app.prisma.eventAttendee.delete({ where: { userId_eventId: { - userId: userId, + userId, eventId: event.id } } diff --git a/apps/backend/src/routes/follow.ts b/apps/backend/src/routes/follow.ts index 265c9ea8..4e26e33b 100644 --- a/apps/backend/src/routes/follow.ts +++ b/apps/backend/src/routes/follow.ts @@ -1,7 +1,8 @@ -import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; import { decrypt } from '../utils/encryption.js'; import { getPlatform, getProfileUrl, getWebViewUrl } from '@devcard/shared'; +import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; + export async function followRoutes(app: FastifyInstance) { app.addHook('preHandler', app.authenticate); diff --git a/apps/backend/src/routes/profiles.ts b/apps/backend/src/routes/profiles.ts index 99aacb8e..7d24cbb2 100644 --- a/apps/backend/src/routes/profiles.ts +++ b/apps/backend/src/routes/profiles.ts @@ -1,11 +1,13 @@ -import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; import { getProfileUrl } from '@devcard/shared'; + import { updateProfileSchema, createLinkSchema, reorderLinksSchema, } from '../utils/validators.js'; +import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; + export async function profileRoutes(app: FastifyInstance) { // All profile routes require auth app.addHook('preHandler', app.authenticate); diff --git a/apps/backend/src/routes/public.ts b/apps/backend/src/routes/public.ts index 0a64e270..3946b023 100644 --- a/apps/backend/src/routes/public.ts +++ b/apps/backend/src/routes/public.ts @@ -1,6 +1,7 @@ -import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; import { generateQRBuffer, generateQRSvg } from '../utils/qr.js'; +import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; + type PublicProfileLink = { id: string; platform: string; diff --git a/apps/backend/src/utils/encryption.ts b/apps/backend/src/utils/encryption.ts index b9105992..adfb3172 100644 --- a/apps/backend/src/utils/encryption.ts +++ b/apps/backend/src/utils/encryption.ts @@ -1,4 +1,4 @@ -import crypto from 'crypto'; +import crypto from 'node:crypto'; const ALGORITHM = 'aes-256-gcm'; const IV_LENGTH = 16; diff --git a/apps/web/src/components/NetworkBackground.svelte b/apps/web/src/components/NetworkBackground.svelte new file mode 100644 index 00000000..9fab8fb2 --- /dev/null +++ b/apps/web/src/components/NetworkBackground.svelte @@ -0,0 +1,118 @@ + + + + + \ No newline at end of file diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte index ac6dd12f..58c33481 100644 --- a/apps/web/src/routes/+layout.svelte +++ b/apps/web/src/routes/+layout.svelte @@ -1,6 +1,122 @@ @@ -8,4 +124,18 @@ + + {@render children()} + + \ No newline at end of file diff --git a/packages/shared/eslint.config.js b/packages/shared/eslint.config.js new file mode 100644 index 00000000..97a3bd15 --- /dev/null +++ b/packages/shared/eslint.config.js @@ -0,0 +1 @@ +export { default } from '../../apps/backend/eslint.config.js'; \ No newline at end of file diff --git a/packages/shared/package.json b/packages/shared/package.json index b3b3ac7e..7a7f1574 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -11,6 +11,7 @@ "test": "vitest run" }, "devDependencies": { + "eslint": "^10.4.0", "typescript": "^5.4.0", "vitest": "^2.0.0" } diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 409d3e76..70fc5df8 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1,3 +1,3 @@ export * from './platforms'; -export * from './types'; -export * from './cards'; \ No newline at end of file +export type * from './types'; +export * from './cards'; diff --git a/packages/shared/src/platforms.test.ts b/packages/shared/src/platforms.test.ts index d1ff86b7..4b92c398 100644 --- a/packages/shared/src/platforms.test.ts +++ b/packages/shared/src/platforms.test.ts @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; + import { PLATFORMS, getAllPlatforms, diff --git a/packages/shared/src/platforms.ts b/packages/shared/src/platforms.ts index a218957c..f019d7cf 100644 --- a/packages/shared/src/platforms.ts +++ b/packages/shared/src/platforms.ts @@ -270,20 +270,20 @@ export function getPlatform(id: string): PlatformDef | undefined { /** Get the profile URL for a given platform and username */ export function getProfileUrl(platformId: string, username: string): string { const platform = PLATFORMS[platformId]; - if (!platform) return ''; + if (!platform) {return '';} return platform.urlPattern.replace(/{username}/g, username); } /** Get the WebView URL for Layer 2 platforms */ export function getWebViewUrl(platformId: string, username: string): string | null { const platform = PLATFORMS[platformId]; - if (!platform?.webViewUrlPattern) return null; + if (!platform?.webViewUrlPattern) {return null;} return platform.webViewUrlPattern.replace(/{username}/g, username); } /** Get the deep link URL for mobile */ export function getDeepLinkUrl(platformId: string, username: string): string | null { const platform = PLATFORMS[platformId]; - if (!platform?.deepLinkPattern) return null; + if (!platform?.deepLinkPattern) {return null;} return platform.deepLinkPattern.replace(/{username}/g, username); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5badd097..c3d6c5f8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -272,6 +272,9 @@ importers: packages/shared: devDependencies: + eslint: + specifier: ^10.4.0 + version: 10.4.0(jiti@2.6.1) typescript: specifier: ^5.4.0 version: 5.9.3