Skip to content

Commit e5eb1ef

Browse files
authored
Merge pull request #47 from biersoeckli/feat/upgrade-prisma-orm-to-v7
feat/upgrade prisma orm to v7
2 parents c2ee1c7 + 13c587e commit e5eb1ef

File tree

14 files changed

+888
-65
lines changed

14 files changed

+888
-65
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
NEXTAUTH_SECRET=SOME_TOKEN_FOR_NEXTJS_AUTHENTICATION
2+
DATABASE_URL="file:/workspace/storage/db/data.db"

.github/copilot-instructions.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# QuickStack AI Coding Instructions
2+
3+
QuickStack is a self-hosted PaaS built with Next.js 14 (App Router) that manages Kubernetes (k3s) deployments. It uses a custom server (`src/server.ts`) that wraps Next.js to handle WebSockets for terminal streaming.
4+
5+
## Architecture Overview
6+
7+
### Three-Layer Structure
8+
- **`src/app/`** - Next.js App Router pages and Server Actions (all pages use `'use server'`)
9+
- **`src/server/`** - Backend services that interact with Kubernetes and database
10+
- **`src/shared/`** - Shared models, utils, and Zod schemas (used by both frontend and server)
11+
12+
### Key Adapters (`src/server/adapter/`)
13+
- `kubernetes-api.adapter.ts` - Wraps `@kubernetes/client-node` APIs (`k3s.core`, `k3s.apps`, etc.)
14+
- `db.client.ts` - Prisma singleton (`dataAccess.client`)
15+
- `longhorn-api.adapter.ts` - Longhorn storage API
16+
17+
### Service Pattern
18+
Services are singleton classes exported as default instances:
19+
```typescript
20+
class AppService { /* methods */ }
21+
const appService = new AppService();
22+
export default appService;
23+
```
24+
25+
## Server Actions Pattern
26+
27+
All server actions use wrappers from `src/server/utils/action-wrapper.utils.ts`:
28+
29+
```typescript
30+
// For form submissions with Zod validation
31+
export const saveApp = async (data: AppModel) =>
32+
saveFormAction(data, AppModelSchema, async (validated) => {
33+
await appService.save(validated);
34+
return new SuccessActionResult(undefined, 'App saved');
35+
}) as Promise<ServerActionResult<any, void>>;
36+
37+
// For simple actions without form validation
38+
export const deleteApp = async (id: string) =>
39+
simpleAction(async () => {
40+
await isAuthorizedWriteForApp(id); // Auth check
41+
await appService.deleteById(id);
42+
return new SuccessActionResult(undefined, 'App deleted');
43+
});
44+
```
45+
46+
## Database & Prisma
47+
48+
- SQLite database at `storage/db/data.db`
49+
- Schema: `prisma/schema.prisma`
50+
- Zod schemas auto-generated to `src/shared/model/generated-zod/`
51+
- After schema changes: `yarn prisma-migrate` (runs `prisma migrate dev` + fixes Zod imports)
52+
- Use `dataAccess.client` for queries, supports transactions via `$transaction()`
53+
54+
## Kubernetes Naming Conventions
55+
56+
Use `KubeObjectNameUtils` for consistent k8s object names:
57+
- `toProjectId(name)``proj-{name}-{hash}`
58+
- `toAppId(name)``app-{name}-{hash}`
59+
- `toPvcName(volumeId)``pvc-{volumeId}`
60+
- `toServiceName(appId)``svc-{appId}`
61+
62+
## Frontend Patterns
63+
64+
### State Management
65+
Zustand stores in `src/frontend/states/zustand.states.ts`:
66+
- `useConfirmDialog` - Promise-based confirmation dialogs
67+
- `useInputDialog` - Promise-based input dialogs
68+
- `useBreadcrumbs` - Page breadcrumb navigation
69+
70+
### UI Components
71+
- shadcn/ui components in `src/components/ui/`
72+
- Custom components in `src/components/custom/`
73+
- Forms use `react-hook-form` with Zod resolvers
74+
75+
### Real-time Updates
76+
- Socket.IO server at `/pod-terminal` namespace for terminal streaming
77+
- WebSocket server for live pod logs
78+
79+
## Caching
80+
81+
Next.js `unstable_cache` with tag-based invalidation:
82+
```typescript
83+
// Reading with cache
84+
await unstable_cache(
85+
async () => dataAccess.client.app.findMany({ where: { projectId } }),
86+
[Tags.apps(projectId)],
87+
{ tags: [Tags.apps(projectId)] }
88+
)(projectId);
89+
90+
// Invalidating after mutations
91+
revalidateTag(Tags.apps(projectId));
92+
```
93+
94+
## Testing
95+
96+
- Jest with jsdom environment
97+
- Tests in `src/__tests__/{frontend,server,shared}/`
98+
- Path alias `@/` maps to `src/`
99+
- Run: `yarn test`
100+
101+
## Development Setup
102+
103+
1. Use provided devcontainer (includes Node, Bun, Prisma extension)
104+
2. Provide k3s credentials in `kube-config.config` at project root
105+
3. `yarn install``yarn dev` for Next.js or `yarn dev-live` for custom server
106+
107+
## Commit Convention
108+
109+
Follow Conventional Commits: `feat:`, `fix:`, `refactor:`, `docs:`, `test:`, `chore:`

