Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 9 additions & 9 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
name: Setup
description: Setup Bun, cache dependencies, and install
description: Setup Node + pnpm, cache dependencies, and install

runs:
using: composite
steps:
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
bun-version: v1.3.10
version: 11.5.0

- name: Mount bun global cache
uses: useblacksmith/stickydisk@v1
- name: Setup Node
uses: actions/setup-node@v4
with:
key: ${{ github.repository }}-bun-cache
path: ~/.bun/install/cache
node-version-file: .nvmrc
cache: pnpm

- name: Mount node_modules
uses: useblacksmith/stickydisk@v1
Expand All @@ -23,4 +23,4 @@ runs:

- name: Install dependencies
shell: bash
run: bun install
run: pnpm install --frozen-lockfile
10 changes: 7 additions & 3 deletions .github/workflows/desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,15 @@ jobs:
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: pnpm/action-setup@v4
with:
bun-version: v1.3.10
version: 11.5.0
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: pnpm
- name: Install dependencies
run: bun install
run: pnpm install --frozen-lockfile
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: install Rust target
Expand Down
31 changes: 15 additions & 16 deletions .github/workflows/production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Detect affected services
id: affected
run: |
AFFECTED=$(bunx turbo build --affected --dry-run=json 2>/dev/null | jq -r '.packages[]' 2>/dev/null || echo "")
AFFECTED=$(pnpm exec turbo build --affected --dry-run=json 2>/dev/null | jq -r '.packages[]' 2>/dev/null || echo "")
echo "Affected packages: $AFFECTED"
echo "api=$(echo "$AFFECTED" | grep -q '@midday/api' && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
echo "dashboard=$(echo "$AFFECTED" | grep -q '@midday/dashboard' && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
Expand All @@ -52,11 +52,10 @@ jobs:

# ---------------------------------------------------------------------------
# Validate — runs in parallel with detect-changes
# TEMPORARILY DISABLED: set `if: false` to skip; remove to re-enable.
# Lint, typecheck (workbench built first), and test on Node 24 + pnpm.
# ---------------------------------------------------------------------------
validate:
name: Validate
if: false
runs-on: blacksmith-16vcpu-ubuntu-2404
timeout-minutes: 20
services:
Expand Down Expand Up @@ -87,20 +86,20 @@ jobs:
- name: Setup test database schema
run: |
PGPASSWORD=postgres psql -h localhost -p 5433 -U postgres -d midday_test -f src/test/helpers/setup-test-db.sql
bunx drizzle-kit push --config=drizzle.config.test.ts --force
pnpm exec drizzle-kit push --config=drizzle.config.test.ts --force
working-directory: packages/db

- name: Lint
run: bunx turbo lint --affected
run: pnpm exec turbo lint --affected

- name: Build required type dependencies
run: bunx turbo build --filter=workbench
run: pnpm exec turbo build --filter=workbench

- name: Typecheck
run: bunx turbo typecheck --affected
run: pnpm exec turbo typecheck --affected

- name: Test
run: bunx turbo test --affected
run: pnpm exec turbo test --affected

# ---------------------------------------------------------------------------
# Tool selection evals — runs when API changes to catch regressions
Expand All @@ -123,7 +122,7 @@ jobs:
run: cd node_modules/better-sqlite3 && npx --yes node-gyp rebuild

- name: Run tool selection evals
run: bun run eval:run
run: pnpm run eval:run
working-directory: apps/api

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -185,7 +184,7 @@ jobs:
env:
API_BASE_URL: ${{ secrets.PRODUCTION_API_URL }}
MIDDAY_API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
run: bun test --exit --timeout 60000 src/__tests__/e2e/
run: pnpm exec vitest run --testTimeout 60000 src/__tests__/e2e/
working-directory: apps/api

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -260,18 +259,18 @@ jobs:
- uses: ./.github/actions/setup

- name: Pull Vercel environment
run: bunx vercel env pull .env --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
run: pnpm dlx vercel env pull .env --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}

- name: Pull Vercel project config
run: bunx vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
run: pnpm dlx vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}

- name: Build
run: bunx vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
run: pnpm dlx vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}

- name: Deploy
run: |
bunx vercel deploy --prebuilt --prod --archive=tgz --token=${{ secrets.VERCEL_TOKEN }} > domain.txt
bunx vercel alias --scope=${{ secrets.VERCEL_ORG_ID }} --token=${{ secrets.VERCEL_TOKEN }} set $(cat domain.txt) midday.ai
pnpm dlx vercel deploy --prebuilt --prod --archive=tgz --token=${{ secrets.VERCEL_TOKEN }} > domain.txt
pnpm dlx vercel alias --scope=${{ secrets.VERCEL_ORG_ID }} --token=${{ secrets.VERCEL_TOKEN }} set $(cat domain.txt) midday.ai

