diff --git a/.gitignore b/.gitignore index 89d58ef..d5ff783 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,8 @@ Thumbs.db .nx/cache +.env + # Next.js .next out \ No newline at end of file diff --git a/apps/web/app/api/deps/route.ts b/apps/web/app/api/deps/route.ts new file mode 100644 index 0000000..4c80dc0 --- /dev/null +++ b/apps/web/app/api/deps/route.ts @@ -0,0 +1,5 @@ +import { getAppDepsHandler } from '@verity/deps-api'; + +export async function GET(request: Request) { + return getAppDepsHandler(request); +} diff --git a/apps/web/app/api/hello/route.ts b/apps/web/app/api/hello/route.ts deleted file mode 100644 index de70bac..0000000 --- a/apps/web/app/api/hello/route.ts +++ /dev/null @@ -1,3 +0,0 @@ -export async function GET(request: Request) { - return new Response('Hello, from API!'); -} diff --git a/libs/deps-api/.eslintrc.json b/libs/deps-api/.eslintrc.json new file mode 100644 index 0000000..a39ac5d --- /dev/null +++ b/libs/deps-api/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/deps-api/README.md b/libs/deps-api/README.md new file mode 100644 index 0000000..5c30a0d --- /dev/null +++ b/libs/deps-api/README.md @@ -0,0 +1,7 @@ +# deps-api + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test api` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/libs/deps-api/project.json b/libs/deps-api/project.json new file mode 100644 index 0000000..7b34083 --- /dev/null +++ b/libs/deps-api/project.json @@ -0,0 +1,9 @@ +{ + "name": "deps-api", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/api/src", + "projectType": "library", + "tags": [], + "// targets": "to see all targets run: nx show project api --web", + "targets": {} +} diff --git a/libs/deps-api/src/lib/deps-api.ts b/libs/deps-api/src/lib/deps-api.ts new file mode 100644 index 0000000..9022f44 --- /dev/null +++ b/libs/deps-api/src/lib/deps-api.ts @@ -0,0 +1,51 @@ +import { PrismaClient } from '@prisma/client'; + +import { getQueryParams } from '@verity/utils'; + +const prisma = new PrismaClient(); + +export const getAppDepsHandler = async (request: Request) => { + const { app, version } = getQueryParams(request); + + if (!app || !version) { + return new Response('app and version params are required', { status: 400 }); + } + + const rawAppVersion = await prisma.appVersion.findFirst({ + where: { + appId: app, + value: version, + }, + select: { + dependencies: { + select: { + dependencyAppVersion: { + select: { + value: true, + appId: true, + }, + }, + }, + }, + }, + }); + + if (!rawAppVersion) { + return new Response('app version not found', { status: 404 }); + } + + const dependencies = rawAppVersion.dependencies.reduce((acc, dep) => { + const appId = dep.dependencyAppVersion?.appId; + + if (!appId) { + return acc; + } else { + return { + ...acc, + [appId]: dep.dependencyAppVersion?.value, + }; + } + }, {}); + + return new Response(JSON.stringify(dependencies), { status: 200 }); +}; diff --git a/libs/deps-api/src/server.ts b/libs/deps-api/src/server.ts new file mode 100644 index 0000000..e9aeb2a --- /dev/null +++ b/libs/deps-api/src/server.ts @@ -0,0 +1 @@ +export * from './lib/deps-api'; diff --git a/libs/deps-api/tsconfig.json b/libs/deps-api/tsconfig.json new file mode 100644 index 0000000..95cfeb2 --- /dev/null +++ b/libs/deps-api/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/deps-api/tsconfig.lib.json b/libs/deps-api/tsconfig.lib.json new file mode 100644 index 0000000..08e579b --- /dev/null +++ b/libs/deps-api/tsconfig.lib.json @@ -0,0 +1,25 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": [ + "node", + "@nx/react/typings/cssmodule.d.ts", + "@nx/react/typings/image.d.ts", + "next", + "@nx/next/typings/image.d.ts" + ] + }, + "exclude": [ + "jest.config.ts", + "src/**/*.spec.ts", + "src/**/*.test.ts", + "src/**/*.spec.tsx", + "src/**/*.test.tsx", + "src/**/*.spec.js", + "src/**/*.test.js", + "src/**/*.spec.jsx", + "src/**/*.test.jsx" + ], + "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] +} diff --git a/libs/utils/src/lib/utils.ts b/libs/utils/src/lib/utils.ts index 2819a83..adf113c 100644 --- a/libs/utils/src/lib/utils.ts +++ b/libs/utils/src/lib/utils.ts @@ -4,3 +4,8 @@ import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } + +export function getQueryParams(request: Request): Record { + const url = new URL(request.url); + return Object.fromEntries(url.searchParams.entries()); +} diff --git a/prisma/migrations/20240603122534_deps_tables/migration.sql b/prisma/migrations/20240603122534_deps_tables/migration.sql new file mode 100644 index 0000000..d9f6505 --- /dev/null +++ b/prisma/migrations/20240603122534_deps_tables/migration.sql @@ -0,0 +1,46 @@ +-- CreateTable +CREATE TABLE "App" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "App_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "AppVersion" ( + "id" SERIAL NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "value" TEXT NOT NULL, + "builtAt" TIMESTAMP(3), + "appId" TEXT NOT NULL, + + CONSTRAINT "AppVersion_pkey" PRIMARY KEY ("appId","value") +); + +-- CreateTable +CREATE TABLE "AppVersionDependency" ( + "id" SERIAL NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "dependantAppVersionId" INTEGER NOT NULL, + "dependencyAppVersionId" INTEGER NOT NULL, + + CONSTRAINT "AppVersionDependency_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "App_id_key" ON "App"("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "AppVersion_id_key" ON "AppVersion"("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "AppVersionDependency_id_key" ON "AppVersionDependency"("id"); + +-- AddForeignKey +ALTER TABLE "AppVersion" ADD CONSTRAINT "AppVersion_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AppVersionDependency" ADD CONSTRAINT "AppVersionDependency_dependantAppVersionId_fkey" FOREIGN KEY ("dependantAppVersionId") REFERENCES "AppVersion"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AppVersionDependency" ADD CONSTRAINT "AppVersionDependency_dependencyAppVersionId_fkey" FOREIGN KEY ("dependencyAppVersionId") REFERENCES "AppVersion"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6debc4c..8ebefab 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -76,3 +76,33 @@ model Authenticator { @@id([userId, credentialID]) } + +model App { + id String @id @unique + createdAt DateTime @default(now()) + versions AppVersion[] +} + +model AppVersion { + id Int @unique @default(autoincrement()) + createdAt DateTime @default(now()) + value String + builtAt DateTime? + appId String + dependencies AppVersionDependency[] @relation("AppVersionDependency") + dependsOn AppVersionDependency[] @relation("AppVersionDependsOn") + + app App @relation(fields: [appId], references: [id]) + + @@id([appId, value]) +} + +model AppVersionDependency { + id Int @id @unique @default(autoincrement()) + createdAt DateTime @default(now()) + dependantAppVersionId Int + dependencyAppVersionId Int + + dependantAppVersion AppVersion? @relation("AppVersionDependency", fields: [dependantAppVersionId], references: [id]) + dependencyAppVersion AppVersion? @relation("AppVersionDependsOn", fields: [dependencyAppVersionId], references: [id]) +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 669fee5..d604da3 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -17,6 +17,7 @@ "paths": { "@verity/auth": ["libs/auth/src/index.ts"], "@verity/auth/server": ["libs/auth/src/server.ts"], + "@verity/deps-api": ["libs/deps-api/src/server.ts"], "@verity/ui": ["libs/ui/src/index.ts"], "@verity/ui/*": ["libs/ui/src/lib/*"], "@verity/ui/server": ["libs/ui/src/server.ts"],