Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions webapp/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DATABASE_URL="file:./dev.db"
22 changes: 22 additions & 0 deletions webapp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Proton Drive Web App (Next.js)

This is a minimal Next.js application that mirrors some of the network APIs from the Proton Drive Android project. It uses Prisma with an SQLite database for persistence.

The code in this directory is provided under the same GPLv3 license as the rest of the repository. See the root `LICENSE` file for details.

## Development

1. Install dependencies (Node.js 18+ required):
```bash
npm install
```
2. Run Prisma migrations and generate the client:
```bash
npx prisma migrate dev
```
3. Start the development server:
```bash
npm run dev
```

This skeleton exposes a `/api/volumes` route that supports `GET` and `POST` requests.
11 changes: 11 additions & 0 deletions webapp/lib/prisma.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { PrismaClient } from '@prisma/client'

declare global {
var prisma: PrismaClient | undefined
}

const prisma = global.prisma || new PrismaClient()

if (process.env.NODE_ENV !== 'production') global.prisma = prisma

export default prisma
5 changes: 5 additions & 0 deletions webapp/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
6 changes: 6 additions & 0 deletions webapp/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}

module.exports = nextConfig
21 changes: 21 additions & 0 deletions webapp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "proton-drive-webapp",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"prisma": "prisma"
},
"dependencies": {
"next": "13.4.10",
"react": "18.2.0",
"react-dom": "18.2.0",
"@prisma/client": "5.14.0"
},
"devDependencies": {
"typescript": "5.0.4",
"prisma": "5.14.0"
}
}
18 changes: 18 additions & 0 deletions webapp/pages/api/volumes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { NextApiRequest, NextApiResponse } from 'next'
import prisma from '../../../lib/prisma'

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'GET') {
const volumes = await prisma.volume.findMany({
include: { shareUrls: true },
})
res.status(200).json(volumes)
} else if (req.method === 'POST') {
const { name } = req.body
const volume = await prisma.volume.create({ data: { name } })
res.status(201).json(volume)
} else {
res.setHeader('Allow', ['GET', 'POST'])
res.status(405).end(`Method ${req.method} Not Allowed`)
}
}
21 changes: 21 additions & 0 deletions webapp/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import useSWR from 'swr'

const fetcher = (url: string) => fetch(url).then(res => res.json())

export default function Home() {
const { data, error } = useSWR('/api/volumes', fetcher)

if (error) return <div>Failed to load</div>
if (!data) return <div>Loading...</div>

return (
<div>
<h1>Volumes</h1>
<ul>
{data.map((v: any) => (
<li key={v.id}>{v.name}</li>
))}
</ul>
</div>
)
}
24 changes: 24 additions & 0 deletions webapp/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}

model Volume {
id String @id @default(cuid())
createdAt DateTime @default(now())
name String
usedSpace Int @default(0)
}

model ShareUrl {
id String @id @default(cuid())
volumeId String
url String
createdAt DateTime @default(now())

volume Volume @relation(fields: [volumeId], references: [id])
}
20 changes: 20 additions & 0 deletions webapp/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}