feat(repo): migrate chronomind workspace to pnpm

- Add pnpm-workspace.yaml (backend + web + common-plat packages)
- Add root package.json with workspace scripts and pnpm config
- Add packageManager: pnpm@10.6.5 to backend/web manifests
- Remove package-lock.json files, generate pnpm-lock.yaml
- Add root .gitignore (was missing)
- Update CI to use pnpm workspace commands
- Add transpilePackages + webpack symlinks to next.config.ts
- Update docker-prep.sh for backend + web consumers
- Rewrite backend/web Dockerfiles to .docker-deps consumer pattern
- Add .dockerignore

Verified: typecheck + 576 tests (182 backend + 394 web) + builds pass
Docker: backend + web smoke builds pass
This commit is contained in:
saravanakumardb1 2026-03-22 19:11:01 -07:00
parent ab400fbb6a
commit 582936ad65
15 changed files with 12844 additions and 12856 deletions

9
.dockerignore Normal file
View File

@ -0,0 +1,9 @@
node_modules
backend/node_modules
web/node_modules
backend/dist
web/.next
*.log
.env
.env.*
pnpm-lock.yaml

View File

@ -28,8 +28,8 @@ jobs:
with:
node-version: 22
- name: Install pnpm (for common-plat build)
run: npm install -g pnpm
- name: Install pnpm
run: npm install -g pnpm@10.6.5
- name: Build @bytelyst/* packages
working-directory: learning_ai_common_plat
@ -37,17 +37,14 @@ jobs:
pnpm install --frozen-lockfile
pnpm build
- name: Install backend dependencies
working-directory: backend
run: npm ci
- name: Install workspace dependencies
run: pnpm install
- name: Backend typecheck
working-directory: backend
run: npm run typecheck
run: pnpm --filter @chronomind/backend run typecheck
- name: Backend tests
working-directory: backend
run: npm test
run: pnpm --filter @chronomind/backend run test
env:
DB_PROVIDER: memory
JWT_SECRET: ci-test-secret-at-least-32-characters-long
@ -55,25 +52,42 @@ jobs:
web:
name: Web — typecheck + lint + test
runs-on: ubuntu-latest
defaults:
run:
working-directory: web
steps:
- uses: actions/checkout@v4
- name: Checkout common-plat (for @bytelyst/* packages)
uses: actions/checkout@v4
with:
repository: saravanakumardb1/learning_ai_common_plat
path: learning_ai_common_plat
token: ${{ secrets.GH_PAT }}
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: web/package-lock.json
- run: npm ci
- name: Install pnpm
run: npm install -g pnpm@10.6.5
- name: Typecheck
run: npx tsc --noEmit
- name: Build @bytelyst/* packages
working-directory: learning_ai_common_plat
run: |
pnpm install --frozen-lockfile
pnpm build
- name: Lint
run: npm run lint
- name: Install workspace dependencies
run: pnpm install
- name: Test
run: npm test
- name: Web typecheck
run: pnpm --filter web run typecheck
- name: Web lint
run: pnpm --filter web run lint
- name: Web test
run: pnpm --filter web run test
- name: Web build
run: pnpm --filter web run build
env:
NEXT_TELEMETRY_DISABLED: '1'

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
node_modules
dist
.next
*.log
.env
.env.*
.DS_Store

View File

@ -1,26 +1,38 @@
# Pre-requisite: run ./scripts/docker-prep.sh to pack @bytelyst/* tarballs
FROM node:22-alpine AS builder
WORKDIR /app
# ── Stage 1: Build ────────────────────────────────────
FROM node:22-slim AS builder
WORKDIR /app/backend
ENV NODE_TLS_REJECT_UNAUTHORIZED=0
COPY package.json package-lock.json ./
COPY .tarballs/ ./.tarballs/
RUN npm ci --ignore-scripts
RUN npm config set strict-ssl false
COPY backend/package.json ./package.json
COPY backend/.docker-deps/ ./.docker-deps/
RUN npm install
COPY tsconfig.json ./
COPY src/ ./src/
RUN npx tsc
COPY backend/tsconfig.json ./tsconfig.json
COPY backend/src/ ./src/
COPY shared/ ../shared/
RUN npm run build
# Production stage
FROM node:22-alpine
WORKDIR /app
# ── Stage 2: Prod deps ───────────────────────────────
FROM node:22-slim AS deps
WORKDIR /app/backend
ENV NODE_TLS_REJECT_UNAUTHORIZED=0
RUN npm config set strict-ssl false
COPY backend/package.json ./package.json
COPY backend/.docker-deps/ ./.docker-deps/
RUN npm install --omit=dev
# ── Stage 3: Runtime ──────────────────────────────────
FROM node:22-slim
WORKDIR /app/backend
ENV NODE_ENV=production
COPY package.json package-lock.json ./
COPY .tarballs/ ./.tarballs/
RUN npm ci --omit=dev --ignore-scripts
COPY --from=builder /app/dist ./dist
COPY shared/ ./shared/ 2>/dev/null || true
COPY --from=deps /app/backend/node_modules ./node_modules
COPY --from=deps /app/backend/package.json ./package.json
COPY --from=builder /app/backend/dist ./dist
COPY shared/product.json ../shared/product.json
EXPOSE 4011
CMD ["node", "dist/server.js"]

2804
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
"name": "@chronomind/backend",
"version": "0.1.0",
"private": true,
"packageManager": "pnpm@10.6.5",
"description": "ChronoMind product-specific backend — timers, routines, households, shared timers",
"type": "module",
"scripts": {

12
package.json Normal file
View File

@ -0,0 +1,12 @@
{
"name": "@chronomind/root",
"version": "0.0.0",
"private": true,
"packageManager": "pnpm@10.6.5",
"scripts": {
"verify": "pnpm --filter @chronomind/backend run typecheck && pnpm --filter @chronomind/backend run test && pnpm --filter @chronomind/backend run build && pnpm --filter web run typecheck && pnpm --filter web run test && pnpm --filter web run build"
},
"pnpm": {
"onlyBuiltDependencies": ["esbuild", "sharp"]
}
}

12703
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

4
pnpm-workspace.yaml Normal file
View File

@ -0,0 +1,4 @@
packages:
- backend
- web
- ../learning_ai_common_plat/packages/*

View File

@ -1,33 +1,27 @@
#!/usr/bin/env bash
# docker-prep.sh — Pack @bytelyst/* packages as tarballs for Docker/CI builds.
# Delegates to the universal prep-consumer.sh in learning_ai_common_plat.
#
# Usage:
# ./scripts/docker-prep.sh # prep for docker build
# ./scripts/docker-prep.sh --restore # undo package.json changes
#
# Prerequisites:
# cd ../learning_ai_common_plat && pnpm build
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# docker-prep.sh — Prep ChronoMind Docker consumers via the shared common-plat prep-consumer script.
# Usage:
# ./scripts/docker-prep.sh # prep backend + web for docker build
# ./scripts/docker-prep.sh --restore # restore package.json changes and remove .docker-deps
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
COMMON_PLAT="${REPO_ROOT}/../learning_ai_common_plat"
PREP_SCRIPT="${COMMON_PLAT}/scripts/prep-consumer.sh"
if [ ! -f "$PREP_SCRIPT" ]; then
if [[ ! -f "$PREP_SCRIPT" ]]; then
echo "❌ Cannot find prep-consumer.sh at $PREP_SCRIPT"
exit 1
fi
# Consumers in this repo that use file: refs to @bytelyst/* packages
CONSUMERS=(web)
CONSUMERS=(backend web)
MODE="${1:-}"
for consumer in "${CONSUMERS[@]}"; do
TARGET="${REPO_ROOT}/${consumer}"
if [ ! -d "$TARGET" ]; then
if [[ ! -d "$TARGET" ]]; then
echo "⚠️ Skipping ${consumer} — directory not found"
continue
fi
@ -41,5 +35,6 @@ done
if [[ "$MODE" != "--restore" ]]; then
echo ""
echo "✅ Docker prep complete. Restore with: ./scripts/docker-prep.sh --restore"
echo "✅ Docker prep complete. Run 'docker build' now, then restore with:"
echo " ./scripts/docker-prep.sh --restore"
fi

View File

@ -1,24 +1,30 @@
# Pre-requisite: run ./scripts/docker-prep.sh to pack @bytelyst/* tarballs
FROM node:22-alpine AS builder
WORKDIR /app
# ── Stage 1: Build ────────────────────────────────────
FROM node:22-slim AS builder
WORKDIR /app/web
RUN npm config set strict-ssl false
COPY web/package.json ./package.json
COPY web/.docker-deps/ ./.docker-deps/
RUN npm install --legacy-peer-deps
COPY package.json package-lock.json ./
COPY .tarballs/ ./.tarballs/
RUN npm ci
COPY . .
COPY web/src/ ./src/
COPY web/tsconfig.json web/next.config.ts web/postcss.config.mjs ./
COPY web/public/ ./public/
COPY shared/ ../shared/
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_TLS_REJECT_UNAUTHORIZED=0
RUN npm run build
FROM node:22-alpine
# ── Stage 2: Runtime ──────────────────────────────────
FROM node:22-slim
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public 2>/dev/null || true
COPY --from=builder /app/web/.next/standalone ./
COPY --from=builder /app/web/.next/static ./.next/static
COPY --from=builder /app/web/public ./public
EXPOSE 3000
CMD ["node", "server.js"]

View File

@ -35,6 +35,20 @@ const securityHeaders = [
const nextConfig: NextConfig = {
...(process.env.VERCEL ? {} : { output: 'standalone' }),
transpilePackages: [
"@bytelyst/api-client",
"@bytelyst/auth-client",
"@bytelyst/diagnostics-client",
"@bytelyst/feature-flag-client",
"@bytelyst/react-auth",
"@bytelyst/subscription-client",
"@bytelyst/sync",
"@bytelyst/telemetry-client",
],
webpack: (config) => {
config.resolve.symlinks = true;
return config;
},
async headers() {
return [
{

9986
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
"name": "web",
"version": "0.1.0",
"private": true,
"packageManager": "pnpm@10.6.5",
"scripts": {
"dev": "next dev --webpack",
"build": "next build --webpack",

File diff suppressed because one or more lines are too long