feat(repo): migrate notelett workspace to pnpm

This commit is contained in:
saravanakumardb1 2026-03-22 15:50:54 -07:00
parent b40097633f
commit 90dd2d3bd5
21 changed files with 14329 additions and 26264 deletions

17
.dockerignore Normal file
View File

@ -0,0 +1,17 @@
node_modules
**/node_modules
.git
.next
**/.next
coverage
**/coverage
dist
**/dist
.turbo
pnpm-debug.log*
npm-debug.log*
.DS_Store
backend/package-lock.json
web/package-lock.json
mobile/package-lock.json
package-lock.json

View File

@ -27,9 +27,11 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install pnpm (for common-plat build)
run: npm install -g pnpm
- name: Enable pnpm
run: corepack enable
- name: Build @bytelyst/* packages
working-directory: learning_ai_common_plat
@ -37,55 +39,85 @@ jobs:
pnpm install --frozen-lockfile
pnpm build
- name: Install backend dependencies
working-directory: backend
run: npm ci
- name: Install workspace dependencies
run: pnpm install --frozen-lockfile
- name: Backend typecheck
working-directory: backend
run: npm run typecheck
run: pnpm --filter @notelett/backend run typecheck
- name: Backend tests
working-directory: backend
run: npm test
run: pnpm --filter @notelett/backend run test
env:
DB_PROVIDER: memory
JWT_SECRET: ci-test-secret-at-least-32-characters-long
- name: Backend build
working-directory: backend
run: npm run build
run: pnpm --filter @notelett/backend run build
web:
name: Web — typecheck + test + build
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
- run: npm run typecheck
- run: npm test
- run: npm run build
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Enable pnpm
run: corepack enable
- name: Build @bytelyst/* packages
working-directory: learning_ai_common_plat
run: |
pnpm install --frozen-lockfile
pnpm build
- name: Install workspace dependencies
run: pnpm install --frozen-lockfile
- run: pnpm --filter @notelett/web run typecheck
- run: pnpm --filter @notelett/web run test
- run: pnpm --filter @notelett/web run build
mobile:
name: Mobile — typecheck
runs-on: ubuntu-latest
defaults:
run:
working-directory: mobile
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: mobile/package-lock.json
- run: npm ci
- run: npm run typecheck
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Enable pnpm
run: corepack enable
- name: Build @bytelyst/* packages
working-directory: learning_ai_common_plat
run: |
pnpm install --frozen-lockfile
pnpm build
- name: Install workspace dependencies
run: pnpm install --frozen-lockfile
- run: pnpm --filter @notelett/mobile run typecheck

View File

@ -202,20 +202,23 @@ learning_ai_notes/
```bash
# ── Backend ────────────────────────────────────────
cd backend && npm run dev # Dev server (port 4016)
cd backend && npm run typecheck # tsc --noEmit
cd backend && npm test # 80 Vitest tests
pnpm --filter @notelett/backend run dev # Dev server (port 4016)
pnpm --filter @notelett/backend run typecheck # tsc --noEmit
pnpm --filter @notelett/backend run test # backend Vitest tests
# ── Web ────────────────────────────────────────────
cd web && npm run dev -- --webpack # Dev server (port 3000)
cd web && npm run build -- --webpack # Production build
cd web && npm run typecheck # tsc --noEmit
cd web && npm test # 14 Vitest tests
pnpm --filter @notelett/web run dev # Dev server (port 3000)
pnpm --filter @notelett/web run build # Production build
pnpm --filter @notelett/web run typecheck # tsc --noEmit
pnpm --filter @notelett/web run test # web Vitest tests
# ── Mobile ─────────────────────────────────────────
cd mobile && npm start # Expo dev server
cd mobile && npm run typecheck # tsc --noEmit
cd mobile && npm test # 23 Vitest tests
pnpm --filter @notelett/mobile run start # Expo dev server
pnpm --filter @notelett/mobile run typecheck # tsc --noEmit
pnpm --filter @notelett/mobile run test # mobile tests
# ── Full verification ──────────────────────────────
pnpm run verify
```
## 7. Backend API Endpoints

View File

@ -27,7 +27,9 @@
## Build Verification
```bash
cd backend && npm test && npm run typecheck && npm run build
pnpm --filter @notelett/backend run test
pnpm --filter @notelett/backend run typecheck
pnpm --filter @notelett/backend run build
```

View File

@ -5,14 +5,16 @@ Structured notes platform for humans and AI agents — part of the ByteLyst ecos
## Quick Start
```bash
pnpm install
# Backend (port 4016)
cd backend && npm install && npm run dev
pnpm --filter @notelett/backend run dev
# Web (port 3000)
cd web && npm install && npm run dev -- --webpack
pnpm --filter @notelett/web run dev
# Mobile
cd mobile && npm install && npm start
pnpm --filter @notelett/mobile run start
```
## Architecture
@ -42,8 +44,10 @@ Copy `backend/.env.example` to `backend/.env` and fill in:
## Tests
```bash
cd backend && npm test # 18 tests (10 files)
cd web && npm test # 6 tests (5 files)
pnpm --filter @notelett/backend run test
pnpm --filter @notelett/web run test
pnpm --filter @notelett/mobile run test
pnpm run verify
```
## Docs

View File

@ -1,26 +1,30 @@
# Pre-requisite: run ./scripts/docker-prep.sh to pack @bytelyst/* tarballs
# ── Stage 1: Build ────────────────────────────────────
FROM node:22-alpine AS builder
WORKDIR /app
WORKDIR /app/backend
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
# ── Stage 2: Runtime ──────────────────────────────────
FROM node:22-alpine
WORKDIR /app
WORKDIR /app/backend
ENV NODE_ENV=production
COPY package.json package-lock.json ./
COPY .tarballs/ ./.tarballs/
RUN npm ci --omit=dev --ignore-scripts
RUN npm config set strict-ssl false
COPY backend/package.json ./package.json
COPY backend/.docker-deps/ ./.docker-deps/
RUN npm install --omit=dev --ignore-scripts
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/backend/dist ./dist
COPY --from=builder /app/backend/shared ./shared
EXPOSE 4016

2836
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
"name": "@notelett/backend",
"version": "0.1.0",
"private": true,
"packageManager": "pnpm@10.6.5",
"description": "NoteLett product backend — notes, workspaces, relationships, tasks, artifacts, agent actions",
"type": "module",
"scripts": {

View File

@ -1,8 +1,8 @@
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
context: .
dockerfile: backend/Dockerfile
ports:
- "4016:4016"
environment:
@ -26,8 +26,8 @@ services:
web:
build:
context: ./web
dockerfile: Dockerfile
context: .
dockerfile: web/Dockerfile
ports:
- "3000:3000"
environment:

14332
mobile/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
"name": "@notelett/mobile",
"version": "0.1.0",
"private": true,
"packageManager": "pnpm@10.6.5",
"main": "index.ts",
"scripts": {
"start": "expo start",

6
package-lock.json generated
View File

@ -1,6 +0,0 @@
{
"name": "learning_ai_notes",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

11
package.json Normal file
View File

@ -0,0 +1,11 @@
{
"name": "notelett-workspace",
"private": true,
"packageManager": "pnpm@10.6.5",
"scripts": {
"typecheck": "pnpm --filter @notelett/backend run typecheck && pnpm --filter @notelett/web run typecheck && pnpm --filter @notelett/mobile run typecheck",
"test": "pnpm --filter @notelett/backend run test && pnpm --filter @notelett/web run test && pnpm --filter @notelett/mobile run test",
"build": "pnpm --filter @notelett/backend run build && pnpm --filter @notelett/web run build",
"verify": "pnpm run typecheck && pnpm run test && pnpm run build"
}
}

14140
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

6
pnpm-workspace.yaml Normal file
View File

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

View File

@ -1,85 +1,40 @@
#!/usr/bin/env bash
set -euo pipefail
# docker-prep.sh — Pack @bytelyst/* packages into tarballs for Docker builds
# docker-prep.sh — Prep NoteLett Docker consumers via the shared common-plat prep-consumer script.
# Usage:
# ./scripts/docker-prep.sh # pack tarballs + rewrite package.json
# ./scripts/docker-prep.sh --restore # undo changes
# ./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)"
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
COMMON_PLAT="${ROOT_DIR}/../learning_ai_common_plat"
TARBALL_DIR="${ROOT_DIR}/.tarballs"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
COMMON_PLAT="${REPO_ROOT}/../learning_ai_common_plat"
PREP_SCRIPT="${COMMON_PLAT}/scripts/prep-consumer.sh"
if [[ "${1:-}" == "--restore" ]]; then
echo "Restoring package.json files..."
for pkg_json in backend/package.json web/package.json; do
backup="${ROOT_DIR}/${pkg_json}.bak"
if [[ -f "$backup" ]]; then
mv "$backup" "${ROOT_DIR}/${pkg_json}"
echo " Restored ${pkg_json}"
fi
done
rm -rf "$TARBALL_DIR"
echo "Done."
exit 0
fi
if [[ ! -d "$COMMON_PLAT/packages" ]]; then
echo "ERROR: Cannot find $COMMON_PLAT/packages — run from the correct directory"
if [[ ! -f "$PREP_SCRIPT" ]]; then
echo "❌ Cannot find prep-consumer.sh at $PREP_SCRIPT"
exit 1
fi
echo "Building @bytelyst/* packages..."
(cd "$COMMON_PLAT" && pnpm build)
CONSUMERS=(backend web)
MODE="${1:-}"
echo "Packing tarballs..."
rm -rf "$TARBALL_DIR"
mkdir -p "$TARBALL_DIR"
for pkg_dir in "$COMMON_PLAT"/packages/*/; do
pkg_name=$(basename "$pkg_dir")
if [[ -f "$pkg_dir/package.json" ]]; then
(cd "$pkg_dir" && npm pack --pack-destination "$TARBALL_DIR" 2>/dev/null) || true
fi
done
echo "Tarballs created:"
ls -la "$TARBALL_DIR"/*.tgz 2>/dev/null || echo " (none)"
echo "Rewriting package.json file: refs..."
for pkg_json in backend/package.json web/package.json; do
full_path="${ROOT_DIR}/${pkg_json}"
if [[ ! -f "$full_path" ]]; then
for consumer in "${CONSUMERS[@]}"; do
TARGET="${REPO_ROOT}/${consumer}"
if [[ ! -d "$TARGET" ]]; then
echo "⚠️ Skipping ${consumer} — directory not found"
continue
fi
cp "$full_path" "${full_path}.bak"
# Replace file:../../learning_ai_common_plat/packages/* refs with tarball paths
node -e "
const fs = require('fs');
const path = require('path');
const pkg = JSON.parse(fs.readFileSync('$full_path', 'utf8'));
const tarballDir = '$TARBALL_DIR';
const tarballs = fs.readdirSync(tarballDir).filter(f => f.endsWith('.tgz'));
for (const depType of ['dependencies', 'devDependencies']) {
if (!pkg[depType]) continue;
for (const [name, version] of Object.entries(pkg[depType])) {
if (typeof version === 'string' && version.startsWith('file:')) {
const shortName = name.replace('@bytelyst/', 'bytelyst-');
const tarball = tarballs.find(t => t.startsWith(shortName));
if (tarball) {
pkg[depType][name] = 'file:' + path.join(tarballDir, tarball);
}
}
}
}
fs.writeFileSync('$full_path', JSON.stringify(pkg, null, 2) + '\n');
"
echo " Rewrote ${pkg_json}"
if [[ "$MODE" == "--restore" ]]; then
bash "$PREP_SCRIPT" "$TARGET" --restore
else
bash "$PREP_SCRIPT" "$TARGET"
fi
done
echo "Done. Run 'docker build' now. Use --restore to undo."
if [[ "$MODE" != "--restore" ]]; then
echo ""
echo "✅ Docker prep complete. Run 'docker build' now, then restore with:"
echo " ./scripts/docker-prep.sh --restore"
fi

View File

@ -1,29 +1,30 @@
# Pre-requisite: run ./scripts/docker-prep.sh to pack @bytelyst/* tarballs
# ── Stage 1: Install ──────────────────────────────────
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:22-alpine 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
# ── Stage 2: Build ────────────────────────────────────
FROM node:20-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
COPY web/ ./
COPY shared/ ../shared/
# Dummy env vars for Next.js build-time page data collection
ENV NEXT_PUBLIC_BACKEND_URL=http://localhost:4016
ENV NEXT_PUBLIC_PLATFORM_URL=http://localhost:4003
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# ── Stage 3: Runtime ──────────────────────────────────
FROM node:20-alpine AS runtime
FROM node:22-alpine AS runtime
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
COPY --from=build /app/.next/standalone ./
COPY --from=build /app/.next/static ./.next/static
COPY --from=build /app/public ./public
COPY --from=builder /app/web/.next/standalone ./
COPY --from=builder /app/web/.next/static ./.next/static
EXPOSE 3000

8948
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1 +1,9 @@
import "@testing-library/jest-dom/vitest";
import { cleanup } from "@testing-library/react";
import * as matchers from "@testing-library/jest-dom/matchers";
import { afterEach, expect } from "vitest";
expect.extend(matchers);
afterEach(() => {
cleanup();
});

View File

@ -18,6 +18,7 @@
"name": "next"
}
],
"types": ["vitest/globals", "@testing-library/jest-dom"],
"paths": {
"@/*": ["./src/*"]
}