# ---------------------------------------------------------------------------
# Deploy Jobs to Trigger.dev
Expand All @@ -294,5 +293,5 @@ jobs:
env:
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
run: |
TRIGGER_PROJECT_ID=${{ secrets.TRIGGER_PROJECT_ID }} bunx trigger.dev@4.1.2 deploy
TRIGGER_PROJECT_ID=${{ secrets.TRIGGER_PROJECT_ID }} pnpm dlx trigger.dev@4.1.2 deploy
working-directory: packages/jobs
27 changes: 13 additions & 14 deletions .github/workflows/staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Detect affected services
id: affected
run: |
AFFECTED=$(bunx turbo build --affected --dry-run=json 2>/dev/null | jq -r '.packages[]' 2>/dev/null || echo "")
AFFECTED=$(pnpm exec turbo build --affected --dry-run=json 2>/dev/null | jq -r '.packages[]' 2>/dev/null || echo "")
echo "Affected packages: $AFFECTED"
echo "api=$(echo "$AFFECTED" | grep -q '@midday/api' && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
echo "dashboard=$(echo "$AFFECTED" | grep -q '@midday/dashboard' && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
Expand All @@ -52,11 +52,10 @@ jobs:

# ---------------------------------------------------------------------------
# Validate — runs in parallel with detect-changes
# TEMPORARILY DISABLED: set `if: false` to skip; remove to re-enable.
# Lint, typecheck (workbench built first), and test on Node 24 + pnpm.
# ---------------------------------------------------------------------------
validate:
name: Validate
if: false
runs-on: blacksmith-16vcpu-ubuntu-2404
timeout-minutes: 20
services:
Expand Down Expand Up @@ -87,20 +86,20 @@ jobs:
- name: Setup test database schema
run: |
PGPASSWORD=postgres psql -h localhost -p 5433 -U postgres -d midday_test -f src/test/helpers/setup-test-db.sql
bunx drizzle-kit push --config=drizzle.config.test.ts --force
pnpm exec drizzle-kit push --config=drizzle.config.test.ts --force
working-directory: packages/db

- name: Lint
run: bunx turbo lint --affected
run: pnpm exec turbo lint --affected

- name: Build required type dependencies
run: bunx turbo build --filter=workbench
run: pnpm exec turbo build --filter=workbench

- name: Typecheck
run: bunx turbo typecheck --affected
run: pnpm exec turbo typecheck --affected

- name: Test
run: bunx turbo test --affected
run: pnpm exec turbo test --affected

# ---------------------------------------------------------------------------
# Tool selection evals — runs when API changes to catch regressions
Expand All @@ -123,7 +122,7 @@ jobs:
run: cd node_modules/better-sqlite3 && npx --yes node-gyp rebuild

- name: Run tool selection evals
run: bun run eval:run
run: pnpm run eval:run
working-directory: apps/api

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -185,7 +184,7 @@ jobs:
env:
API_BASE_URL: ${{ secrets.STAGING_API_URL }}
MIDDAY_API_KEY: ${{ secrets.STAGING_API_KEY }}
run: bun test --exit --timeout 60000 src/__tests__/e2e/
run: pnpm exec vitest run --testTimeout 60000 src/__tests__/e2e/
working-directory: apps/api

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -259,7 +258,7 @@ jobs:
env:
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
run: |
TRIGGER_PROJECT_ID=${{ secrets.TRIGGER_PROJECT_ID }} bunx trigger.dev@4.1.2 deploy --env staging
TRIGGER_PROJECT_ID=${{ secrets.TRIGGER_PROJECT_ID }} pnpm dlx trigger.dev@4.1.2 deploy --env staging
working-directory: packages/jobs

# ---------------------------------------------------------------------------
Expand All @@ -283,10 +282,10 @@ jobs:
- uses: ./.github/actions/setup

- name: Pull Vercel environment
run: bunx vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
run: pnpm dlx vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}

- name: Build
run: bunx vercel build --token=${{ secrets.VERCEL_TOKEN }}
run: pnpm dlx vercel build --token=${{ secrets.VERCEL_TOKEN }}

