diff --git a/apps/backend/@types/express/index.d.ts b/apps/backend/@types/express/index.d.ts deleted file mode 100644 index 35b994da..00000000 --- a/apps/backend/@types/express/index.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -export {} - -declare global { - // metadata-scraper relies on this type - type Element = any - - // add context to request - namespace Express { - interface Request { - client: { - project_id: string - } - } - } -} diff --git a/apps/backend/Dockerfile b/apps/backend/Dockerfile deleted file mode 100644 index 67e58ddf..00000000 --- a/apps/backend/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM --platform=linux/amd64 oven/bun:1.0.4-slim as builder - -ARG DATABASE_URL -ENV DATABASE_URL=$DATABASE_URL - -# For prisma -ARG NODE_VERSION=18 -RUN apt update \ - && apt install -y curl \ - && curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n \ - && bash n $NODE_VERSION \ - && rm n \ - && npm install -g n - -WORKDIR /app -COPY package.json package.json -COPY apps/backend/package.json apps/backend/package.json -COPY packages/types/package.json packages/types/package.json -COPY bun.lockb bun.lockb -RUN bun install -COPY . . -WORKDIR /app/apps/backend -RUN bunx prisma generate -# RUN bunx prisma migrate deploy -WORKDIR /app/apps/backend -EXPOSE ${PORT} -CMD ["bun", "start"] - diff --git a/apps/backend/package.json b/apps/backend/package.json deleted file mode 100644 index 9981d20f..00000000 --- a/apps/backend/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "backend", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "bunx prisma migrate deploy && bun src/app.ts", - "dev": "bun --watch src/app.ts", - "codegen": "bunx prisma generate" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@mixan/types": "workspace:*", - "@prisma/client": "^5.4.2", - "@types/ramda": "^0.29.6", - "express": "^4.18.2", - "morgan": "^1.10.0", - "prisma": "^5.4.2", - "ramda": "^0.29.1", - "random-animal-name": "^0.1.1", - "uuid": "^9.0.1" - }, - "devDependencies": { - "@types/express": "^4.17.18", - "@types/morgan": "^1.9.6", - "@types/uuid": "^9.0.5", - "bun-types": "latest", - "typescript": "^5.0.0" - } -} diff --git a/apps/backend/prisma/migrations/20231010091416_init/migration.sql b/apps/backend/prisma/migrations/20231010091416_init/migration.sql deleted file mode 100644 index 3fb3b5d4..00000000 --- a/apps/backend/prisma/migrations/20231010091416_init/migration.sql +++ /dev/null @@ -1,59 +0,0 @@ --- CreateTable -CREATE TABLE "organizations" ( - "id" UUID NOT NULL DEFAULT gen_random_uuid(), - "name" TEXT NOT NULL, - - CONSTRAINT "organizations_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "projects" ( - "id" UUID NOT NULL DEFAULT gen_random_uuid(), - "name" TEXT NOT NULL, - "organization_id" UUID NOT NULL, - - CONSTRAINT "projects_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "users" ( - "id" UUID NOT NULL DEFAULT gen_random_uuid(), - "name" TEXT NOT NULL, - "email" TEXT NOT NULL, - "password" TEXT NOT NULL, - "organization_id" UUID NOT NULL, - - CONSTRAINT "users_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "events" ( - "id" UUID NOT NULL DEFAULT gen_random_uuid(), - "name" TEXT NOT NULL, - "properties" JSONB NOT NULL, - "project_id" UUID NOT NULL, - - CONSTRAINT "events_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "profiles" ( - "id" UUID NOT NULL DEFAULT gen_random_uuid(), - "name" TEXT NOT NULL, - "properties" JSONB NOT NULL, - "project_id" UUID NOT NULL, - - CONSTRAINT "profiles_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "projects" ADD CONSTRAINT "projects_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "users" ADD CONSTRAINT "users_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "events" ADD CONSTRAINT "events_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "profiles" ADD CONSTRAINT "profiles_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/backend/prisma/migrations/20231010094459_add_dates/migration.sql b/apps/backend/prisma/migrations/20231010094459_add_dates/migration.sql deleted file mode 100644 index 81e72e4b..00000000 --- a/apps/backend/prisma/migrations/20231010094459_add_dates/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ --- AlterTable -ALTER TABLE "events" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; - --- AlterTable -ALTER TABLE "organizations" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; - --- AlterTable -ALTER TABLE "profiles" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; - --- AlterTable -ALTER TABLE "projects" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; - --- AlterTable -ALTER TABLE "users" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/apps/backend/prisma/migrations/20231010184810_fix_profile/migration.sql b/apps/backend/prisma/migrations/20231010184810_fix_profile/migration.sql deleted file mode 100644 index 1eca309e..00000000 --- a/apps/backend/prisma/migrations/20231010184810_fix_profile/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `name` on the `profiles` table. All the data in the column will be lost. - - Added the required column `profile_id` to the `profiles` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "profiles" DROP COLUMN "name", -ADD COLUMN "profile_id" TEXT NOT NULL; diff --git a/apps/backend/prisma/migrations/20231010185023_add_profile_properties/migration.sql b/apps/backend/prisma/migrations/20231010185023_add_profile_properties/migration.sql deleted file mode 100644 index fdd80823..00000000 --- a/apps/backend/prisma/migrations/20231010185023_add_profile_properties/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- AlterTable -ALTER TABLE "profiles" ADD COLUMN "avatar" TEXT, -ADD COLUMN "email" TEXT, -ADD COLUMN "first_name" TEXT, -ADD COLUMN "last_name" TEXT; diff --git a/apps/backend/prisma/migrations/20231010195623_add_client/migration.sql b/apps/backend/prisma/migrations/20231010195623_add_client/migration.sql deleted file mode 100644 index 5d28ac9e..00000000 --- a/apps/backend/prisma/migrations/20231010195623_add_client/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ --- CreateTable -CREATE TABLE "clients" ( - "id" UUID NOT NULL DEFAULT gen_random_uuid(), - "name" TEXT NOT NULL, - "secret" TEXT NOT NULL, - "project_id" UUID NOT NULL, - - CONSTRAINT "clients_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "clients" ADD CONSTRAINT "clients_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/backend/prisma/migrations/20231010195805_add_timestamps_on_client/migration.sql b/apps/backend/prisma/migrations/20231010195805_add_timestamps_on_client/migration.sql deleted file mode 100644 index 1a9aea58..00000000 --- a/apps/backend/prisma/migrations/20231010195805_add_timestamps_on_client/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "clients" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/apps/backend/prisma/migrations/20231010202343_add_profile_id_on_event/migration.sql b/apps/backend/prisma/migrations/20231010202343_add_profile_id_on_event/migration.sql deleted file mode 100644 index c8709ccc..00000000 --- a/apps/backend/prisma/migrations/20231010202343_add_profile_id_on_event/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - Added the required column `profile_id` to the `events` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "events" ADD COLUMN "profile_id" UUID NOT NULL; - --- AddForeignKey -ALTER TABLE "events" ADD CONSTRAINT "events_profile_id_fkey" FOREIGN KEY ("profile_id") REFERENCES "profiles"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/backend/prisma/migrations/20231010202552_profile_nullable_on_events/migration.sql b/apps/backend/prisma/migrations/20231010202552_profile_nullable_on_events/migration.sql deleted file mode 100644 index 511459c8..00000000 --- a/apps/backend/prisma/migrations/20231010202552_profile_nullable_on_events/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ --- DropForeignKey -ALTER TABLE "events" DROP CONSTRAINT "events_profile_id_fkey"; - --- AlterTable -ALTER TABLE "events" ALTER COLUMN "profile_id" DROP NOT NULL; - --- AddForeignKey -ALTER TABLE "events" ADD CONSTRAINT "events_profile_id_fkey" FOREIGN KEY ("profile_id") REFERENCES "profiles"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/apps/backend/prisma/migrations/20231011063223_rename_profile_id_to_external/migration.sql b/apps/backend/prisma/migrations/20231011063223_rename_profile_id_to_external/migration.sql deleted file mode 100644 index 3da7a1d7..00000000 --- a/apps/backend/prisma/migrations/20231011063223_rename_profile_id_to_external/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `profile_id` on the `profiles` table. All the data in the column will be lost. - - Added the required column `external_id` to the `profiles` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "profiles" DROP COLUMN "profile_id", -ADD COLUMN "external_id" TEXT NOT NULL; diff --git a/apps/backend/prisma/migrations/20231011064100_add_unique_external_id_and_project_id/migration.sql b/apps/backend/prisma/migrations/20231011064100_add_unique_external_id_and_project_id/migration.sql deleted file mode 100644 index eafa2140..00000000 --- a/apps/backend/prisma/migrations/20231011064100_add_unique_external_id_and_project_id/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[project_id,external_id]` on the table `profiles` will be added. If there are existing duplicate values, this will fail. - -*/ --- CreateIndex -CREATE UNIQUE INDEX "profiles_project_id_external_id_key" ON "profiles"("project_id", "external_id"); diff --git a/apps/backend/prisma/migrations/20231012082544_external_id_optional/migration.sql b/apps/backend/prisma/migrations/20231012082544_external_id_optional/migration.sql deleted file mode 100644 index 98890914..00000000 --- a/apps/backend/prisma/migrations/20231012082544_external_id_optional/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- DropIndex -DROP INDEX "profiles_project_id_external_id_key"; - --- AlterTable -ALTER TABLE "profiles" ALTER COLUMN "external_id" DROP NOT NULL; diff --git a/apps/backend/prisma/migrations/migration_lock.toml b/apps/backend/prisma/migrations/migration_lock.toml deleted file mode 100644 index fbffa92c..00000000 --- a/apps/backend/prisma/migrations/migration_lock.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) -provider = "postgresql" \ No newline at end of file diff --git a/apps/backend/prisma/schema.prisma b/apps/backend/prisma/schema.prisma deleted file mode 100644 index d40ef1e7..00000000 --- a/apps/backend/prisma/schema.prisma +++ /dev/null @@ -1,99 +0,0 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - -generator client { - provider = "prisma-client-js" -} - -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} - -model Organization { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - name String - projects Project[] - users User[] - - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) @updatedAt - - @@map("organizations") -} - -model Project { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - name String - organization_id String @db.Uuid - organization Organization @relation(fields: [organization_id], references: [id]) - events Event[] - profiles Profile[] - clients Client[] - - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) @updatedAt - - @@map("projects") -} - -model User { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - name String - email String - password String - organization_id String @db.Uuid - organization Organization @relation(fields: [organization_id], references: [id]) - - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) @updatedAt - - @@map("users") -} - -model Event { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - name String - properties Json - project_id String @db.Uuid - project Project @relation(fields: [project_id], references: [id]) - - profile_id String? @db.Uuid - profile Profile? @relation(fields: [profile_id], references: [id]) - - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) @updatedAt - - @@map("events") -} - -model Profile { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - external_id String? - first_name String? - last_name String? - email String? - avatar String? - properties Json - project_id String @db.Uuid - project Project @relation(fields: [project_id], references: [id]) - events Event[] - - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) @updatedAt - - @@map("profiles") -} - -model Client { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - name String - secret String - project_id String @db.Uuid - project Project @relation(fields: [project_id], references: [id]) - - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) @updatedAt - - @@map("clients") -} diff --git a/apps/backend/src/app.ts b/apps/backend/src/app.ts deleted file mode 100644 index 53676e55..00000000 --- a/apps/backend/src/app.ts +++ /dev/null @@ -1,28 +0,0 @@ -import express, { ErrorRequestHandler } from 'express' -import events from './routes/events' -import profiles from './routes/profiles' -import { authMiddleware } from './middlewares/auth' -import morgan from 'morgan' -import { setup } from './routes/setup' -import { errorHandler } from './middlewares/errors' - -const app = express() -const port = process.env.PORT || 8080 - -app.use(express.json()) -app.use(morgan(':method :url :status :response-time ms')) - -// Public routes -app.get('/', (req, res) => res.json('Welcome to Mixan')) -app.use('/setup', setup) - -// Protected routes -app.use(authMiddleware) -app.use('/api/sdk', events) -app.use('/api/sdk', profiles) - -app.use(errorHandler) - -app.listen(port, () => { - console.log(`Listening on port ${port}...`) -}) diff --git a/apps/backend/src/db.ts b/apps/backend/src/db.ts deleted file mode 100644 index dff3b3e9..00000000 --- a/apps/backend/src/db.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { PrismaClient } from "@prisma/client"; - -export const db = new PrismaClient(); diff --git a/apps/backend/src/middlewares/auth.ts b/apps/backend/src/middlewares/auth.ts deleted file mode 100644 index 7ae7ed24..00000000 --- a/apps/backend/src/middlewares/auth.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { NextFunction, Request, Response } from 'express' -import { db } from '../db' -import { HttpError, createError } from '../responses/errors' -import { verifyPassword } from '../services/hash' - -export async function authMiddleware( - req: Request, - res: Response, - next: NextFunction -) { - try { - const clientId = req.headers['mixan-client-id'] as string | undefined - const clientSecret = req.headers['mixan-client-secret'] as string | undefined - - if (!clientId) { - return next(createError(401, 'Misisng client id')) - } - - if (!clientSecret) { - return next(createError(401, 'Misisng client secret')) - } - - const client = await db.client.findUnique({ - where: { - id: clientId, - }, - }) - - if(!client) { - return next(createError(401, 'Invalid client id')) - } - - if (!await verifyPassword(clientSecret, client.secret)) { - return next(createError(401, 'Invalid client secret')) - } - - req.client = { - project_id: client.project_id, - } - - next() - } catch (error) { - next(new HttpError(500, 'Failed verify client credentials')) - } -} diff --git a/apps/backend/src/middlewares/errors.ts b/apps/backend/src/middlewares/errors.ts deleted file mode 100644 index ee7d10f2..00000000 --- a/apps/backend/src/middlewares/errors.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { HttpError } from "../responses/errors"; -import { MixanErrorResponse } from "@mixan/types"; - -export const errorHandler = (error: HttpError | Error, req: Request, res: Response, next: NextFunction) => { - if(error instanceof HttpError) { - console.log('[HttpError]', error.toJson()) - return res.status(error.status).json(error.toJson()) - } - - console.log('[UnknownError]', error.name, error.message) - if(error.stack) { - console.log(error.stack) - } - return res.status(500).json({ - code: 500, - status: 'error', - message: error.message || 'Unexpected error occured', - issues: [] - } satisfies MixanErrorResponse); -}; \ No newline at end of file diff --git a/apps/backend/src/responses/errors.ts b/apps/backend/src/responses/errors.ts deleted file mode 100644 index 1c388b76..00000000 --- a/apps/backend/src/responses/errors.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { - MixanIssue, - MixanErrorResponse -} from '@mixan/types' - -export class HttpError extends Error { - public status: number - public message: string - public issues: MixanIssue[] - - constructor(status: number, message: string | Error, issues?: MixanIssue[]) { - super(message instanceof Error ? message.message : message) - this.status = status - this.message = message instanceof Error ? message.message : message - this.issues = issues || [] - } - - toJson(): MixanErrorResponse { - return { - code: this.status, - status: 'error', - message: this.message, - issues: this.issues, - } - } -} - -export function createIssues(arr: Array) { - throw new HttpError(400, 'Issues', arr) -} - -export function createError(status = 500, error: unknown | Error | string) { - if(error instanceof Error || typeof error === 'string') { - return new HttpError(status, error) - } - - return new HttpError(500, 'Unexpected error occured') -} diff --git a/apps/backend/src/responses/success.ts b/apps/backend/src/responses/success.ts deleted file mode 100644 index 94ce898f..00000000 --- a/apps/backend/src/responses/success.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { MixanResponse } from "@mixan/types"; - -export function success(result?: T): MixanResponse { - return { - result: result || null, - status: 'ok' - } -} \ No newline at end of file diff --git a/apps/backend/src/routes/events.ts b/apps/backend/src/routes/events.ts deleted file mode 100644 index 1fc3a891..00000000 --- a/apps/backend/src/routes/events.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { NextFunction, Response, Router } from 'express' -import { db } from '../db' -import { MixanRequest } from '../types/express' -import { EventPayload } from '@mixan/types' -import { getEvents } from '../services/event' -import { success } from '../responses/success' -import { getProfile } from '../services/profile' -import { uniq } from 'ramda' -const router = Router() - -type PostRequest = MixanRequest> - -router.get('/events', async (req, res, next) => { - try { - const events = await getEvents(req.client.project_id) - res.json(success(events)) - } catch (error) { - next(error) - } -}) - -router.post( - '/events', - async (req: PostRequest, res: Response, next: NextFunction) => { - try { - const projectId = req.client.project_id - - const profileIds = uniq( - req.body - .map((event) => event.profileId) - .filter((id): id is string => !!id) - ) - - for (const profileId of profileIds) { - try { - await getProfile(profileId) - } catch (error) { - console.log('Profile not found, create it', profileId) - await db.profile.create({ - data: { - project_id: projectId, - id: profileId, - properties: {}, - }, - }) - } - } - - await db.event.createMany({ - data: req.body.map((event) => ({ - name: event.name, - properties: event.properties, - createdAt: event.time, - project_id: projectId, - profile_id: event.profileId, - })), - }) - - res.status(201).json(success()) - } catch (error) { - next(error) - } - } -) - -export default router diff --git a/apps/backend/src/routes/profiles.ts b/apps/backend/src/routes/profiles.ts deleted file mode 100644 index ecba0352..00000000 --- a/apps/backend/src/routes/profiles.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { NextFunction, Response, Router } from 'express' -import { db } from '../db' -import { MixanRequest } from '../types/express' -import { getProfile, tickProfileProperty } from '../services/profile' -import { - ProfileDecrementPayload, - ProfileIncrementPayload, - ProfilePayload, -} from '@mixan/types' -import { success } from '../responses/success' -import randomAnimalName from 'random-animal-name' - -const router = Router() - -type PostRequest = MixanRequest - -router.get('/profiles', async (req, res, next) => { - try { - res.json( - success( - await db.profile.findMany({ - where: { - project_id: req.client.project_id, - }, - }) - ) - ) - } catch (error) { - next(error) - } -}) - -router.post( - '/profiles', - async ( - req: MixanRequest<{ - id: string - properties?: Record - }>, - res: Response, - next: NextFunction - ) => { - try { - const projectId = req.client.project_id - const { id, properties } = req.body - const profile = await db.profile.create({ - data: { - id, - external_id: null, - email: null, - first_name: randomAnimalName(), - last_name: null, - avatar: null, - properties: { - ...(properties || {}), - }, - project_id: projectId, - }, - }) - - res.status(201).json(success(profile)) - } catch (error) { - next(error) - } - } -) - -router.put('/profiles/:id', async (req: PostRequest, res: Response, next: NextFunction) => { - try { - const profileId = req.params.id - const profile = await getProfile(profileId) - const { body } = req - if (profile) { - await db.profile.update({ - where: { - id: profileId, - }, - data: { - external_id: body.id, - email: body.email, - first_name: body.first_name, - last_name: body.last_name, - avatar: body.avatar, - properties: { - ...(typeof profile.properties === 'object' - ? profile.properties || {} - : {}), - ...(body.properties || {}), - }, - }, - }) - - res.status(200).json(success()) - } - } catch (error) { - next(error) - } -}) - -router.put( - '/profiles/:id/increment', - async (req: MixanRequest, res: Response, next: NextFunction) => { - try { - await tickProfileProperty({ - name: req.body.name, - tick: req.body.value, - profileId: req.params.id, - }) - res.status(200).json(success()) - } catch (error) { - next(error) - } - } -) - -router.put( - '/profiles/:id/decrement', - async (req: MixanRequest, res: Response, next: NextFunction) => { - try { - await tickProfileProperty({ - name: req.body.name, - tick: -Math.abs(req.body.value), - profileId: req.params.id, - }) - res.status(200).json(success()) - } catch (error) { - next(error) - } - } -) - -export default router diff --git a/apps/backend/src/routes/setup.ts b/apps/backend/src/routes/setup.ts deleted file mode 100644 index e803b642..00000000 --- a/apps/backend/src/routes/setup.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { NextFunction, Request, Response } from 'express' -import { db } from '../db' -import { v4 as uuid } from 'uuid' -import { hashPassword } from '../services/hash' -import { success } from '../responses/success' - -export async function setup(req: Request, res: Response, next: NextFunction) { - try { - const counts = await db.$transaction([ - db.organization.count(), - db.project.count(), - db.client.count(), - ]) - - if (counts.some((count) => count > 0)) { - return res.json(success('Setup already done')) - } - - const organization = await db.organization.create({ - data: { - name: 'Acme Inc.', - }, - }) - - const project = await db.project.create({ - data: { - name: 'Acme Website', - organization_id: organization.id, - }, - }) - const secret = uuid() - const client = await db.client.create({ - data: { - name: 'Acme Website Client', - project_id: project.id, - secret: await hashPassword(secret), - }, - }) - - res.json( - success({ - clientId: client.id, - clientSecret: secret, - }) - ) - } catch (error) { - next(error) - } -} diff --git a/apps/backend/src/services/event.ts b/apps/backend/src/services/event.ts deleted file mode 100644 index 537ac410..00000000 --- a/apps/backend/src/services/event.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { db } from "../db"; - -export function getEvents(projectId: string) { - return db.event.findMany({ - where: { - project_id: projectId, - } - }) -} diff --git a/apps/backend/src/services/hash.ts b/apps/backend/src/services/hash.ts deleted file mode 100644 index 0c38644d..00000000 --- a/apps/backend/src/services/hash.ts +++ /dev/null @@ -1,7 +0,0 @@ -export async function hashPassword(password: string) { - return await Bun.password.hash(password); -} - -export async function verifyPassword(password: string, hashedPassword: string) { - return await Bun.password.verify(password, hashedPassword); -} diff --git a/apps/backend/src/services/profile.ts b/apps/backend/src/services/profile.ts deleted file mode 100644 index 776afe6d..00000000 --- a/apps/backend/src/services/profile.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { EventPayload, ProfilePayload } from '@mixan/types' -import { db } from '../db' -import { Prisma } from '@prisma/client' -import { HttpError } from '../responses/errors' - -type DbProfile = Exclude, null> - -export function getProfile(id: string) { - return db.profile.findUniqueOrThrow({ - where: { - id, - }, - }) -} - -export function getProfiles(projectId: string) { - return db.profile.findMany({ - where: { - project_id: projectId, - }, - }) -} - -export async function tickProfileProperty({ - profileId, - tick, - name, -}: { - profileId: string - tick: number - name: string -}) { - const profile = await getProfile(profileId) - - if (!profile) { - throw new HttpError(404, `Profile not found ${profileId}`) - } - - const properties = ( - typeof profile.properties === 'object' ? profile.properties || {} : {} - ) as Record - const value = name in properties ? properties[name] : 0 - - if (typeof value !== 'number') { - throw new HttpError(400, `Property "${name}" on user is of type ${typeof value}`) - } - - if (typeof tick !== 'number') { - throw new HttpError(400, `Value is not a number ${tick} (${typeof tick})`) - } - - await db.profile.update({ - where: { - id: profileId, - }, - data: { - properties: { - ...properties, - [name]: value + tick, - }, - }, - }) -} diff --git a/apps/backend/src/types/express.ts b/apps/backend/src/types/express.ts deleted file mode 100644 index 7331a4bb..00000000 --- a/apps/backend/src/types/express.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Request } from "express" - -export type MixanRequest = Omit & { - body: Body -} \ No newline at end of file diff --git a/apps/backend/tsconfig.json b/apps/backend/tsconfig.json deleted file mode 100644 index 7556e1d4..00000000 --- a/apps/backend/tsconfig.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "compilerOptions": { - "lib": ["ESNext"], - "module": "esnext", - "target": "esnext", - "moduleResolution": "bundler", - "moduleDetection": "force", - "allowImportingTsExtensions": true, - "noEmit": true, - "composite": true, - "strict": true, - "downlevelIteration": true, - "skipLibCheck": true, - "jsx": "react-jsx", - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "allowJs": true, - "types": [ - "bun-types" // add Bun global - ] - } -}