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 - uses: actions/setup-node@v4
with: with:
node-version: 22 node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install pnpm (for common-plat build) - name: Enable pnpm
run: npm install -g pnpm run: corepack enable
- name: Build @bytelyst/* packages - name: Build @bytelyst/* packages
working-directory: learning_ai_common_plat working-directory: learning_ai_common_plat
@ -37,55 +39,85 @@ jobs:
pnpm install --frozen-lockfile pnpm install --frozen-lockfile
pnpm build pnpm build
- name: Install backend dependencies - name: Install workspace dependencies
working-directory: backend run: pnpm install --frozen-lockfile
run: npm ci
- name: Backend typecheck - name: Backend typecheck
working-directory: backend run: pnpm --filter @notelett/backend run typecheck
run: npm run typecheck
- name: Backend tests - name: Backend tests
working-directory: backend run: pnpm --filter @notelett/backend run test
run: npm test
env: env:
DB_PROVIDER: memory DB_PROVIDER: memory
JWT_SECRET: ci-test-secret-at-least-32-characters-long JWT_SECRET: ci-test-secret-at-least-32-characters-long
- name: Backend build - name: Backend build
working-directory: backend run: pnpm --filter @notelett/backend run build
run: npm run build
web: web:
name: Web — typecheck + test + build name: Web — typecheck + test + build
runs-on: ubuntu-latest runs-on: ubuntu-latest
defaults:
run:
working-directory: web
steps: steps:
- uses: actions/checkout@v4 - 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 - uses: actions/setup-node@v4
with: with:
node-version: 22 node-version: 22
cache: npm cache: pnpm
cache-dependency-path: web/package-lock.json cache-dependency-path: pnpm-lock.yaml
- run: npm ci
- run: npm run typecheck - name: Enable pnpm
- run: npm test run: corepack enable
- run: npm run build
- 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: mobile:
name: Mobile — typecheck name: Mobile — typecheck
runs-on: ubuntu-latest runs-on: ubuntu-latest
defaults:
run:
working-directory: mobile
steps: steps:
- uses: actions/checkout@v4 - 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 - uses: actions/setup-node@v4
with: with:
node-version: 22 node-version: 22
cache: npm cache: pnpm
cache-dependency-path: mobile/package-lock.json cache-dependency-path: pnpm-lock.yaml
- run: npm ci
- run: npm run typecheck - 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 ```bash
# ── Backend ──────────────────────────────────────── # ── Backend ────────────────────────────────────────
cd backend && npm run dev # Dev server (port 4016) pnpm --filter @notelett/backend run dev # Dev server (port 4016)
cd backend && npm run typecheck # tsc --noEmit pnpm --filter @notelett/backend run typecheck # tsc --noEmit
cd backend && npm test # 80 Vitest tests pnpm --filter @notelett/backend run test # backend Vitest tests
# ── Web ──────────────────────────────────────────── # ── Web ────────────────────────────────────────────
cd web && npm run dev -- --webpack # Dev server (port 3000) pnpm --filter @notelett/web run dev # Dev server (port 3000)
cd web && npm run build -- --webpack # Production build pnpm --filter @notelett/web run build # Production build
cd web && npm run typecheck # tsc --noEmit pnpm --filter @notelett/web run typecheck # tsc --noEmit
cd web && npm test # 14 Vitest tests pnpm --filter @notelett/web run test # web Vitest tests
# ── Mobile ───────────────────────────────────────── # ── Mobile ─────────────────────────────────────────
cd mobile && npm start # Expo dev server pnpm --filter @notelett/mobile run start # Expo dev server
cd mobile && npm run typecheck # tsc --noEmit pnpm --filter @notelett/mobile run typecheck # tsc --noEmit
cd mobile && npm test # 23 Vitest tests pnpm --filter @notelett/mobile run test # mobile tests
# ── Full verification ──────────────────────────────
pnpm run verify
``` ```
## 7. Backend API Endpoints ## 7. Backend API Endpoints

View File

@ -27,7 +27,9 @@
## Build Verification ## Build Verification
```bash ```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 ## Quick Start
```bash ```bash
pnpm install
# Backend (port 4016) # Backend (port 4016)
cd backend && npm install && npm run dev pnpm --filter @notelett/backend run dev
# Web (port 3000) # Web (port 3000)
cd web && npm install && npm run dev -- --webpack pnpm --filter @notelett/web run dev
# Mobile # Mobile
cd mobile && npm install && npm start pnpm --filter @notelett/mobile run start
``` ```
## Architecture ## Architecture
@ -42,8 +44,10 @@ Copy `backend/.env.example` to `backend/.env` and fill in:
## Tests ## Tests
```bash ```bash
cd backend && npm test # 18 tests (10 files) pnpm --filter @notelett/backend run test
cd web && npm test # 6 tests (5 files) pnpm --filter @notelett/web run test
pnpm --filter @notelett/mobile run test
pnpm run verify
``` ```
## Docs ## Docs

View File

@ -1,26 +1,30 @@
# Pre-requisite: run ./scripts/docker-prep.sh to pack @bytelyst/* tarballs # Pre-requisite: run ./scripts/docker-prep.sh to pack @bytelyst/* tarballs
# ── Stage 1: Build ──────────────────────────────────── # ── Stage 1: Build ────────────────────────────────────
FROM node:22-alpine AS builder FROM node:22-alpine AS builder
WORKDIR /app WORKDIR /app/backend
COPY package.json package-lock.json ./ RUN npm config set strict-ssl false
COPY .tarballs/ ./.tarballs/ COPY backend/package.json ./package.json
RUN npm ci --ignore-scripts COPY backend/.docker-deps/ ./.docker-deps/
RUN npm install
COPY tsconfig.json ./ COPY backend/tsconfig.json ./tsconfig.json
COPY src/ ./src/ COPY backend/src/ ./src/
RUN npx tsc COPY shared/ ./shared/
RUN npm run build
# ── Stage 2: Runtime ────────────────────────────────── # ── Stage 2: Runtime ──────────────────────────────────
FROM node:22-alpine FROM node:22-alpine
WORKDIR /app WORKDIR /app/backend
ENV NODE_ENV=production ENV NODE_ENV=production
COPY package.json package-lock.json ./ RUN npm config set strict-ssl false
COPY .tarballs/ ./.tarballs/ COPY backend/package.json ./package.json
RUN npm ci --omit=dev --ignore-scripts 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 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", "name": "@notelett/backend",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"packageManager": "pnpm@10.6.5",
"description": "NoteLett product backend — notes, workspaces, relationships, tasks, artifacts, agent actions", "description": "NoteLett product backend — notes, workspaces, relationships, tasks, artifacts, agent actions",
"type": "module", "type": "module",
"scripts": { "scripts": {

View File

@ -1,8 +1,8 @@
services: services:
backend: backend:
build: build:
context: ./backend context: .
dockerfile: Dockerfile dockerfile: backend/Dockerfile
ports: ports:
- "4016:4016" - "4016:4016"
environment: environment:
@ -26,8 +26,8 @@ services:
web: web:
build: build:
context: ./web context: .
dockerfile: Dockerfile dockerfile: web/Dockerfile
ports: ports:
- "3000:3000" - "3000:3000"
environment: 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", "name": "@notelett/mobile",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"packageManager": "pnpm@10.6.5",
"main": "index.ts", "main": "index.ts",
"scripts": { "scripts": {
"start": "expo start", "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 #!/usr/bin/env bash
set -euo pipefail 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: # Usage:
# ./scripts/docker-prep.sh # pack tarballs + rewrite package.json # ./scripts/docker-prep.sh # prep backend + web for docker build
# ./scripts/docker-prep.sh --restore # undo changes # ./scripts/docker-prep.sh --restore # restore package.json changes and remove .docker-deps
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
COMMON_PLAT="${ROOT_DIR}/../learning_ai_common_plat" COMMON_PLAT="${REPO_ROOT}/../learning_ai_common_plat"
TARBALL_DIR="${ROOT_DIR}/.tarballs" PREP_SCRIPT="${COMMON_PLAT}/scripts/prep-consumer.sh"
if [[ "${1:-}" == "--restore" ]]; then if [[ ! -f "$PREP_SCRIPT" ]]; then
echo "Restoring package.json files..." echo "❌ Cannot find prep-consumer.sh at $PREP_SCRIPT"
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"
exit 1 exit 1
fi fi
echo "Building @bytelyst/* packages..." CONSUMERS=(backend web)
(cd "$COMMON_PLAT" && pnpm build) MODE="${1:-}"
echo "Packing tarballs..." for consumer in "${CONSUMERS[@]}"; do
rm -rf "$TARBALL_DIR" TARGET="${REPO_ROOT}/${consumer}"
mkdir -p "$TARBALL_DIR" if [[ ! -d "$TARGET" ]]; then
echo "⚠️ Skipping ${consumer} — directory not found"
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
continue continue
fi fi
cp "$full_path" "${full_path}.bak" if [[ "$MODE" == "--restore" ]]; then
bash "$PREP_SCRIPT" "$TARGET" --restore
# Replace file:../../learning_ai_common_plat/packages/* refs with tarball paths else
node -e " bash "$PREP_SCRIPT" "$TARGET"
const fs = require('fs'); fi
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}"
done 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 ────────────────────────────────── # ── Stage 1: Install ──────────────────────────────────
FROM node:20-alpine AS deps FROM node:22-alpine AS builder
WORKDIR /app WORKDIR /app/web
COPY package.json package-lock.json ./ RUN npm config set strict-ssl false
RUN npm ci COPY web/package.json ./package.json
COPY web/.docker-deps/ ./.docker-deps/
RUN npm install --legacy-peer-deps
# ── Stage 2: Build ──────────────────────────────────── COPY web/ ./
FROM node:20-alpine AS build COPY shared/ ../shared/
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Dummy env vars for Next.js build-time page data collection # Dummy env vars for Next.js build-time page data collection
ENV NEXT_PUBLIC_BACKEND_URL=http://localhost:4016 ENV NEXT_PUBLIC_BACKEND_URL=http://localhost:4016
ENV NEXT_PUBLIC_PLATFORM_URL=http://localhost:4003 ENV NEXT_PUBLIC_PLATFORM_URL=http://localhost:4003
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build RUN npm run build
# ── Stage 3: Runtime ────────────────────────────────── # ── Stage 3: Runtime ──────────────────────────────────
FROM node:20-alpine AS runtime FROM node:22-alpine AS runtime
WORKDIR /app WORKDIR /app
ENV NODE_ENV=production ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
COPY --from=build /app/.next/standalone ./ COPY --from=builder /app/web/.next/standalone ./
COPY --from=build /app/.next/static ./.next/static COPY --from=builder /app/web/.next/static ./.next/static
COPY --from=build /app/public ./public
EXPOSE 3000 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", "name": "@notelett/web",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"packageManager": "pnpm@10.6.5",
"scripts": { "scripts": {
"dev": "next dev --webpack", "dev": "next dev --webpack",
"build": "next build --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" "name": "next"
} }
], ],
"types": ["vitest/globals", "@testing-library/jest-dom"],
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
} }