- name: Deploy
run: bunx vercel deploy --prebuilt --archive=tgz --token=${{ secrets.VERCEL_TOKEN }}
run: pnpm dlx vercel deploy --prebuilt --archive=tgz --token=${{ secrets.VERCEL_TOKEN }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,5 @@ dist-ssr
.matching-eval-history.json

# Toolpick embedding cache (auto-generated on first boot)
.toolpick-cache.json
.toolpick-cache.json
.env*
5 changes: 5 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# React 19 / peer-heavy graph: install peers automatically, don't hard-fail on
# peer mismatches. node_modules layout is pnpm's default (isolated/symlinked) so
# undeclared (phantom) deps surface as errors — fix by declaring them explicitly.
auto-install-peers=true
strict-peer-dependencies=false
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
18 changes: 12 additions & 6 deletions apps/api/.env-template
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Resend
RESEND_API_KEY=

# Supabase
SUPABASE_SECRET_KEY=
SUPABASE_URL=
# Legacy HS256 fallback — remove after revoking the legacy JWT secret in Supabase
SUPABASE_JWT_SECRET=
# Auth (better-auth)
BETTER_AUTH_SECRET=
BETTER_AUTH_URL=http://localhost:3001

# Supabase - Database (use pooler URLs via pooler.supabase.com)
# Database (Neon)
DATABASE_URL=
DATABASE_URL_UNPOOLED=
DATABASE_PRIMARY_URL="" # Primary (Frankfurt)

# Read replicas — only the current region's replica is used at runtime
Expand All @@ -31,6 +31,12 @@ TELLER_CERT_BASE64=
TELLER_KEY_BASE64=
TELLER_SIGNING_SECRET=

# Vercel Blob Storage
# midday-vault store (PRIVATE — documents/inbox/attachments/invoices/insights)
BLOB_VAULT_READ_WRITE_TOKEN=
# midday-public store (PUBLIC — avatars/apps)
BLOB_PUBLIC_READ_WRITE_TOKEN=

# R2 Storage (institution logos)
R2_ENDPOINT=
R2_ACCESS_KEY_ID=
Expand Down
44 changes: 28 additions & 16 deletions apps/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,39 +1,48 @@
# Base image with Bun
FROM oven/bun:1.3.10 AS base

# Install turbo CLI globally
FROM base AS turbo-cli
RUN bun add -g turbo
# Node 24 base with pnpm via corepack
FROM node:24-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
RUN corepack enable

# Builder stage - prune API workspace
FROM turbo-cli AS builder
FROM base AS builder
WORKDIR /app
RUN pnpm add -g turbo
COPY . .
RUN turbo prune @midday/api --docker

# Installer stage - install deps and build
FROM base AS installer
WORKDIR /app

# Install dependencies
# Native module build deps (sharp / better-sqlite3 / canvas via node-gyp)
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 \
build-essential \
&& rm -rf /var/lib/apt/lists/*

# Install from the pruned lockfile. turbo prune --docker emits pnpm-lock.yaml,
# pnpm-workspace.yaml (catalog + overrides) and .npmrc into out/json. The
# overrides reference the vendored xlsx tarball, so copy vendor/ as well.
COPY --from=builder /app/out/json/ .
COPY bunfig.toml .
RUN bun install
COPY --from=builder /app/vendor ./vendor
RUN pnpm install --frozen-lockfile

# Copy full source
COPY --from=builder /app/out/full/ .

# Build the mcp-apps package (produces self-contained HTML files)
RUN cd packages/mcp-apps && bun run build
# Build the mcp-apps package (vite -> dist/ HTML files served at runtime)
RUN pnpm --filter @midday/mcp-apps build

# Runner stage - clean image
FROM oven/bun:1.3.10 AS runner
# Runner stage
FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV PORT=8080

# Copy only what's needed at runtime
# Copy the installed workspace (node_modules symlinks point into packages/*)
COPY --from=installer /app/node_modules ./node_modules
COPY --from=installer /app/apps/api ./apps/api
COPY --from=installer /app/packages ./packages
Expand All @@ -49,4 +58,7 @@ WORKDIR /app/apps/api
EXPOSE 8080

ENTRYPOINT ["/app/entrypoint.sh"]
CMD ["bun", "src/index.ts"]
# Run TypeScript directly on Node 24 via tsx (preserves require.resolve + runtime
# asset reads that an ESM bundle would break). `node --import tsx` resolves tsx
# from the workspace root node_modules.
CMD ["node", "--import", "tsx", "src/index.ts"]
1 change: 0 additions & 1 deletion apps/api/bunfig.toml

This file was deleted.

Loading
Loading