This commit is contained in:
mpabi 2025-09-13 22:01:42 +02:00
commit 9ca22325cc
11 changed files with 2526 additions and 0 deletions

23
backend/Dockerfile Normal file
View File

@ -0,0 +1,23 @@
FROM node:20-slim AS build
WORKDIR /app
COPY package*.json tsconfig.json ./
RUN npm install
COPY src ./src
RUN npm run build
# Finalny obraz
FROM node:20-slim
WORKDIR /app
COPY --from=build /app/package*.json ./
RUN npm install --omit=dev
COPY --from=build /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/server.js"]

16
backend/_export Normal file
View File

@ -0,0 +1,16 @@
> repo_export.txt # wyczyść plik wynikowy
while IFS= read -r file; do
# Pomijaj puste linie i pliki z katalogu _export
[[ -z "$file" || "$file" == *_export* ]] && continue
# Sprawdź, czy plik istnieje i nie jest ukryty
[[ -f "$file" && "$file" != */.* ]] || continue
echo "=== FILE: $file ==="
echo
cat "$file"
echo
echo
done < files.txt > repo_export.txt

1
backend/_find Normal file
View File

@ -0,0 +1 @@
find . \( -path "./node_modules" -o -path "./dist" \) -prune -o -print > files.txt

View File

@ -0,0 +1,31 @@
version: "3.9"
services:
postgres:
image: postgres:16
container_name: pg-demo
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: demo
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
backend:
build: .
container_name: backend-demo
restart: always
depends_on:
- postgres
environment:
DATABASE_URL: postgres://postgres:postgres@postgres:5432/demo
PORT: 3000
ports:
- "3000:3000"
volumes:
pgdata:

0
backend/migrate.sql Normal file
View File

2320
backend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

22
backend/package.json Normal file
View File

@ -0,0 +1,22 @@
{
"name": "fastify-graphql-demo",
"version": "1.0.0",
"main": "dist/server.js",
"type": "module",
"scripts": {
"dev": "ts-node-dev --respawn --transpile-only src/server.ts",
"build": "tsc -p .",
"start": "node dist/server.js"
},
"dependencies": {
"fastify": "^4.26.2",
"mercurius": "^16.2.0",
"pg": "^8.11.3"
},
"devDependencies": {
"@types/node": "^22.7.4",
"@types/pg": "^8.15.5",
"ts-node-dev": "^2.0.0",
"typescript": "^5.6.3"
}
}

32
backend/src/db.ts Normal file
View File

@ -0,0 +1,32 @@
import pkg from "pg";
const { Pool } = pkg;
const pool = new Pool({
connectionString:
process.env.DATABASE_URL ||
"postgres://postgres:postgres@localhost:5432/demo",
});
export async function query<T extends pkg.QueryResultRow>(
q: string,
params?: any[]
): Promise<T[]> {
const client = await pool.connect();
try {
const res = await client.query<T>(q, params);
return res.rows;
} finally {
client.release();
}
}
export async function initDB(): Promise<void> {
await query(`
CREATE TABLE IF NOT EXISTS pump_data (
id SERIAL PRIMARY KEY,
payload JSONB NOT NULL,
created_at TIMESTAMP DEFAULT now()
);
`);
}

65
backend/src/server.ts Normal file
View File

@ -0,0 +1,65 @@
import Fastify from "fastify";
import mercurius from "mercurius";
import { query, initDB } from "./db.js";
const app = Fastify();
// Healthchecki
app.get("/healthz", async () => ({ status: "ok" }));
app.get("/readyz", async () => ({ ready: true }));
// Schemat GraphQL
const schema = `
type PumpResult {
id: ID!
created_at: String!
}
type Query {
health: String!
}
type Mutation {
pump(payload: String!): PumpResult!
}
`;
const resolvers = {
Query: {
health: async () => "ok",
},
Mutation: {
pump: async (_: unknown, { payload }: { payload: string }) => {
const rows = await query<{ id: number; created_at: string }>(
"INSERT INTO pump_data(payload) VALUES($1) RETURNING id, created_at",
[payload]
);
return rows[0];
},
},
};
// Rejestracja GraphQL
app.register(mercurius, {
schema,
resolvers,
graphiql: true,
});
const start = async () => {
try {
await initDB();
const port = Number(process.env.PORT) || 3000;
await app.listen(port, "0.0.0.0");
console.log(`🚀 Server running at http://0.0.0.0:${port}/graphql`);
} catch (err) {
console.error(err);
process.exit(1);
}
};
start();

0
backend/src/types.d.ts vendored Normal file
View File

16
backend/tsconfig.json Normal file
View File

@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "Node",
"outDir": "dist",
"rootDir": "src",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}