diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f4f5391..5be76db 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -322,6 +322,9 @@ importers: specifier: ^0.5.4 version: 0.5.4(prisma@5.4.2)(zod@3.22.2) devDependencies: + '@faker-js/faker': + specifier: ^8.4.0 + version: 8.4.0 '@types/bcryptjs': specifier: ^2.4.3 version: 2.4.3 @@ -5545,6 +5548,11 @@ packages: resolution: {integrity: sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==} dev: false + /@faker-js/faker@8.4.0: + resolution: {integrity: sha512-htW87352wzUCdX1jyUQocUcmAaFqcR/w082EC8iP/gtkF0K+aKcBp0hR5Arb7dzR8tQ1TrhE9DNa5EbJELm84w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13'} + dev: true + /@hapi/hoek@9.3.0: resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} diff --git a/src/client/vite.config.ts b/src/client/vite.config.ts index 1fb6c0e..ed896ec 100644 --- a/src/client/vite.config.ts +++ b/src/client/vite.config.ts @@ -19,6 +19,9 @@ export default defineConfig({ '/trpc': { target: 'http://localhost:12345', }, + '/api/workspace': { + target: 'http://localhost:12345', + }, }, }, }); diff --git a/src/server/package.json b/src/server/package.json index 55dbb69..36875a1 100644 --- a/src/server/package.json +++ b/src/server/package.json @@ -12,6 +12,7 @@ "db:migrate:dev": "prisma migrate dev", "db:migrate:apply": "prisma migrate deploy", "db:studio": "prisma studio", + "db:seed:website": "ts-node ./tests/seeds/website.ts", "test": "vitest", "test:ci": "vitest --run" }, @@ -62,6 +63,7 @@ "zod-prisma": "^0.5.4" }, "devDependencies": { + "@faker-js/faker": "^8.4.0", "@types/bcryptjs": "^2.4.3", "@types/compression": "^1.7.2", "@types/cors": "^2.8.15", diff --git a/src/server/tests/seeds/website.ts b/src/server/tests/seeds/website.ts new file mode 100644 index 0000000..9d041ce --- /dev/null +++ b/src/server/tests/seeds/website.ts @@ -0,0 +1,106 @@ +import { prisma } from '../../model/_client'; +import { hashUuid } from '../../utils/common'; +import { faker } from '@faker-js/faker'; +import { getLocation } from '../../utils/detect'; +import dayjs from 'dayjs'; +import { WebsiteSession } from '@prisma/client'; + +async function main() { + Array.from({ length: 200 }).map(async (_, i) => { + const session = await createSession(); + + await createSessionEvent(session); + + console.log(`generate session ${i} completed`); + }); +} + +main() + .then(async () => { + await prisma.$disconnect(); + }) + .catch(async (e) => { + console.error(e); + await prisma.$disconnect(); + process.exit(1); + }); + +const startDate = dayjs().subtract(30, 'days').toDate(); +const endDate = dayjs().toDate(); +async function createSession() { + const websiteId = 'clrytmpbe000lvyo434zxiwqh'; + const hostname = faker.internet.domainName(); + const ip = faker.internet.ipv4(); + const userAgent = faker.internet.userAgent(); + const sessionId = hashUuid(websiteId, hostname, ip, userAgent); + const browser = faker.helpers.arrayElement([ + 'chromium-webview', + 'ios-webview', + 'ios', + 'edge-ios', + 'crios', + 'ios', + ]); + const os = faker.helpers.arrayElement([ + 'Android OS', + 'iOS', + 'Mac OS', + 'Windows 10', + ]); + const device = faker.helpers.arrayElement(['desktop', 'mobile', 'tablet']); + const screen = faker.helpers.arrayElement([ + '1366x768', + '1920x1080', + '1440x900', + '800x600', + ]); + const language = faker.helpers.arrayElement(['zh-CN', 'en-US']); + const { + country, + subdivision1, + subdivision2, + city, + longitude, + latitude, + accuracyRadius, + } = (await getLocation(ip)) ?? {}; + const createdAt = faker.date.between({ from: startDate, to: endDate }); + + const session = await prisma.websiteSession.create({ + data: { + id: sessionId, + websiteId, + hostname, + browser, + os, + device, + screen, + language, + ip, + country, + subdivision1, + subdivision2, + city, + longitude, + latitude, + accuracyRadius, + createdAt, + }, + }); + + return session; +} + +async function createSessionEvent(session: WebsiteSession) { + await prisma.websiteEvent.createMany({ + data: Array.from({ length: faker.number.int({ max: 20 }) }).map(() => ({ + sessionId: session.id, + websiteId: session.websiteId, + urlPath: '/', + createdAt: faker.date.between({ + from: session.createdAt, + to: endDate, + }), + })), + }); +}