feat(repo): migrate notelett workspace to pnpm
This commit is contained in:
parent
b40097633f
commit
90dd2d3bd5
17
.dockerignore
Normal file
17
.dockerignore
Normal 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
|
||||
86
.github/workflows/ci.yml
vendored
86
.github/workflows/ci.yml
vendored
@ -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
|
||||
|
||||
23
AGENTS.md
23
AGENTS.md
@ -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
|
||||
|
||||
@ -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
|
||||
```
|
||||
|
||||
|
||||
|
||||
14
README.md
14
README.md
@ -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
|
||||
|
||||
@ -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
2836
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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": {
|
||||
|
||||
@ -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
14332
mobile/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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
6
package-lock.json
generated
@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "learning_ai_notes",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
11
package.json
Normal file
11
package.json
Normal 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
14140
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
pnpm-workspace.yaml
Normal file
6
pnpm-workspace.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
packages:
|
||||
- backend
|
||||
- web
|
||||
- mobile
|
||||
- ../learning_ai_common_plat/packages/*
|
||||
- learning_ai_common_plat/packages/*
|
||||
@ -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
|
||||
|
||||
@ -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
8948
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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",
|
||||
|
||||
@ -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();
|
||||
});
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"types": ["vitest/globals", "@testing-library/jest-dom"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user