From e7f70b9295feb1d141f7d88c3ab9e8aa48a534e5 Mon Sep 17 00:00:00 2001 From: Linus Miller Date: Sun, 23 Nov 2025 23:30:02 +0100 Subject: [PATCH] intial server setup --- .env.development | 13 +- Dockerfile | 19 +- client/client.d.ts | 6 + client/public/client.ts | 8 + client/public/components/app.module.scss | 3 + client/public/components/app.tsx | 36 + client/public/components/error_page.tsx | 15 + client/public/components/footer.tsx | 5 + client/public/components/head.ts | 172 +++++ client/public/components/header.tsx | 18 + client/public/components/not_found_page.tsx | 5 + client/public/components/other_page.tsx | 15 + client/public/components/start_page.tsx | 11 + client/public/routes.ts | 17 + client/public/server.ts | 22 + .../shared/components/button_factory.tsx | 62 ++ .../shared/components/checkbox_factory.tsx | 77 ++ .../components/image_upload_factory.tsx | 70 ++ .../shared/components/input_factory.tsx | 144 ++++ .../shared/components/link_button_factory.tsx | 55 ++ .../components/message_factory.test.tsx | 32 + .../shared/components/message_factory.tsx | 34 + client/public/shared/components/portal.tsx | 6 + .../shared/components/select_factory.tsx | 116 +++ .../shared/components/textarea_factory.tsx | 88 +++ .../public/shared/hooks/use_request_state.ts | 58 ++ client/public/shared/styles/_breakpoints.scss | 66 ++ client/public/shared/styles/_flex.scss | 60 ++ client/public/shared/styles/_reset.scss | 154 ++++ client/public/shared/styles/_units.scss | 92 +++ client/public/shared/styles/_utils.scss | 74 ++ client/public/shared/utils/disable_scroll.ts | 20 + client/public/shared/utils/escape_regex.ts | 3 + client/public/shared/utils/is_loading.ts | 3 + client/public/shared/utils/merge_styles.ts | 19 + .../shared/utils/serialize_form.test.ts | 115 +++ client/public/shared/utils/serialize_form.ts | 30 + client/public/styles/main.scss | 5 + client/test/tsx_hook.ts | 2 +- docker-compose.yml | 31 + global.d.ts | 7 - package.json | 13 +- pnpm-lock.yaml | 696 ++++++++++++++++++ server/env.ts | 29 +- server/handlers/error.ts | 39 + server/handlers/robots.ts | 18 + server/index.ts | 25 + server/lib/console.ts | 19 + server/lib/html.ts | 79 ++ server/lib/parse_stream.ts | 3 - server/lib/pino_transport_console.ts | 71 ++ server/plugins/vite.ts | 52 ++ server/plugins/vite/development.ts | 130 ++++ server/plugins/vite/production.ts | 166 +++++ server/routes/api.ts | 63 ++ server/server.ts | 32 + server/templates/public.ts | 28 + tsconfig.json | 2 +- vite.config.js | 2 +- 59 files changed, 3224 insertions(+), 31 deletions(-) create mode 100644 client/client.d.ts create mode 100644 client/public/client.ts create mode 100644 client/public/components/app.module.scss create mode 100644 client/public/components/app.tsx create mode 100644 client/public/components/error_page.tsx create mode 100644 client/public/components/footer.tsx create mode 100644 client/public/components/head.ts create mode 100644 client/public/components/header.tsx create mode 100644 client/public/components/not_found_page.tsx create mode 100644 client/public/components/other_page.tsx create mode 100644 client/public/components/start_page.tsx create mode 100644 client/public/routes.ts create mode 100644 client/public/server.ts create mode 100644 client/public/shared/components/button_factory.tsx create mode 100644 client/public/shared/components/checkbox_factory.tsx create mode 100644 client/public/shared/components/image_upload_factory.tsx create mode 100644 client/public/shared/components/input_factory.tsx create mode 100644 client/public/shared/components/link_button_factory.tsx create mode 100644 client/public/shared/components/message_factory.test.tsx create mode 100644 client/public/shared/components/message_factory.tsx create mode 100644 client/public/shared/components/portal.tsx create mode 100644 client/public/shared/components/select_factory.tsx create mode 100644 client/public/shared/components/textarea_factory.tsx create mode 100644 client/public/shared/hooks/use_request_state.ts create mode 100644 client/public/shared/styles/_breakpoints.scss create mode 100644 client/public/shared/styles/_flex.scss create mode 100644 client/public/shared/styles/_reset.scss create mode 100644 client/public/shared/styles/_units.scss create mode 100644 client/public/shared/styles/_utils.scss create mode 100644 client/public/shared/utils/disable_scroll.ts create mode 100644 client/public/shared/utils/escape_regex.ts create mode 100644 client/public/shared/utils/is_loading.ts create mode 100644 client/public/shared/utils/merge_styles.ts create mode 100644 client/public/shared/utils/serialize_form.test.ts create mode 100644 client/public/shared/utils/serialize_form.ts create mode 100644 client/public/styles/main.scss create mode 100644 server/handlers/error.ts create mode 100644 server/handlers/robots.ts create mode 100644 server/index.ts create mode 100644 server/lib/console.ts create mode 100644 server/lib/html.ts create mode 100644 server/lib/pino_transport_console.ts create mode 100644 server/plugins/vite.ts create mode 100644 server/plugins/vite/development.ts create mode 100644 server/plugins/vite/production.ts create mode 100644 server/routes/api.ts create mode 100644 server/server.ts create mode 100644 server/templates/public.ts diff --git a/.env.development b/.env.development index c1383a3..e0a13d7 100644 --- a/.env.development +++ b/.env.development @@ -1,5 +1,16 @@ -PGHOST=localhost +NODE_ENV=development +DOMAIN=bitmill.io +PROTOCOL=https +HOSTNAME=brf.local +PORT=null +FASTIFY_HOST=0.0.0.0 +FASTIFY_PORT=1337 +LOG_LEVEL=debug +LOG_STREAM=console +PGHOST=postgres PGPORT=5432 PGDATABASE=brf_books PGUSER=brf_books PGPASSWORD=brf_books +REDIS_HOST=redis +VITE_HMR_PROXY=true diff --git a/Dockerfile b/Dockerfile index b4c39f5..9649a8c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,24 @@ -FROM node:23-alpine AS base +FROM node:25-alpine AS base ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" -RUN corepack enable pnpm ARG UID=1000 ARG GID=1000 -RUN apk add --no-cache git shadow +RUN apk add --no-cache shadow +RUN npm install -g pnpm@^10.23.0 RUN groupmod -g $GID node # this does not seem to be having full effect. eg /home/node gets 1337:1000 ownership despite group node having id 1337 RUN usermod -u $UID -g node node USER node -RUN mkdir /home/node/startbit -RUN git config --global --add safe.directory /home/node/startbit -WORKDIR /home/node/startbit +RUN mkdir /home/node/brf_books +WORKDIR /home/node/brf_books -COPY --chown=node pnpm-lock.yaml package.json ./ +COPY --chown=node pnpm-lock.yaml package.json . RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile -COPY --chown=node \ - .env.secrets \ - vite.config.js ./ +COPY --chown=node vite.config.js . # -------- development -------- # FROM base AS development @@ -42,4 +39,4 @@ RUN pnpm run build COPY --chown=node .git .git -CMD pnpm run start server/index.ts +CMD pnpm run start diff --git a/client/client.d.ts b/client/client.d.ts new file mode 100644 index 0000000..12da21c --- /dev/null +++ b/client/client.d.ts @@ -0,0 +1,6 @@ +declare module '*.module.scss' { + const classNames: Record + export default classNames +} + +declare module '*.scss' diff --git a/client/public/client.ts b/client/public/client.ts new file mode 100644 index 0000000..48fe099 --- /dev/null +++ b/client/public/client.ts @@ -0,0 +1,8 @@ +import './styles/main.scss' + +import { h, hydrate } from 'preact' +import App from './components/app.tsx' + +const STATE = typeof __STATE__ !== 'undefined' ? __STATE__ : undefined + +hydrate(h(App, STATE), document.body) diff --git a/client/public/components/app.module.scss b/client/public/components/app.module.scss new file mode 100644 index 0000000..55e7d1b --- /dev/null +++ b/client/public/components/app.module.scss @@ -0,0 +1,3 @@ +.title { + font-size: 120px; +} diff --git a/client/public/components/app.tsx b/client/public/components/app.tsx new file mode 100644 index 0000000..8c121f6 --- /dev/null +++ b/client/public/components/app.tsx @@ -0,0 +1,36 @@ +import { h } from 'preact' +import { Router } from 'preact-router' +import Head from './head.ts' +import Footer from './footer.tsx' +import Header from './header.tsx' +import ErrorPage from './error_page.tsx' +import routes from '../routes.ts' + +import s from './app.module.scss' + +export default function App({ error, url, title }) { + return ( +
+ + {title || 'Untitled'} + + +
+ +
+ {error ? ( + + ) : ( + + {routes.map((route) => ( + // @ts-ignore + + ))} + + )} +
+ +
+
+ ) +} diff --git a/client/public/components/error_page.tsx b/client/public/components/error_page.tsx new file mode 100644 index 0000000..35764e1 --- /dev/null +++ b/client/public/components/error_page.tsx @@ -0,0 +1,15 @@ +import { h } from 'preact' +import Head from './head.ts' + +const OtherPage = ({ error }) => ( +
+ + : Error + + +

Oh no!

+
{JSON.stringify(error, ['name', ...Object.getOwnPropertyNames(error)], '  ')}
+
+) + +export default OtherPage diff --git a/client/public/components/footer.tsx b/client/public/components/footer.tsx new file mode 100644 index 0000000..861be7c --- /dev/null +++ b/client/public/components/footer.tsx @@ -0,0 +1,5 @@ +import { h } from 'preact' + +const Footer = () =>