Skip to content

Commit c49ce38

Browse files
Merge pull request #13 from vintasoftware/ft/watcher
Added watchers in both frontend and backend
2 parents 2faf79b + af15c1f commit c49ce38

19 files changed

+925
-273
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,4 @@ cython_debug/
159159
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
160160
# and can be added to the global gitignore or merged into this file. For a more nuclear
161161
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
162-
.idea/
162+
.idea/

.pre-commit-config.docker.yaml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
fail_fast: true
2+
3+
repos:
4+
- repo: https://github.com/pre-commit/pre-commit-hooks
5+
rev: v4.5.0
6+
hooks:
7+
- id: check-added-large-files
8+
args: ["--maxkb=500"]
9+
exclude: >
10+
(?x)^(
11+
package-lock\.json
12+
)$
13+
- id: fix-byte-order-marker
14+
- id: check-case-conflict
15+
- id: check-merge-conflict
16+
- id: check-symlinks
17+
- id: debug-statements
18+
- id: detect-private-key
19+
20+
- repo: https://github.com/astral-sh/ruff-pre-commit
21+
# Ruff version.
22+
rev: v0.1.8
23+
hooks:
24+
# Run the linter.
25+
- id: ruff
26+
args: [ --fix ]
27+
# Run the formatter.
28+
- id: ruff-format
29+
30+
- repo: local
31+
hooks:
32+
- id: generate-openapi-schema
33+
name: generate OpenAPI schema
34+
entry: sh -c 'docker compose run --rm --no-deps -T backend poetry run python -m commands.generate_openapi_schema'
35+
language: system
36+
pass_filenames: false
37+
- id: generate-frontend-client
38+
name: generate frontend client
39+
entry: sh -c 'docker compose run --rm --no-deps -T frontend npm run generate-client'
40+
language: system
41+
# Only run frontend client generation if frontend files have changed:
42+
files: ^local-shared-data/openapi\.json$
43+
pass_filenames: false

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@ repos:
3939
entry: sh -c 'cd nextjs-frontend && npm run generate-client'
4040
language: system
4141
# Only run frontend client generation if frontend files have changed:
42-
files: openapi_schema\.json$
42+
files: openapi\.json$
4343
pass_filenames: false

docker-compose.yml

+10-7
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ services:
33
backend:
44
build:
55
context: ./fastapi-backend
6+
environment:
7+
- OPENAPI_OUTPUT_FILE=./shared-data/openapi.json
68
ports:
79
- "8000:8000"
810
networks:
911
- my_network
1012
volumes:
1113
- ./fastapi-backend:/app
14+
- ./local-shared-data:/app/shared-data
1215
depends_on:
1316
- db
1417
db:
@@ -26,23 +29,23 @@ services:
2629
frontend:
2730
build:
2831
context: ./nextjs-frontend
32+
user: node
2933
ports:
3034
- "3000:3000"
3135
networks:
3236
- my_network
3337
environment:
34-
NODE_ENV: production
35-
env_file:
36-
- ./nextjs-frontend/.env.local
38+
NODE_ENV: development
39+
NEXT_PUBLIC_API_BASE_URL: http://backend:8000
40+
OPENAPI_OUTPUT_FILE: ./shared-data/openapi.json
3741
volumes:
3842
- ./nextjs-frontend:/app
39-
- /app/node_modules
40-
- nextjs-build:/app/.next
43+
- nextjs-node-modules:/app/node_modules
44+
- ./local-shared-data:/app/shared-data
4145

4246
volumes:
4347
postgres_data:
44-
nextjs-build:
45-
name: nextjs-build-data
48+
nextjs-node-modules:
4649

4750
networks:
4851
my_network:

fastapi-backend/Dockerfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ RUN poetry config virtualenvs.create false
1010

1111
COPY pyproject.toml poetry.lock ./
1212

13-
RUN poetry install --no-root --no-dev
13+
RUN poetry install --no-root
1414

1515
COPY . .
1616

1717
EXPOSE 8000
1818

19-
CMD ["fastapi", "dev", "src/main.py", "--host", "0.0.0.0", "--port", "8000", "--reload"]
19+
CMD ["./start.sh"]

fastapi-backend/commands/generate_openapi_schema.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import json
22
from pathlib import Path
33
from src.main import app
4+
import os
45

5-
OUTPUT_FILE = "../nextjs-frontend/openapi.json"
6+
from dotenv import load_dotenv
7+
8+
load_dotenv()
9+
10+
OUTPUT_FILE = os.getenv("OPENAPI_OUTPUT_FILE")
611

712

813
def generate_openapi_schema(output_file):

fastapi-backend/poetry.lock