.github/workflows/build-release.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ on:
55
release:
66
types: [released, prereleased]
77

8+
env:
9+
# dummy database url for build time --> prisma
10+
DATABASE_URL: file:./dev.db
11+
812
permissions:
913
contents: read
1014

@@ -17,7 +21,7 @@ jobs:
1721

1822
- uses: actions/setup-node@v4
1923
with:
20-
node-version: '18.x'
24+
node-version: '22.x'
2125
registry-url: 'https://registry.npmjs.org'
2226

2327
- name: Install dependencies for backend

.github/workflows/canary-release.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ on:
66
- main
77
workflow_dispatch:
88

9+
env:
10+
# dummy database url for build time --> prisma
11+
DATABASE_URL: file:./dev.db
12+
913
permissions:
1014
contents: read
1115

@@ -18,7 +22,7 @@ jobs:
1822

1923
- uses: actions/setup-node@v4
2024
with:
21-
node-version: '18.x'
25+
node-version: '22.x'
2226
registry-url: 'https://registry.npmjs.org'
2327

2428
- name: Install dependencies for backend

.github/workflows/tests.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ on:
66
branches:
77
- main
88

9+
env:
10+
# dummy database url for build time --> prisma
11+
DATABASE_URL: file:./dev.db
12+
913
permissions:
1014
contents: read
1115

@@ -18,7 +22,7 @@ jobs:
1822

1923
- uses: actions/setup-node@v4
2024
with:
21-
node-version: '18.x'
25+
node-version: '22.x'
2226
registry-url: 'https://registry.npmjs.org'
2327

2428
- name: Install dependencies for backend

Dockerfile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:18-alpine AS base
1+
FROM node:22-alpine AS base
22

33
ARG VERSION_ARG
44
RUN apk add --no-cache openssl
@@ -20,6 +20,9 @@ WORKDIR /app
2020
COPY --from=deps /app/node_modules ./node_modules
2121
COPY . .
2222

23+
# Dummy Database URL for Prisma generation
24+
ENV DATABASE_URL="file:./dev.db"
25+
2326
RUN yarn run prisma-generate-build
2427
RUN yarn run build
2528
RUN rm -rf ./next/standalone
@@ -31,6 +34,7 @@ WORKDIR /app
3134
ENV NODE_ENV=production
3235
ENV PYTHON=/usr/bin/python3
3336
ENV QS_VERSION=$VERSION_ARG
37+
ENV DATABASE_URL="file:/app/storage/db/data.db"
3438

3539
RUN apk add --no-cache git
3640

@@ -42,6 +46,7 @@ RUN chown nextjs:nodejs storage tmp-storage
4246

