mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-05-19 10:28:48 +02:00
Compare commits
6 Commits
097fe9c4cf
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20b4ad102d | ||
|
|
ec716e698f | ||
|
|
f556c392fb | ||
|
|
aa4bb6512f | ||
|
|
6b3069eef4 | ||
|
|
ead8fb8684 |
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
@@ -23,6 +23,8 @@ jobs:
|
|||||||
LETSENCRYPT_EMAIL=${{ secrets.LETSENCRYPT_EMAIL }}
|
LETSENCRYPT_EMAIL=${{ secrets.LETSENCRYPT_EMAIL }}
|
||||||
VAPID_PRIVATE_KEY=${{ secrets.VAPID_PRIVATE_KEY }}
|
VAPID_PRIVATE_KEY=${{ secrets.VAPID_PRIVATE_KEY }}
|
||||||
VAPID_PUBLIC_KEY=${{ secrets.VAPID_PUBLIC_KEY }}
|
VAPID_PUBLIC_KEY=${{ secrets.VAPID_PUBLIC_KEY }}
|
||||||
|
OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }}
|
||||||
|
AGENT_MODEL=${{ secrets.AGENT_MODEL }}
|
||||||
ENVEOF
|
ENVEOF
|
||||||
sed -i 's/^[[:space:]]*//' .env.prod
|
sed -i 's/^[[:space:]]*//' .env.prod
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,11 @@ def get_recent_transactions(
|
|||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
"""Recent transactions, newest first. Use filters to narrow down. For
|
"""Recent transactions, newest first. Use filters to narrow down. For
|
||||||
billing-cycle scoped totals prefer get_cycle_summary."""
|
billing-cycle scoped totals prefer get_cycle_summary."""
|
||||||
q = select(Transaction)
|
q = select(Transaction).where(
|
||||||
|
col(Transaction.transaction_type).notin_(
|
||||||
|
[TransactionType.SALARY, TransactionType.DEPOSITO]
|
||||||
|
)
|
||||||
|
)
|
||||||
if source:
|
if source:
|
||||||
q = q.where(Transaction.source == TransactionSource(source))
|
q = q.where(Transaction.source == TransactionSource(source))
|
||||||
if category_id is not None:
|
if category_id is not None:
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
BACKEND_URL: http://backend:8000
|
BACKEND_URL: http://wealthysmart-backend-prod:8000
|
||||||
AGENT_URL: http://backend:8000/api/v1/agent/agui
|
AGENT_URL: http://wealthysmart-backend-prod:8000/api/v1/agent/agui
|
||||||
JWT_SECRET: ${SECRET_KEY}
|
JWT_SECRET: ${SECRET_KEY}
|
||||||
COOKIE_DOMAIN: wealth.cescalante.dev
|
COOKIE_DOMAIN: wealth.cescalante.dev
|
||||||
COOKIE_SECURE: "true"
|
COOKIE_SECURE: "true"
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ FROM node:22-alpine AS builder
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
COPY . .
|
COPY . .
|
||||||
|
# Cap node heap so a build on a small VPS can't OOM-kill neighbours.
|
||||||
|
ENV NODE_OPTIONS=--max-old-space-size=1536
|
||||||
RUN corepack enable && pnpm build
|
RUN corepack enable && pnpm build
|
||||||
|
|
||||||
# Production: Hono serves dist/ + /api/copilotkit on port 3000
|
# Production: Hono serves dist/ + /api/copilotkit on port 3000
|
||||||
@@ -34,4 +36,4 @@ COPY server.ts package.json ./
|
|||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
|
||||||
CMD wget -qO- http://127.0.0.1:3000/api/health || exit 1
|
CMD wget -qO- http://127.0.0.1:3000/api/health || exit 1
|
||||||
CMD ["sh", "-c", "corepack enable && tsx server.ts"]
|
CMD ["./node_modules/.bin/tsx", "server.ts"]
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { Hono } from "hono";
|
|||||||
|
|
||||||
const AGENT_URL =
|
const AGENT_URL =
|
||||||
process.env.AGENT_URL ?? "http://backend:8000/api/v1/agent/agui";
|
process.env.AGENT_URL ?? "http://backend:8000/api/v1/agent/agui";
|
||||||
|
const BACKEND_URL =
|
||||||
|
process.env.BACKEND_URL ?? "http://localhost:8001";
|
||||||
|
|
||||||
const isProd = process.env.NODE_ENV === "production";
|
const isProd = process.env.NODE_ENV === "production";
|
||||||
const PORT = parseInt(process.env.PORT ?? (isProd ? "3000" : "3001"));
|
const PORT = parseInt(process.env.PORT ?? (isProd ? "3000" : "3001"));
|
||||||
@@ -376,6 +378,32 @@ app.all("/api/copilotkit/*", async (c) => {
|
|||||||
|
|
||||||
app.get("/api/health", (c) => c.json({ ok: true }));
|
app.get("/api/health", (c) => c.json({ ok: true }));
|
||||||
|
|
||||||
|
// Proxy backend API calls (FastAPI). In dev these hit Vite's proxy directly,
|
||||||
|
// but in prod the browser talks to this Hono server, which must forward
|
||||||
|
// `/api/v1/*` and `/api/auth/*` to the FastAPI container — otherwise the SPA
|
||||||
|
// fallback below swallows them and returns index.html.
|
||||||
|
const proxyToBackend = async (c: import("hono").Context) => {
|
||||||
|
const url = new URL(c.req.url);
|
||||||
|
const target = `${BACKEND_URL}${url.pathname}${url.search}`;
|
||||||
|
const method = c.req.method;
|
||||||
|
const headers = new Headers(c.req.raw.headers);
|
||||||
|
headers.delete("host");
|
||||||
|
const init: RequestInit = {
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
redirect: "manual",
|
||||||
|
};
|
||||||
|
if (method !== "GET" && method !== "HEAD") {
|
||||||
|
init.body = c.req.raw.body;
|
||||||
|
// @ts-expect-error undici requires duplex for streamed bodies
|
||||||
|
init.duplex = "half";
|
||||||
|
}
|
||||||
|
return fetch(target, init);
|
||||||
|
};
|
||||||
|
|
||||||
|
app.all("/api/v1/*", proxyToBackend);
|
||||||
|
app.all("/api/auth/*", proxyToBackend);
|
||||||
|
|
||||||
// In production, serve the Vite build output.
|
// In production, serve the Vite build output.
|
||||||
if (isProd) {
|
if (isProd) {
|
||||||
app.use("/*", serveStatic({ root: "./dist" }));
|
app.use("/*", serveStatic({ root: "./dist" }));
|
||||||
|
|||||||
Reference in New Issue
Block a user