12 Commits

Author SHA1 Message Date
ahmed 4f782560de downgrade tus server
Publish Docker Image / Publish Docker Image (push) Successful in 41s
2025-05-01 21:59:27 -04:00
ahmed 979cf7320e Switch to alpine
Publish Docker Image / Publish Docker Image (push) Successful in 43s
2025-05-01 21:41:35 -04:00
ahmed 1f9f11e1be Fix crash (thank you gpt o3!)
Publish Docker Image / Publish Docker Image (push) Successful in 5s
2025-05-01 21:18:38 -04:00
ahmed 1d183c37f8 Cors is gone..? reverting old changes
Publish Docker Image / Publish Docker Image (push) Successful in 5s
2025-05-01 21:05:40 -04:00
ahmed 3aeec4d23e Fix PDF once and for all
Publish Docker Image / Publish Docker Image (push) Successful in 57s
2025-05-01 20:46:50 -04:00
ahmed debfcf7226 Attempt 2
Publish Development Docker Image / Publish Development Docker Image (push) Successful in 8s
Publish Docker Image / Publish Docker Image (push) Successful in 27s
2025-04-07 17:33:54 -04:00
ahmed 15bbc27238 Attempt to propegate app version properly
Publish Development Docker Image / Publish Development Docker Image (push) Successful in 8s
2025-04-07 17:17:05 -04:00
ahmed 16bd44c599 Fix app version?
Publish Development Docker Image / Publish Development Docker Image (push) Successful in 9s
2025-04-07 17:06:40 -04:00
ahmed d13b16c032 Update TUS backend
Publish Development Docker Image / Publish Development Docker Image (push) Successful in 1m34s
2025-04-07 16:54:17 -04:00
ahmed d144f7385b Quietly embed version to homepage 2025-04-07 15:08:07 -04:00
ahmed 0283c293ef An attempt to fix the PDF iframe not loading properly when the API domain is third-partyBasic printer CRUD
Publish Docker Image / Publish Docker Image (push) Successful in 39s
2025-04-06 18:08:05 -04:00
Ahmed Al-Taiar 8d75849c55 More reliable docker-compose.yml 2024-11-10 14:48:43 -05:00
171 changed files with 375 additions and 68 deletions
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+1 -2
View File
@@ -1,6 +1,5 @@
version: "1" version: "1"
name: Publish Docker Image name: Publish Docker Image
on: on:
push: push:
tags: tags:
@@ -22,7 +21,7 @@ jobs:
- name: Build & Tag Image - name: Build & Tag Image
run: | run: |
docker build -t git.altaiar.dev/${{ gitea.repository }}:${{ gitea.ref_name }} . docker build --build-arg APP_VERSION=${{ gitea.ref_name }} -t git.altaiar.dev/${{ gitea.repository }}:${{ gitea.ref_name }} .
docker tag git.altaiar.dev/${{ gitea.repository }}:${{ gitea.ref_name }} git.altaiar.dev/${{ gitea.repository }}:latest docker tag git.altaiar.dev/${{ gitea.repository }}:${{ gitea.ref_name }} git.altaiar.dev/${{ gitea.repository }}:latest
- name: Push Images - name: Push Images
Regular → Executable
View File
Regular → Executable
View File
Vendored Regular → Executable
View File
Vendored Regular → Executable
View File
Vendored Regular → Executable
View File
Vendored Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+22 -13
View File
@@ -1,15 +1,13 @@
# base # base
# ---- # ----
FROM node:20-bookworm-slim as base FROM node:lts-alpine AS base
RUN corepack enable RUN corepack enable
# We tried to make the Dockerfile as lean as possible. In some cases, that means we excluded a dependency your project needs. # We tried to make the Dockerfile as lean as possible. In some cases, that means we excluded a dependency your project needs.
# By far the most common is Python. If you're running into build errors because `python3` isn't available, # By far the most common is Python. If you're running into build errors because `python3` isn't available,
# add `python3 make gcc \` before the `openssl \` line below and in other stages as necessary: # add `python3 make gcc \` before the `openssl \` line below and in other stages as necessary:
RUN apt-get update && apt-get install -y \ RUN apk add openssl
openssl \
&& rm -rf /var/lib/apt/lists/*
USER node USER node
WORKDIR /home/node/app WORKDIR /home/node/app
@@ -32,7 +30,7 @@ COPY --chown=node:node graphql.config.js .
# api build # api build
# --------- # ---------
FROM base as api_build FROM base AS api_build
# If your api side build relies on build-time environment variables, # If your api side build relies on build-time environment variables,
# specify them here as ARGs. (But don't put secrets in your Dockerfile!) # specify them here as ARGs. (But don't put secrets in your Dockerfile!)
@@ -51,13 +49,14 @@ ARG EMAIL_FROM
ARG EMAIL_TO ARG EMAIL_TO
ARG FIRST_NAME ARG FIRST_NAME
ARG LAST_NAME ARG LAST_NAME
ARG APP_VERSION
COPY --chown=node:node api api COPY --chown=node:node api api
RUN yarn rw build api RUN yarn rw build api
# web prerender build # web prerender build
# ------------------- # -------------------
FROM api_build as web_build_with_prerender FROM api_build AS web_build_with_prerender
ARG FIRST_NAME ARG FIRST_NAME
ARG LAST_NAME ARG LAST_NAME
@@ -67,13 +66,16 @@ ARG CITY
ARG DEFAULT_THEME ARG DEFAULT_THEME
ARG API_ADDRESS_PROD ARG API_ADDRESS_PROD
ARG API_ADDRESS_DEV ARG API_ADDRESS_DEV
ARG APP_VERSION
ENV APP_VERSION=$APP_VERSION
COPY --chown=node:node web web COPY --chown=node:node web web
RUN yarn rw build web RUN yarn rw build web
# web build # web build
# --------- # ---------
FROM base as web_build FROM base AS web_build
ARG FIRST_NAME ARG FIRST_NAME
ARG LAST_NAME ARG LAST_NAME
@@ -83,19 +85,20 @@ ARG CITY
ARG DEFAULT_THEME ARG DEFAULT_THEME
ARG API_ADDRESS_PROD ARG API_ADDRESS_PROD
ARG API_ADDRESS_DEV ARG API_ADDRESS_DEV
ARG APP_VERSION
ENV APP_VERSION=$APP_VERSION
COPY --chown=node:node web web COPY --chown=node:node web web
RUN yarn rw build web --no-prerender RUN yarn rw build web --no-prerender
# api serve # api serve
# --------- # ---------
FROM node:20-bookworm-slim as api_serve FROM node:lts-alpine AS api_serve
RUN corepack enable RUN corepack enable
RUN apt-get update && apt-get install -y \ RUN apk add openssl
openssl \
&& rm -rf /var/lib/apt/lists/*
USER node USER node
WORKDIR /home/node/app WORKDIR /home/node/app
@@ -119,7 +122,10 @@ COPY --chown=node:node --from=api_build /home/node/app/api/dist /home/node/app/a
COPY --chown=node:node --from=api_build /home/node/app/api/db /home/node/app/api/db COPY --chown=node:node --from=api_build /home/node/app/api/db /home/node/app/api/db
COPY --chown=node:node --from=api_build /home/node/app/node_modules/.prisma /home/node/app/node_modules/.prisma COPY --chown=node:node --from=api_build /home/node/app/node_modules/.prisma /home/node/app/node_modules/.prisma
ARG APP_VERSION
ENV NODE_ENV=production ENV NODE_ENV=production
ENV APP_VERSION=$APP_VERSION
# default api serve command # default api serve command
# --------- # ---------
@@ -132,7 +138,7 @@ CMD [ "./api/dist/server.js" ]
# web serve # web serve
# --------- # ---------
FROM node:20-bookworm-slim as web_serve FROM node:lts-alpine AS web_serve
RUN corepack enable RUN corepack enable
@@ -156,6 +162,9 @@ COPY --chown=node:node graphql.config.js .
COPY --chown=node:node --from=web_build /home/node/app/web/dist /home/node/app/web/dist COPY --chown=node:node --from=web_build /home/node/app/web/dist /home/node/app/web/dist
ARG APP_VERSION
ENV APP_VERSION=$APP_VERSION
ENV NODE_ENV=production \ ENV NODE_ENV=production \
API_PROXY_TARGET=http://api:8911 API_PROXY_TARGET=http://api:8911
@@ -164,7 +173,7 @@ CMD "node_modules/.bin/rw-web-server" "--api-proxy-target" "$API_PROXY_TARGET"
# console # console
# ------- # -------
FROM base as console FROM base AS console
# To add more packages: # To add more packages:
# #
Regular → Executable
+10 -3
View File
@@ -16,6 +16,7 @@ services:
portfolio: portfolio:
container_name: portfolio container_name: portfolio
image: git.altaiar.dev/ahmed/portfolio:latest image: git.altaiar.dev/ahmed/portfolio:latest
restart: unless-stopped
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- API_PROXY_TARGET=http://localhost:8911 - API_PROXY_TARGET=http://localhost:8911
@@ -44,7 +45,8 @@ services:
- 8910:8910 # Web - 8910:8910 # Web
- 8911:8911 # API - 8911:8911 # API
depends_on: depends_on:
- db db:
condition: service_healthy
volumes: volumes:
- files:/home/node/app/api/files_prod - files:/home/node/app/api/files_prod
command: > command: >
@@ -54,14 +56,19 @@ services:
yarn rw prisma db seed && yarn rw prisma db seed &&
yarn rw serve" yarn rw serve"
db: db:
container_name: portfolio-db container_name: portfolio-db
image: postgres:16-bookworm image: postgres:16-bookworm
environment: environment:
- POSTGRES_USER=redwood - POSTGRES_USER=redwood
- POSTGRES_PASSWORD=changeme - POSTGRES_PASSWORD=changeme # Change to a more secure password
- POSTGRES_DB=portfolio - POSTGRES_DB=portfolio
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d DATABASE_URL"] # Replace DATABASE_URL with the database URL from the portfolio container
interval: 10s
timeout: 5s
retries: 5
volumes: volumes:
- postgres:/var/lib/postgresql/data - postgres:/var/lib/postgresql/data
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+2 -2
View File
@@ -9,8 +9,8 @@
"@redwoodjs/api-server": "8.4.0", "@redwoodjs/api-server": "8.4.0",
"@redwoodjs/auth-dbauth-api": "8.4.0", "@redwoodjs/auth-dbauth-api": "8.4.0",
"@redwoodjs/graphql-server": "8.4.0", "@redwoodjs/graphql-server": "8.4.0",
"@tus/file-store": "^1.4.0", "@tus/file-store": "1.4.0",
"@tus/server": "^1.7.0", "@tus/server": "1.7.0",
"countries-list": "^3.1.1", "countries-list": "^3.1.1",
"graphql-scalars": "^1.23.0", "graphql-scalars": "^1.23.0",
"nodemailer": "^6.9.14" "nodemailer": "^6.9.14"
Regular → Executable
View File
View File
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+3 -2
View File
@@ -25,10 +25,11 @@ export const handleTusUpload = (
tusHandler: Server, tusHandler: Server,
isPublicEndpoint: boolean isPublicEndpoint: boolean
) => { ) => {
res.hijack()
if (isProduction) { if (isProduction) {
if (req.method === 'OPTIONS') handleOptionsRequest(res) if (req.method === 'OPTIONS') handleOptionsRequest(res)
else if (isPublicEndpoint && req.method === 'GET') else if (isPublicEndpoint && req.method === 'GET')
tusHandler.handle(req.raw, res.raw) void tusHandler.handle(req.raw, res.raw)
else if (['GET', 'POST', 'HEAD', 'PATCH'].includes(req.method)) { else if (['GET', 'POST', 'HEAD', 'PATCH'].includes(req.method)) {
if (req.headers.cookie) handleAuthenticatedRequest(req, res, tusHandler) if (req.headers.cookie) handleAuthenticatedRequest(req, res, tusHandler)
else { else {
@@ -41,7 +42,7 @@ export const handleTusUpload = (
} }
} else { } else {
setCorsHeaders(res) setCorsHeaders(res)
tusHandler.handle(req.raw, res.raw) void tusHandler.handle(req.raw, res.raw)
} }
} }
Regular → Executable
+12 -5
View File
@@ -28,6 +28,8 @@ enum Theme {
'Invalid DEFAULT_THEME environment variable, please select either light or dark' 'Invalid DEFAULT_THEME environment variable, please select either light or dark'
) )
logger.info(`Portfolio ${process.env.APP_VERSION}`)
const server = await createServer({ const server = await createServer({
logger, logger,
configureApiServer: async (server) => { configureApiServer: async (server) => {
@@ -52,7 +54,10 @@ enum Theme {
datastore: new FileStore({ datastore: new FileStore({
directory: `./files_${isProduction ? 'prod' : 'dev'}`, directory: `./files_${isProduction ? 'prod' : 'dev'}`,
}), }),
onResponseError: (_req, res, _err) => logger.error(res), onResponseError(_, err) {
logger.error(err)
return { status_code: 500, body: 'Internal Server Error' }
},
}) })
server.addContentTypeParser( server.addContentTypeParser(
@@ -60,12 +65,14 @@ enum Theme {
(_request, _payload, done) => done(null) (_request, _payload, done) => done(null)
) )
server.all('/files', (req, res) => server.all('/files', (req, res) => {
res.hijack()
handleTusUpload(req, res, tusServer, false) handleTusUpload(req, res, tusServer, false)
) })
server.all('/files/*', (req, res) => server.all('/files/*', (req, res) => {
res.hijack()
handleTusUpload(req, res, tusServer, true) handleTusUpload(req, res, tusServer, true)
) })
await server.start() await server.start()
})() })()
Regular → Executable
View File
View File
View File
View File
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+1 -1
View File
@@ -5,7 +5,7 @@
"esModuleInterop": true, "esModuleInterop": true,
"target": "ES2023", "target": "ES2023",
"module": "Node16", "module": "Node16",
"moduleResolution": "Node16", "moduleResolution": "node16",
"skipLibCheck": false, "skipLibCheck": false,
"rootDirs": [ "rootDirs": [
"./src", "./src",
Regular → Executable
+10 -3
View File
@@ -4,6 +4,7 @@ services:
portfolio: portfolio:
container_name: portfolio container_name: portfolio
image: git.altaiar.dev/ahmed/portfolio:latest image: git.altaiar.dev/ahmed/portfolio:latest
restart: unless-stopped
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- API_PROXY_TARGET=http://localhost:8911 - API_PROXY_TARGET=http://localhost:8911
@@ -32,7 +33,8 @@ services:
- 8910:8910 # Web - 8910:8910 # Web
- 8911:8911 # API - 8911:8911 # API
depends_on: depends_on:
- db db:
condition: service_healthy
volumes: volumes:
- files:/home/node/app/api/files_prod - files:/home/node/app/api/files_prod
command: > command: >
@@ -42,14 +44,19 @@ services:
yarn rw prisma db seed && yarn rw prisma db seed &&
yarn rw serve" yarn rw serve"
db: db:
container_name: portfolio-db container_name: portfolio-db
image: postgres:16-bookworm image: postgres:16-bookworm
environment: environment:
- POSTGRES_USER=redwood - POSTGRES_USER=redwood
- POSTGRES_PASSWORD=changeme - POSTGRES_PASSWORD=changeme # Change to a more secure password
- POSTGRES_DB=portfolio - POSTGRES_DB=portfolio
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d DATABASE_URL"] # Replace DATABASE_URL with the database URL from the portfolio container
interval: 10s
timeout: 5s
retries: 5
volumes: volumes:
- postgres:/var/lib/postgresql/data - postgres:/var/lib/postgresql/data
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+1 -1
View File
@@ -9,7 +9,7 @@
title = "${FIRST_NAME} ${LAST_NAME}" title = "${FIRST_NAME} ${LAST_NAME}"
port = 8910 port = 8910
apiUrl = "/api" apiUrl = "/api"
includeEnvironmentVariables = ["FIRST_NAME", "LAST_NAME", "COUNTRY", "STATE", "CITY", "DEFAULT_THEME", "API_ADDRESS_PROD", "API_ADDRESS_DEV"] includeEnvironmentVariables = ["FIRST_NAME", "LAST_NAME", "COUNTRY", "STATE", "CITY", "DEFAULT_THEME", "API_ADDRESS_PROD", "API_ADDRESS_DEV", "APP_VERSION"]
[generate] [generate]
tests = false tests = false
stories = false stories = false
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+2 -1
View File
@@ -41,7 +41,8 @@
"react": "18.3.1", "react": "18.3.1",
"react-colorful": "^5.6.1", "react-colorful": "^5.6.1",
"react-dom": "18.3.1", "react-dom": "18.3.1",
"react-html-parser": "^2.0.2" "react-html-parser": "^2.0.2",
"react-pdf": "^9.2.1"
}, },
"devDependencies": { "devDependencies": {
"@redwoodjs/vite": "8.4.0", "@redwoodjs/vite": "8.4.0",
Regular → Executable
View File
Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 757 B

After

Width:  |  Height:  |  Size: 757 B

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
View File
View File
View File
View File
View File
View File
View File
View File
Regular → Executable
+31 -18
View File
@@ -1,7 +1,15 @@
import { useState } from 'react' import { useState } from 'react'
import { mdiAlertOutline } from '@mdi/js' import { mdiOpenInNew } from '@mdi/js'
import Icon from '@mdi/react' import Icon from '@mdi/react'
import { Document, Page as PdfPage, pdfjs } from 'react-pdf'
import 'react-pdf/dist/Page/AnnotationLayer.css'
import 'react-pdf/dist/Page/TextLayer.css'
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.min.mjs',
import.meta.url
).toString()
interface PDFProps { interface PDFProps {
url: string url: string
@@ -9,28 +17,33 @@ interface PDFProps {
} }
const PDF = ({ url, form = false }: PDFProps) => { const PDF = ({ url, form = false }: PDFProps) => {
const [error, setError] = useState<boolean>(false) const [numPages, setNumPages] = useState<number>(0)
function onLoadSuccess({ numPages }: { numPages: number }) {
setNumPages(numPages)
}
return error ? ( return (
<div role="alert" className="alert alert-warning"> <div
<Icon path={mdiAlertOutline} className="size-7" /> className="overflow-y-auto flex justify-center"
<span>
Could not load PDF, this is common in in-app browsers, try opening this
page in a regular browser
</span>
</div>
) : (
<iframe
src={url}
title="PDF"
style={{ style={{
width: 'calc(100vw - 1rem)', width: 'calc(100vw - 1rem)',
height: `calc(100vh - ${form ? '8.5rem' : '6rem'})`, height: `calc(100vh - ${form ? '8.5rem' : '6rem'})`,
}} }}
className="rounded-xl" >
onError={() => setError(true)} <a
onLoad={() => setError(false)} href={url}
/> target="_blank"
rel="noopener noreferrer"
className="fixed top-20 left-0 z-10 m-2 p-2 rounded-xl btn btn-square btn-ghost shadow-lg"
>
<Icon path={mdiOpenInNew} size={1} className="text-gray-600" />
</a>
<Document file={url} onLoadSuccess={onLoadSuccess}>
{Array.from({ length: numPages }, (_, i) => (
<PdfPage key={i} pageNumber={i + 1} width={800} />
))}
</Document>
</div>
) )
} }
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File

Some files were not shown because too many files have changed in this diff Show More