4347
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
4448
COPY --from=builder --chown=nextjs:nodejs /app/prisma ./prisma
49+
COPY --from=builder --chown=nextjs:nodejs /app/prisma.config.ts ./prisma.config.js
4550
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
4651
COPY --from=builder --chown=nextjs:nodejs /app/dist ./dist
4752
COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ QuickStack is a self-hosted PaaS solution designed to simplify the management of
66

77
Developed as part of a student project by [glueh-wyy-huet](https://github.com/glueh-wyy-huet) and [biersoeckli](https://github.com/biersoeckli) at the [Eastern Switzerland University of Applied Sciences](https://ost.ch/), QuickStack provides a scalable and cost-effective alternative to commercial cloud PaaS offerings like Vercel, Digital Ocean App Platform or Azure App Service.
88

9+
<img src="/github-assets/app-settings-general.png" alt="QuickStack App Settings Image" width="100%" />
10+
911
## Key Features
1012

1113
* **One-Command Installation:** Deploy QuickStack on a VPS with a single command.
666 KB
Loading

package.json

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"@hookform/resolvers": "^3.9.0",
2121
"@kubernetes/client-node": "^0.22.2",
2222
"@next-auth/prisma-adapter": "^1.0.7",
23-
"@prisma/client": "^5.21.1",
23+
"@prisma/adapter-better-sqlite3": "^7.1.0",
24+
"@prisma/client": "7.1.0",
2425
"@radix-ui/react-alert-dialog": "^1.1.2",
2526
"@radix-ui/react-avatar": "^1.1.1",
2627
"@radix-ui/react-checkbox": "^1.1.2",
@@ -40,10 +41,6 @@
4041
"@radix-ui/react-tabs": "^1.1.1",
4142
"@radix-ui/react-tooltip": "^1.1.4",
4243
"@tanstack/react-table": "^8.20.5",
43-
"@types/bcrypt": "^5.0.2",
44-
"@types/node-schedule": "^2.1.7",
45-
"@types/qrcode": "^1.5.5",
46-
"@types/ws": "^8.5.13",
4744
"@xterm/xterm": "^5.5.0",
4845
"bcrypt": "^5.1.1",
4946
"bufferutil": "^4.0.9",
@@ -53,14 +50,15 @@
5350
"cross-env": "^7.0.3",
5451
"date-fns": "^4.1.0",
5552
"date-fns-tz": "^3.2.0",
53+
"dotenv": "^17.2.3",
5654
"lucide-react": "^0.465.0",
5755
"moment": "^2.30.1",
5856
"next": "14.2.15",
5957
"next-auth": "^4.24.8",
6058
"next-themes": "^0.3.0",
6159
"node-schedule": "^2.1.1",
6260
"otpauth": "^9.3.4",
63-
"prisma": "^5.21.1",
61+
"prisma": "7.1.0",
6462
"qrcode": "^1.5.4",
6563
"react": "^18.3.1",
6664
"react-day-picker": "8.10.1",
@@ -82,8 +80,13 @@
8280
},
8381
"devDependencies": {
8482
"@testing-library/dom": "^10.4.0",
83+
"@types/bcrypt": "^5.0.2",
84+
"@types/node-schedule": "^2.1.7",
85+
"@types/qrcode": "^1.5.5",
86+
"@types/ws": "^8.5.13",
8587
"@testing-library/jest-dom": "^6.6.3",
8688
"@testing-library/react": "^16.1.0",
89+
"@types/better-sqlite3": "^7.6.13",
8790
"@types/jest": "^29.5.14",
8891
"@types/mocha": "^10.0.10",
8992
"@types/node": "^22.7.9",

prisma.config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import 'dotenv/config'
2+
import { defineConfig, env } from 'prisma/config'
3+
4+
export default defineConfig({
5+
schema: 'prisma/schema.prisma',
6+
migrations: {
7+
path: 'prisma/migrations',
8+
},
9+
datasource: {
10+
url: env('DATABASE_URL'),
11+
},
12+
})

0 commit comments

Comments
 (0)