+317-252
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fastapi-backend/pyproject.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ alembic = "^1.13.3"
1414
fastapi-users = {extras = ["sqlalchemy"], version = "^13.0.0"}
1515
pydantic-settings = "^2.5.2"
1616

17-
[tool.poetry.dev-dependencies]
17+
[tool.poetry.group.dev.dependencies]
1818
pre-commit = "^3.4.0"
1919
ruff = "^0.1.0"
20+
watchdog = "^5.0.3"
21+
python-dotenv = "^1.0.1"
2022

2123
[build-system]
2224
requires = ["poetry-core"]

fastapi-backend/start.sh

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
3+
# Start the FastAPI server in the background
4+
fastapi dev src/main.py --host 0.0.0.0 --port 8000 --reload &
5+
6+
# Start the watcher script
7+
python watcher.py
8+
9+
# Wait for all background jobs to finish
10+
wait

fastapi-backend/watcher.py

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import time
2+
from watchdog.observers import Observer
3+
from watchdog.events import FileSystemEventHandler
4+
import subprocess
5+
from threading import Timer
6+
7+
WATCHER_FILES = [
8+
"src/schemas.py",
9+
"src/main.py",
10+
]
11+
12+
13+
class MyHandler(FileSystemEventHandler):
14+
def __init__(self):
15+
super().__init__()
16+
self.debounce_timer = None # Timer to debounce multiple events
17+
self.last_modified = 0
18+
19+
def on_modified(self, event):
20+
# Check if the event is for a file and not a directory
21+
if not event.is_directory:
22+
if event.src_path in WATCHER_FILES: # Specify the file(s) you want to track
23+
# If there's an existing debounce timer, cancel it
24+
if self.debounce_timer:
25+
self.debounce_timer.cancel()
26+
27+
# Start a new timer (e.g., 1 second delay) to wait before executing
28+
self.debounce_timer = Timer(1.0, self.execute_command, [event.src_path])
29+
self.debounce_timer.start()
30+
31+
def execute_command(self, file_path):
32+
print(f"File {file_path} has been modified and saved.")
33+
34+
try:
35+
# Execute your first command
36+
subprocess.run(
37+
["poetry", "run", "python", "-m", "commands.generate_openapi_schema"],
38+
check=True,
39+
)
40+
41+
except subprocess.CalledProcessError as e:
42+
print(f"An error occurred: {e}")
43+
44+
45+
if __name__ == "__main__":
46+
path = "src" # Directory to watch
47+
event_handler = MyHandler()
48+
observer = Observer()
49+
observer.schedule(event_handler, path, recursive=False)
50+
51+
observer.start()
52+
try:
53+
while True:
54+
time.sleep(1)
55+
except KeyboardInterrupt:
56+
observer.stop()
57+
observer.join()
File renamed without changes.

nextjs-frontend/.gitignore

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ yarn-debug.log*
2626
yarn-error.log*
2727

2828
# local env files
29-
.env*.local
29+
.env
30+
.env.local
3031

3132
# vercel
3233
.vercel
@@ -35,4 +36,4 @@ yarn-error.log*
3536
*.tsbuildinfo
3637
next-env.d.ts
3738

38-
!/lib/
39+
!/lib/

nextjs-frontend/Dockerfile

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
FROM node:20-bookworm
22

3+
# Set the working directory
34
WORKDIR /app
45

6+
# Copy package files and install dependencies
57
COPY package*.json ./
68

9+
# Install dependencies as root (or myappuser, depending on your structure)
710
RUN npm install
811

9-
COPY . .
12+
## Switch to the non-root user
13+
USER node
1014

11-
RUN npm run build
15+
# Copy the rest of your application code
16+
COPY . .
1217

1318
EXPOSE 3000
1419

15-
# Start the Next.js app
16-
CMD ["npm", "start"]
20+
# Start the application
21+
CMD ["./start.sh"]

nextjs-frontend/next.config.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const nextConfig = {
66
if (!isServer) {
77
config.plugins.push(
88
new ForkTsCheckerWebpackPlugin({
9-
async: false, // Run type checking synchronously to block the build
9+
async: true, // Run type checking synchronously to block the build
1010
typescript: {
1111
configOverwrite: {
1212
compilerOptions: {

nextjs-frontend/openapi-ts.config.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { defineConfig } from '@hey-api/openapi-ts';
2+
import { config } from 'dotenv';
3+
4+
config({ path: '.env.local' });
5+
6+
const openapiFile = process.env.OPENAPI_OUTPUT_FILE
27

38
export default defineConfig({
49
client: '@hey-api/client-fetch',
5-
input: 'openapi.json',
10+
input: openapiFile as string,
611
output: 'app/openapi-client',
712
});

0 commit comments

Comments
 (0)