From 5f04c8f143a86d5eff677673ef9627d6cada1a6a Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 27 Jan 2026 18:40:26 +1100 Subject: [PATCH 1/8] create dev container --- .devcontainer/Dockerfile | 68 +++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 41 +++++++++++++++++ .devcontainer/post-create.sh | 81 +++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100755 .devcontainer/post-create.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..202c8d1 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,68 @@ +# Dev container for dart_node monorepo +# Dart + Node.js + all build/test tooling +FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04 + +ARG DART_VERSION=3.10.0 +ARG NODE_MAJOR=20 + +# System dependencies +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get install -y --no-install-recommends \ + apt-transport-https \ + bc \ + build-essential \ + ca-certificates \ + curl \ + git \ + gnupg \ + jq \ + lcov \ + lsof \ + python3 \ + unzip \ + wget \ + xvfb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Dart SDK +RUN set -eux; \ + case "$(dpkg --print-architecture)" in \ + amd64) DART_ARCH="x64" ;; \ + arm64) DART_ARCH="arm64" ;; \ + *) echo "Unsupported arch"; exit 1 ;; \ + esac; \ + curl -fsSL "https://storage.googleapis.com/dart-archive/channels/stable/release/${DART_VERSION}/sdk/dartsdk-linux-${DART_ARCH}-release.zip" -o /tmp/dart-sdk.zip \ + && unzip /tmp/dart-sdk.zip -d /usr/lib \ + && rm /tmp/dart-sdk.zip + +ENV PATH="/usr/lib/dart-sdk/bin:${PATH}" +ENV PATH="/home/vscode/.pub-cache/bin:${PATH}" + +# Node.js via NodeSource +RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - \ + && apt-get install -y nodejs \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Chromium for browser tests +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get install -y --no-install-recommends chromium-browser \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + || true + +# Global npm tools +RUN npm install -g cspell + +# Global Dart tools (as vscode user so pub-cache is in the right place) +USER vscode +RUN dart pub global activate coverage +USER root + +# Playwright system deps (for website tests) +RUN npx playwright install-deps chromium 2>/dev/null || true + +# Chrome/Chromium env +ENV CHROME_EXECUTABLE="/usr/bin/chromium-browser" +ENV PUPPETEER_EXECUTABLE_PATH="/usr/bin/chromium-browser" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..827ace6 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,41 @@ +{ + "name": "dart_node", + "build": { + "dockerfile": "Dockerfile", + "args": { + "DART_VERSION": "3.10.0", + "NODE_MAJOR": "20" + } + }, + "features": { + "ghcr.io/devcontainers/features/github-cli:1": {} + }, + "postCreateCommand": "bash .devcontainer/post-create.sh", + "remoteUser": "vscode", + "containerEnv": { + "MIN_COVERAGE": "80", + "CHROME_EXECUTABLE": "/usr/bin/chromium-browser", + "PUPPETEER_EXECUTABLE_PATH": "/usr/bin/chromium-browser" + }, + "customizations": { + "vscode": { + "extensions": [ + "Dart-Code.dart-code", + "streetsidesoftware.code-spell-checker" + ], + "settings": { + "dart.sdkPath": "/usr/lib/dart-sdk", + "editor.formatOnSave": true, + "dart.lineLength": 80 + } + } + }, + "mounts": [ + "source=dart_node_pub_cache,target=/home/vscode/.pub-cache,type=volume" + ], + "forwardPorts": [3000, 8080], + "portsAttributes": { + "3000": { "label": "Backend API (Express)", "onAutoForward": "notify" }, + "8080": { "label": "Frontend", "onAutoForward": "notify" } + } +} diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100755 index 0000000..a260506 --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# Post-create: install ALL dependencies and pre-build the backend demo +# so ./run_dev.sh works immediately with zero setup +set -euo pipefail + +echo "===========================================" +echo " dart_node dev container setup" +echo "===========================================" +echo "" +echo "Dart: $(dart --version 2>&1)" +echo "Node: $(node --version)" +echo "npm: $(npm --version)" + +# ── 1. Build tool dependencies ────────────────────────────────────── +echo "" +echo "[1/6] Setting up build tool..." +(cd tools/build && dart pub get) + +# ── 2. Dart pub get for all packages ──────────────────────────────── +echo "" +echo "[2/6] Installing Dart dependencies (packages)..." +for dir in packages/*; do + [ -d "$dir" ] && [ -f "$dir/pubspec.yaml" ] && { + echo " $(basename "$dir")..." + (cd "$dir" && dart pub get) || echo " WARNING: pub get failed for $dir" + } +done + +# ── 3. Dart pub get for all examples ──────────────────────────────── +echo "" +echo "[3/6] Installing Dart dependencies (examples)..." +for dir in examples/*; do + [ -d "$dir" ] && [ -f "$dir/pubspec.yaml" ] && { + echo " $(basename "$dir")..." + (cd "$dir" && dart pub get) || echo " WARNING: pub get failed for $dir" + } +done + +# ── 4. npm install for all packages/examples with package.json ────── +echo "" +echo "[4/6] Installing npm dependencies..." +for dir in packages/* examples/*; do + [ -d "$dir" ] && [ -f "$dir/package.json" ] && { + echo " npm install: $(basename "$dir")..." + (cd "$dir" && npm install) || echo " WARNING: npm install failed for $dir" + } +done + +# Handle nested React Native dir +[ -d "examples/mobile/rn" ] && [ -f "examples/mobile/rn/package.json" ] && { + echo " npm install: mobile/rn..." + (cd examples/mobile/rn && npm install) || echo " WARNING: npm install failed for mobile/rn" +} + +# Website deps +[ -d "website" ] && [ -f "website/package.json" ] && { + echo " npm ci: website..." + (cd website && npm ci) || echo " WARNING: npm ci failed for website" +} + +# ── 5. Pre-build the backend demo ─────────────────────────────────── +echo "" +echo "[5/6] Pre-building backend demo..." +dart run tools/build/build.dart backend + +# ── 6. Playwright browsers (for website tests) ────────────────────── +echo "" +echo "[6/6] Installing Playwright browsers..." +(cd website && npx playwright install chromium) 2>/dev/null || echo " Playwright install skipped (optional)" + +# Ensure coverage tool is available +dart pub global activate coverage 2>/dev/null || true + +echo "" +echo "===========================================" +echo " Setup complete!" +echo "" +echo " Run the demo: ./run_dev.sh" +echo " Or manually: node examples/backend/build/server.js" +echo " API at: http://localhost:3000" +echo "===========================================" From e409083d1168fe4af21b516e05afc0da7b0ef3b2 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 27 Jan 2026 20:26:57 +1100 Subject: [PATCH 2/8] Claude stuff --- CLAUDE.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 7e96a73..7f6add4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,6 +35,11 @@ Dart packages for building Node.js apps. Strongly Typed Dart layer over JS inter - All packages require: `austerity` (linting), `nadz` (Result types) - `node_preamble` for dart2js Node.js compatibility +**Pull Requests** +- Keep the documentation tight +- Use the template: .github/PULL_REQUEST_TEMPLATE.md +- Only use git diff with main. Ignore commit messages + # Web & Translation - Optimize for AI Search and SEO From 0019e7a5e49fb0843825537e5001c9e84f223d9b Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 27 Jan 2026 21:14:34 +1100 Subject: [PATCH 3/8] Fix container --- .devcontainer/Dockerfile | 65 ++++++++++--------- .devcontainer/devcontainer.json | 14 ++-- .devcontainer/post-create.sh | 62 ++++++------------ README.md | 12 +++- README_zh.md | 2 +- examples/README.md | 4 +- examples/run_taskflow.sh | 75 ++++++++++++++++++++++ run_dev.sh | 109 -------------------------------- 8 files changed, 147 insertions(+), 196 deletions(-) create mode 100755 examples/run_taskflow.sh delete mode 100755 run_dev.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 202c8d1..24a4c2c 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,31 +1,38 @@ # Dev container for dart_node monorepo -# Dart + Node.js + all build/test tooling +# Dart + Node.js — lean image, fast startup +# +# ┌─────────────────────────────────────────────────┐ +# │ PINNED VERSIONS — update here, nowhere else │ +# │ │ +# │ Dart SDK: 3.10.7 │ +# │ Node.js: 20.20.0 │ +# │ cspell: 9.6.0 │ +# │ coverage: 1.15.0 │ +# │ gh CLI: 2.67.0 (in devcontainer.json) │ +# └─────────────────────────────────────────────────┘ FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04 -ARG DART_VERSION=3.10.0 -ARG NODE_MAJOR=20 +ARG DART_VERSION=3.10.7 +ARG NODE_VERSION=20.20.0 +ARG CSPELL_VERSION=9.6.0 +ARG COVERAGE_VERSION=1.15.0 -# System dependencies +# System dependencies (minimal) RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get install -y --no-install-recommends \ - apt-transport-https \ bc \ build-essential \ ca-certificates \ curl \ git \ - gnupg \ jq \ - lcov \ lsof \ python3 \ unzip \ - wget \ - xvfb \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -# Dart SDK +# Dart SDK (exact version) RUN set -eux; \ case "$(dpkg --print-architecture)" in \ amd64) DART_ARCH="x64" ;; \ @@ -39,30 +46,22 @@ RUN set -eux; \ ENV PATH="/usr/lib/dart-sdk/bin:${PATH}" ENV PATH="/home/vscode/.pub-cache/bin:${PATH}" -# Node.js via NodeSource -RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - \ - && apt-get install -y nodejs \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -# Chromium for browser tests -RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ - && apt-get install -y --no-install-recommends chromium-browser \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* \ - || true +# Node.js (exact version, direct binary) +RUN set -eux; \ + case "$(dpkg --print-architecture)" in \ + amd64) NODE_ARCH="x64" ;; \ + arm64) NODE_ARCH="arm64" ;; \ + *) echo "Unsupported arch"; exit 1 ;; \ + esac; \ + curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" -o /tmp/node.tar.xz \ + && tar -xJf /tmp/node.tar.xz -C /usr/local --strip-components=1 \ + && rm /tmp/node.tar.xz \ + && node --version && npm --version -# Global npm tools -RUN npm install -g cspell +# Global npm tools (pinned) +RUN npm install -g "cspell@${CSPELL_VERSION}" -# Global Dart tools (as vscode user so pub-cache is in the right place) +# Global Dart tools (pinned, as vscode user so pub-cache lands correctly) USER vscode -RUN dart pub global activate coverage +RUN dart pub global activate coverage "${COVERAGE_VERSION}" USER root - -# Playwright system deps (for website tests) -RUN npx playwright install-deps chromium 2>/dev/null || true - -# Chrome/Chromium env -ENV CHROME_EXECUTABLE="/usr/bin/chromium-browser" -ENV PUPPETEER_EXECUTABLE_PATH="/usr/bin/chromium-browser" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 827ace6..78f9653 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,19 +3,21 @@ "build": { "dockerfile": "Dockerfile", "args": { - "DART_VERSION": "3.10.0", - "NODE_MAJOR": "20" + "DART_VERSION": "3.10.7", + "NODE_VERSION": "20.20.0", + "CSPELL_VERSION": "9.6.0", + "COVERAGE_VERSION": "1.15.0" } }, "features": { - "ghcr.io/devcontainers/features/github-cli:1": {} + "ghcr.io/devcontainers/features/github-cli:1": { + "version": "2.67.0" + } }, "postCreateCommand": "bash .devcontainer/post-create.sh", "remoteUser": "vscode", "containerEnv": { - "MIN_COVERAGE": "80", - "CHROME_EXECUTABLE": "/usr/bin/chromium-browser", - "PUPPETEER_EXECUTABLE_PATH": "/usr/bin/chromium-browser" + "MIN_COVERAGE": "80" }, "customizations": { "vscode": { diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index a260506..0503c9a 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -1,6 +1,5 @@ #!/bin/bash -# Post-create: install ALL dependencies and pre-build the backend demo -# so ./run_dev.sh works immediately with zero setup +# Post-create: install deps and pre-build so run_taskflow.sh just works set -euo pipefail echo "===========================================" @@ -11,71 +10,46 @@ echo "Dart: $(dart --version 2>&1)" echo "Node: $(node --version)" echo "npm: $(npm --version)" -# ── 1. Build tool dependencies ────────────────────────────────────── +# ── 1. Build tool ──────────────────────────────────────────────────── echo "" -echo "[1/6] Setting up build tool..." +echo "[1/4] Setting up build tool..." (cd tools/build && dart pub get) -# ── 2. Dart pub get for all packages ──────────────────────────────── +# ── 2. Dart pub get ────────────────────────────────────────────────── echo "" -echo "[2/6] Installing Dart dependencies (packages)..." -for dir in packages/*; do - [ -d "$dir" ] && [ -f "$dir/pubspec.yaml" ] && { - echo " $(basename "$dir")..." - (cd "$dir" && dart pub get) || echo " WARNING: pub get failed for $dir" - } -done - -# ── 3. Dart pub get for all examples ──────────────────────────────── -echo "" -echo "[3/6] Installing Dart dependencies (examples)..." -for dir in examples/*; do +echo "[2/4] Installing Dart dependencies..." +for dir in packages/* examples/*; do [ -d "$dir" ] && [ -f "$dir/pubspec.yaml" ] && { echo " $(basename "$dir")..." (cd "$dir" && dart pub get) || echo " WARNING: pub get failed for $dir" } done -# ── 4. npm install for all packages/examples with package.json ────── +# ── 3. npm install ─────────────────────────────────────────────────── echo "" -echo "[4/6] Installing npm dependencies..." +echo "[3/4] Installing npm dependencies..." for dir in packages/* examples/*; do [ -d "$dir" ] && [ -f "$dir/package.json" ] && { - echo " npm install: $(basename "$dir")..." - (cd "$dir" && npm install) || echo " WARNING: npm install failed for $dir" + if [ -f "$dir/package-lock.json" ]; then + echo " npm ci: $(basename "$dir")..." + (cd "$dir" && npm ci) || echo " WARNING: npm ci failed for $dir" + else + echo " npm install: $(basename "$dir")..." + (cd "$dir" && npm install) || echo " WARNING: npm install failed for $dir" + fi } done -# Handle nested React Native dir -[ -d "examples/mobile/rn" ] && [ -f "examples/mobile/rn/package.json" ] && { - echo " npm install: mobile/rn..." - (cd examples/mobile/rn && npm install) || echo " WARNING: npm install failed for mobile/rn" -} - -# Website deps -[ -d "website" ] && [ -f "website/package.json" ] && { - echo " npm ci: website..." - (cd website && npm ci) || echo " WARNING: npm ci failed for website" -} - -# ── 5. Pre-build the backend demo ─────────────────────────────────── +# ── 4. Pre-build backend ──────────────────────────────────────────── echo "" -echo "[5/6] Pre-building backend demo..." +echo "[4/4] Pre-building backend..." dart run tools/build/build.dart backend -# ── 6. Playwright browsers (for website tests) ────────────────────── -echo "" -echo "[6/6] Installing Playwright browsers..." -(cd website && npx playwright install chromium) 2>/dev/null || echo " Playwright install skipped (optional)" - -# Ensure coverage tool is available -dart pub global activate coverage 2>/dev/null || true - echo "" echo "===========================================" echo " Setup complete!" echo "" -echo " Run the demo: ./run_dev.sh" +echo " Run the demo: sh examples/run_taskflow.sh" echo " Or manually: node examples/backend/build/server.js" echo " API at: http://localhost:3000" echo "===========================================" diff --git a/README.md b/README.md index 6c60615..3c7fd6b 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,16 @@ Write your entire stack in Dart: React web apps, React Native mobile apps with E | [too-many-cooks](examples/too_many_cooks) | Multi-agent coordination MCP server ([npm](https://www.npmjs.com/package/too-many-cooks)) | | [Too Many Cooks VSCode](examples/too_many_cooks_vscode_extension) | VSCode extension for agent visualization | +## Dev Container (Recommended) + +This project includes a [Dev Container](.devcontainer/devcontainer.json) that provides a fully configured development environment with Dart, Node.js, and Chromium pre-installed. Open the project in VSCode and select **Reopen in Container** when prompted. + +**Why use it?** + +- **Consistent environment** — Dart 3.10, Node 20, and Chromium are pinned and pre-configured. No version mismatches across machines. +- **Avoids Windows + Node.js performance issues** — Node.js file-heavy operations (`npm install`, `dart2js` output, `node_modules` creation) run up to [4x slower on Windows than Linux](https://github.com/microsoft/Windows-Dev-Performance/issues/17) due to NTFS overhead and Windows Defender real-time scanning. Yo will probably get better performance running on [WSL2](https://docs.docker.com/desktop/features/wsl/). The Dev Container sidesteps this entirely by running inside a Linux container. +- **Zero setup** — Coverage thresholds, linting, and test tooling are pre-configured via environment variables and VSCode settings. + ## Quick Start ```bash @@ -36,7 +46,7 @@ Write your entire stack in Dart: React web apps, React Native mobile apps with E dart tools/switch_deps.dart local # Run everything -sh run_dev.sh +sh examples/run_taskflow.sh ``` Open http://localhost:8080/web/ diff --git a/README_zh.md b/README_zh.md index 050901a..e8712d7 100644 --- a/README_zh.md +++ b/README_zh.md @@ -36,7 +36,7 @@ dart tools/switch_deps.dart local # 运行全部 -sh run_dev.sh +sh examples/run_taskflow.sh ``` 打开 http://localhost:8080/web/ diff --git a/examples/README.md b/examples/README.md index 6222386..9dbdbfe 100644 --- a/examples/README.md +++ b/examples/README.md @@ -18,8 +18,8 @@ examples/ ## Quick Start ```bash -# Build everything from repo root -sh run_dev.sh +# Build and run the TaskFlow demo (Express + React + React Native) +sh examples/run_taskflow.sh ``` ## Too Many Cooks diff --git a/examples/run_taskflow.sh b/examples/run_taskflow.sh new file mode 100755 index 0000000..5c46e03 --- /dev/null +++ b/examples/run_taskflow.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# Build and run the TaskFlow demo (Express + React + React Native) +# Dependencies are installed by .devcontainer/post-create.sh +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +cleanup() { + echo "" + echo "Shutting down servers..." + kill $SERVER_PID 2>/dev/null || true + kill $FRONTEND_PID 2>/dev/null || true + exit 0 +} + +trap cleanup INT TERM EXIT + +# Kill any existing instances by port +echo "Cleaning up old processes..." +lsof -ti :3000 | xargs kill -9 2>/dev/null || true +lsof -ti :8080 | xargs kill -9 2>/dev/null || true +sleep 2 + +echo "===================================" +echo " TaskFlow Development Environment" +echo "===================================" +echo "" + +# Step 1: Build all targets +echo "[1/2] Building all targets..." +cd "$ROOT_DIR" + +echo " Building backend..." +dart run tools/build/build.dart backend + +echo " Building mobile..." +dart run tools/build/build.dart mobile + +echo " Building frontend..." +cd "$SCRIPT_DIR/frontend" +mkdir -p build +dart compile js web/app.dart -o build/app.js -O2 + +# Step 2: Start servers +echo "" +echo "[2/2] Starting servers..." +echo "" + +cd "$SCRIPT_DIR/backend" +node build/server.js & +SERVER_PID=$! + +cd "$SCRIPT_DIR/frontend" +python3 -m http.server 8080 & +FRONTEND_PID=$! + +sleep 2 + +echo "===================================" +echo " Servers running!" +echo "===================================" +echo "" +echo " Backend API: http://localhost:3000" +echo " Frontend: http://localhost:8080/web/" +echo "" +echo " Mobile: Use VSCode launch config or run:" +echo " cd examples/mobile/rn && npm run ios" +echo " cd examples/mobile/rn && npm run android" +echo "" +echo " Press Ctrl+C to stop" +echo "===================================" +echo "" + +wait $SERVER_PID $FRONTEND_PID diff --git a/run_dev.sh b/run_dev.sh deleted file mode 100755 index c931059..0000000 --- a/run_dev.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/bash -set -e - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" - -cleanup() { - echo "" - echo "Shutting down servers..." - kill $SERVER_PID 2>/dev/null || true - kill $FRONTEND_PID 2>/dev/null || true - exit 0 -} - -trap cleanup SIGINT SIGTERM EXIT - -# Kill any existing instances by port (more reliable) -echo "Cleaning up old processes..." -lsof -ti :3000 | xargs kill -9 2>/dev/null || true -lsof -ti :8080 | xargs kill -9 2>/dev/null || true -sleep 2 - -echo "===================================" -echo " TaskFlow Development Environment" -echo "===================================" -echo "" - -# Step 1: Get dependencies for build tool -echo "[1/7] Setting up build tool..." -cd "$SCRIPT_DIR/tools/build" -dart pub get - -# Step 2: Get dependencies for all packages -echo "" -echo "[2/7] Getting dependencies for all packages..." -for pkg in "$SCRIPT_DIR/packages"/*; do - [ -f "$pkg/pubspec.yaml" ] && (cd "$pkg" && echo " $(basename "$pkg")..." && dart pub get) -done - -# Step 3: Get dependencies for all examples (Dart) -echo "" -echo "[3/7] Getting dependencies for all examples..." -for example in "$SCRIPT_DIR/examples"/*; do - [ -f "$example/pubspec.yaml" ] && (cd "$example" && echo " $(basename "$example")..." && dart pub get) -done - -# Step 4: npm install for backend -echo "" -echo "[4/7] Installing Node dependencies for backend..." -cd "$SCRIPT_DIR/examples/backend" -[ -d "node_modules" ] || npm install - -# Step 5: npm install for mobile/rn (Expo) -echo "" -echo "[5/7] Installing Node dependencies for mobile (Expo)..." -cd "$SCRIPT_DIR/examples/mobile/rn" -[ -d "node_modules" ] || npm install - -# Step 6: Build all targets -echo "" -echo "[6/7] Building all targets..." -cd "$SCRIPT_DIR" - -# Build backend -echo " Building backend..." -dart run tools/build/build.dart backend - -# Build mobile -echo " Building mobile..." -dart run tools/build/build.dart mobile - -# Build frontend (browser JS, not node preamble) -echo " Building frontend..." -cd "$SCRIPT_DIR/examples/frontend" -mkdir -p build -dart compile js web/app.dart -o build/app.js -O2 - -# Step 7: Start servers -echo "" -echo "[7/7] Starting servers..." -echo "" - -# Start Express backend on port 3000 -cd "$SCRIPT_DIR/examples/backend" -node build/server.js & -SERVER_PID=$! - -# Start simple HTTP server for frontend on port 8080 -cd "$SCRIPT_DIR/examples/frontend" -python3 -m http.server 8080 & -FRONTEND_PID=$! - -sleep 2 - -echo "===================================" -echo " Servers running!" -echo "===================================" -echo "" -echo " Backend API: http://localhost:3000" -echo " Frontend: http://localhost:8080/web/" -echo "" -echo " Mobile: Use VSCode launch config or run:" -echo " cd examples/mobile/rn && npm run ios" -echo " cd examples/mobile/rn && npm run android" -echo "" -echo " Press Ctrl+C to stop" -echo "===================================" -echo "" - -wait $SERVER_PID $FRONTEND_PID From 193657c67bb46a469ef6a16b576b7ef4b3d56608 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 27 Jan 2026 21:24:23 +1100 Subject: [PATCH 4/8] Add skillz --- .claude/skills/build-extension/SKILL.md | 59 ++++++++++++++++ .claude/skills/create-pr/SKILL.md | 63 ++++++++++++++++++ .claude/skills/pub-get/SKILL.md | 30 +++++++++ .claude/skills/setup-claude/SKILL.md | 75 +++++++++++++++++++++ .claude/skills/setup-playwright/SKILL.md | 49 ++++++++++++++ .claude/skills/taskflow/SKILL.md | 52 +++++++++++++++ .claude/skills/test/SKILL.md | 85 ++++++++++++++++++++++++ .claude/skills/website/SKILL.md | 62 +++++++++++++++++ 8 files changed, 475 insertions(+) create mode 100644 .claude/skills/build-extension/SKILL.md create mode 100644 .claude/skills/create-pr/SKILL.md create mode 100644 .claude/skills/pub-get/SKILL.md create mode 100644 .claude/skills/setup-claude/SKILL.md create mode 100644 .claude/skills/setup-playwright/SKILL.md create mode 100644 .claude/skills/taskflow/SKILL.md create mode 100644 .claude/skills/test/SKILL.md create mode 100644 .claude/skills/website/SKILL.md diff --git a/.claude/skills/build-extension/SKILL.md b/.claude/skills/build-extension/SKILL.md new file mode 100644 index 0000000..a9da67c --- /dev/null +++ b/.claude/skills/build-extension/SKILL.md @@ -0,0 +1,59 @@ +--- +name: build-extension +description: Build, test, and package VSCode extensions in the dart_node repo +argument-hint: "[too-many-cooks|dart-node-vsix] [build|test|package|install]" +disable-model-invocation: true +allowed-tools: Bash +--- + +# Build VSCode Extensions + +This repo has two VSCode extension components: + +| Component | Location | What it is | +|-----------|----------|------------| +| **dart_node_vsix** | `packages/dart_node_vsix/` | The SDK package — Dart bindings for the VSCode extension API (commands, tree views, webviews, status bar, etc.) | +| **too_many_cooks** | `examples/too_many_cooks_vscode_extension/` | A concrete extension built with that SDK — multi-agent coordination UI | + +## too-many-cooks extension + +**Full build** (MCP server + extension + .vsix package): +```bash +bash examples/too_many_cooks_vscode_extension/build.sh +``` + +This does: +1. Compiles MCP server: `dart compile js` → `add_preamble.dart` → `server_node.js` +2. Compiles extension: `dart compile js` → `wrap-extension.js` bridge → `out/lib/extension.js` +3. Packages: `vsce package` → `.vsix` file + +**Test** (runs Mocha tests under a real VSCode instance): +```bash +cd examples/too_many_cooks_vscode_extension && npm run pretest && npm test +``` +On headless Linux, prefix with `xvfb-run -a`. + +**Install into VSCode**: +```bash +code --install-extension examples/too_many_cooks_vscode_extension/*.vsix +``` + +## dart_node_vsix SDK package + +**Test the SDK** (Dart tests compiled to JS, run in VSCode): +```bash +cd packages/dart_node_vsix && npm install && npm run compile && npm test +``` + +**What it provides** — Dart bindings for: +- `commands`, `window`, `workspace`, `statusBar` +- `TreeView`, `Webview`, `OutputChannel` +- `ExtensionContext`, `Disposable` +- `Mocha` test API bindings +- JS interop helpers (`Promise`, `EventEmitter`) + +## Architecture + +Both use the same pattern: Dart → `dart compile js` → wrapper script → VSCode-compatible JS module. + +The wrapper scripts (`scripts/wrap-extension.js`, `scripts/wrap-tests.js`) bridge dart2js output to VSCode's CommonJS `require`/`module.exports` system and inject polyfills (navigator, self) needed by dart2js async scheduling. diff --git a/.claude/skills/create-pr/SKILL.md b/.claude/skills/create-pr/SKILL.md new file mode 100644 index 0000000..c930232 --- /dev/null +++ b/.claude/skills/create-pr/SKILL.md @@ -0,0 +1,63 @@ +--- +name: create-pr +description: Create a pull request using the dart_node PR template +disable-model-invocation: true +allowed-tools: Bash, Read, Grep, Glob +--- + +# Create Pull Request + +Create a PR following the dart_node template and conventions. + +## Steps + +1. **Check state**: + ```bash + git status + git diff main...HEAD + git log main..HEAD --oneline + ``` + +2. **Analyze all commits** from the branch (NOT just the latest — ALL commits since diverging from main). Use `git diff main` to understand the full scope. + +3. **Draft PR using the template** from `.github/PULL_REQUEST_TEMPLATE.md`: + + ``` + ## TLDR; + [One sentence summary] + + ## What Does This Do? + [Clear description of the change] + + ## Brief Details? + [Implementation details, design decisions] + + ## How Do The Tests Prove The Change Works? + [Describe test coverage and what the tests verify] + ``` + +4. **Create the PR**: + ```bash + gh pr create --title "Short title under 70 chars" --body "$(cat <<'EOF' + ## TLDR; + ... + + ## What Does This Do? + ... + + ## Brief Details? + ... + + ## How Do The Tests Prove The Change Works? + ... + EOF + )" + ``` + +## Rules + +- Keep the title under 70 chars +- Keep documentation tight (per CLAUDE.md) +- Only diff against `main` — ignore commit messages +- Push to remote with `-u` flag if needed +- Return the PR URL when done diff --git a/.claude/skills/pub-get/SKILL.md b/.claude/skills/pub-get/SKILL.md new file mode 100644 index 0000000..d42caa8 --- /dev/null +++ b/.claude/skills/pub-get/SKILL.md @@ -0,0 +1,30 @@ +--- +name: pub-get +description: Install all Dart and npm dependencies in dependency order +disable-model-invocation: true +allowed-tools: Bash +--- + +# Install Dependencies + +Run the dependency installer that handles the tiered monorepo structure. + +```bash +./tools/pub_get.sh +``` + +## What it does + +Installs `dart pub get` and `npm install` across all packages and examples in dependency order: + +1. **Tier 1 (Core):** `dart_logging`, `dart_node_coverage`, `dart_node_core`, `reflux` +2. **Tier 2 (Packages):** `dart_jsx`, `dart_node_express`, `dart_node_ws`, `dart_node_better_sqlite3`, `dart_node_mcp`, `dart_node_react`, `dart_node_react_native` +3. **Tier 3 (Examples):** `frontend`, `markdown_editor`, `reflux_demo/web_counter`, `too_many_cooks`, `backend`, `mobile`, `jsx_demo` + +Order matters because Tier 2 depends on Tier 1, and Tier 3 depends on both. + +## After running + +Report any failures. If a package fails, it's usually because: +- A dependency in an earlier tier hasn't been published yet (use `dart run tools/switch_deps.dart local` for local dev) +- npm packages need `npm install` in a subdirectory (e.g., `examples/mobile/rn/`) diff --git a/.claude/skills/setup-claude/SKILL.md b/.claude/skills/setup-claude/SKILL.md new file mode 100644 index 0000000..262bca7 --- /dev/null +++ b/.claude/skills/setup-claude/SKILL.md @@ -0,0 +1,75 @@ +--- +name: setup-claude +description: Install Claude Code CLI and the Too Many Cooks VSCode extension for multi-agent development +disable-model-invocation: true +allowed-tools: Bash +--- + +# Install Claude Code & Extension + +Sets up Claude Code CLI and the Too Many Cooks VSCode extension for multi-agent coordination. + +## Step 1: Install Claude Code CLI + +```bash +npm install -g @anthropic-ai/claude-code +``` + +Verify: +```bash +claude --version +``` + +## Step 2: Build the Too Many Cooks VSCode Extension + +The extension provides visual agent coordination (locks, messages, plans) via the MCP server. + +### 2a. Build the MCP Server first + +```bash +cd examples/too_many_cooks && dart pub get && npm install +dart compile js -o examples/too_many_cooks/build/bin/server.js examples/too_many_cooks/bin/server.dart +dart run tools/build/add_preamble.dart \ + examples/too_many_cooks/build/bin/server.js \ + examples/too_many_cooks/build/bin/server_node.js \ + --shebang +``` + +### 2b. Build and package the extension + +```bash +cd examples/too_many_cooks_vscode_extension +npm install +npm run compile +npx @vscode/vsce package +``` + +This creates a `.vsix` file in `examples/too_many_cooks_vscode_extension/`. + +### 2c. Install the extension + +```bash +code --install-extension examples/too_many_cooks_vscode_extension/*.vsix +``` + +Or use the full build script that does steps 2a-2b: +```bash +bash examples/too_many_cooks_vscode_extension/build.sh +``` + +## Step 3: Configure Claude Code for this project + +The project's `.claude/settings.local.json` already has the required permissions: +- `Bash(dart pub get:*)` — dependency installation +- `mcp__too-many-cooks__register` — MCP agent registration +- `Bash(docker ps:*)` — Docker status checks + +Custom skills are in `.claude/skills/` — run `/help` to see them. + +## Multi-Agent Usage + +After setup, agents coordinate via the Too Many Cooks MCP server: +- **Lock files** before editing, unlock after +- **Check messages** regularly between agents +- **Update plans** so other agents can see your intent +- Keep your agent key — it's critical for authentication diff --git a/.claude/skills/setup-playwright/SKILL.md b/.claude/skills/setup-playwright/SKILL.md new file mode 100644 index 0000000..60b6326 --- /dev/null +++ b/.claude/skills/setup-playwright/SKILL.md @@ -0,0 +1,49 @@ +--- +name: setup-playwright +description: Install Chromium and Playwright for website E2E testing +disable-model-invocation: true +allowed-tools: Bash +--- + +# Install Chromium & Playwright + +Sets up Playwright with Chromium for running the website's E2E test suite. + +## Steps + +1. **Install website npm dependencies** (includes `@playwright/test`): + ```bash + cd website && npm ci + ``` + +2. **Install Chromium browser and OS dependencies**: + ```bash + cd website && npx playwright install --with-deps chromium + ``` + This installs the Chromium binary plus required system libraries (libgbm, libasound, etc.). + +3. **Verify installation**: + ```bash + cd website && npx playwright --version + ``` + +## Notes + +- Only Chromium is needed — this project does not test against Firefox or WebKit. +- On the Dev Container (Ubuntu 24.04), `--with-deps` installs the OS packages automatically. +- On macOS, Playwright downloads its own Chromium binary — no Homebrew needed. +- Browser cache lives at `~/.cache/ms-playwright/`. Delete this to force a clean reinstall. +- The website tests are at `website/tests/` and configured in `website/playwright.config.js`. +- Base URL: `http://localhost:8080` (Eleventy dev server). + +## After installing + +Run the website tests: +```bash +cd website && npm test +``` + +Or with UI mode: +```bash +cd website && npm run test:ui +``` diff --git a/.claude/skills/taskflow/SKILL.md b/.claude/skills/taskflow/SKILL.md new file mode 100644 index 0000000..973c51d --- /dev/null +++ b/.claude/skills/taskflow/SKILL.md @@ -0,0 +1,52 @@ +--- +name: taskflow +description: Build and run the full TaskFlow demo stack (Express backend + React frontend + mobile) +disable-model-invocation: true +allowed-tools: Bash +--- + +# TaskFlow Demo + +Build and run the full-stack demo that showcases dart_node's capabilities. + +## Run it + +```bash +sh examples/run_taskflow.sh +``` + +This: +1. Kills any existing processes on ports 3000 and 8080 +2. Builds backend, mobile, and frontend from Dart to JS +3. Starts the Express backend on **http://localhost:3000** +4. Starts the frontend dev server on **http://localhost:8080/web/** +5. Traps Ctrl+C for clean shutdown + +## Ports + +| Service | Port | How | +|---------|------|-----| +| Backend API (Express) | 3000 | `node examples/backend/build/server.js` | +| Frontend (static) | 8080 | `python3 -m http.server 8080` | +| Mobile (Expo) | — | `cd examples/mobile/rn && npm run ios` or `npm run android` | + +## Prerequisites + +Dependencies must be installed first. If the build fails, run: +```bash +./tools/pub_get.sh +``` + +Or use the Dev Container which runs `post-create.sh` automatically. + +## Manual start (individual services) + +Backend only: +```bash +dart run tools/build/build.dart backend && node examples/backend/build/server.js +``` + +Frontend only: +```bash +cd examples/frontend && bash build.sh && python3 -m http.server 8080 +``` diff --git a/.claude/skills/test/SKILL.md b/.claude/skills/test/SKILL.md new file mode 100644 index 0000000..d1015d3 --- /dev/null +++ b/.claude/skills/test/SKILL.md @@ -0,0 +1,85 @@ +--- +name: test +description: Run tests and coverage for dart_node packages. Automatically detects which packages to test based on changed files. +argument-hint: "[--tier N] [--all] [package...]" +disable-model-invocation: true +allowed-tools: Bash, Read, Grep, Glob +--- + +# Run Tests & Coverage + +## Step 1: Determine what to test + +If `$ARGUMENTS` specifies a tier or package, use that. Otherwise, **detect which packages were affected by recent changes**: + +```bash +git diff --name-only main +``` + +Map changed files to packages: + +| Changed path | Test target | +|---|---| +| `packages/dart_node_core/` | `packages/dart_node_core` | +| `packages/dart_node_express/` | `packages/dart_node_express` | +| `packages/dart_node_ws/` | `packages/dart_node_ws` | +| `packages/dart_node_better_sqlite3/` | `packages/dart_node_better_sqlite3` | +| `packages/dart_node_mcp/` | `packages/dart_node_mcp` | +| `packages/dart_node_react/` | `packages/dart_node_react` | +| `packages/dart_node_react_native/` | `packages/dart_node_react_native` | +| `packages/dart_logging/` | `packages/dart_logging` | +| `packages/reflux/` | `packages/reflux` | +| `packages/dart_jsx/` | `packages/dart_jsx` | +| `examples/frontend/` | `examples/frontend` | +| `examples/too_many_cooks/` | `examples/too_many_cooks` | +| `examples/markdown_editor/` | `examples/markdown_editor` | +| `examples/reflux_demo/` | `examples/reflux_demo/web_counter` | +| `tools/` or root config | Run `--all` | + +If a Tier 1 package changed, also run its downstream dependents in Tier 2/3. + +## Step 2: Run tests + +**Specific packages** (preferred — faster): +```bash +./tools/test.sh packages/dart_node_core packages/dart_node_express +``` + +**Full tier**: +```bash +./tools/test.sh --tier 1 +``` + +**Everything** (use `--all` arg or when root files changed): +```bash +./tools/test.sh +``` + +## Step 3: Coverage for affected packages + +For each Node package that was tested, run the coverage tool: + +```bash +cd packages/ && dart run ../dart_node_coverage/bin/coverage.dart +``` + +Node packages (use coverage CLI): `dart_node_core`, `dart_node_express`, `dart_node_ws`, `dart_node_better_sqlite3`, `dart_node_mcp`, `dart_node_react_native` + +Browser packages (use `dart test -p chrome`): `dart_node_react` + +Standard packages (use `dart test --coverage`): `dart_logging`, `reflux` + +Minimum coverage: **80%**. If below threshold, read `coverage/lcov.info` and identify uncovered lines. + +## Tiers reference + +- **Tier 1:** `dart_logging`, `dart_node_core` +- **Tier 2:** `reflux`, `dart_node_express`, `dart_node_ws`, `dart_node_better_sqlite3`, `dart_node_mcp`, `dart_node_react_native`, `dart_node_react` +- **Tier 3:** `examples/frontend`, `examples/markdown_editor`, `examples/reflux_demo/web_counter`, `examples/too_many_cooks` + +## After running + +1. Report PASS/FAIL per package with coverage percentages +2. If failures occur, read the log from `logs/.log` and diagnose +3. If coverage is below 80%, suggest specific test cases to add +4. Never skip tests, remove assertions, or silently swallow failures diff --git a/.claude/skills/website/SKILL.md b/.claude/skills/website/SKILL.md new file mode 100644 index 0000000..b87de43 --- /dev/null +++ b/.claude/skills/website/SKILL.md @@ -0,0 +1,62 @@ +--- +name: website +description: Build, serve, and test the dart_node documentation website (Eleventy + Playwright) +argument-hint: "[build|dev|test|clean]" +disable-model-invocation: true +allowed-tools: Bash +--- + +# Website (Eleventy + Playwright) + +Build and test the dart_node documentation site at `website/`. + +## Commands + +Parse `$ARGUMENTS` to determine the action: + +**build** — Full production build (copies READMEs, generates API docs, runs Eleventy): +```bash +cd website && npm run build +``` + +**dev** — Start the dev server with live reload: +```bash +cd website && npm run dev +``` +Serves at `http://localhost:8080`. + +**test** — Run Playwright E2E tests (builds first if `_site/` doesn't exist): +```bash +cd website && npm test +``` + +**test:coverage** — Run tests with V8 JS coverage: +```bash +cd website && npm run test:coverage +``` + +**clean** — Remove generated files: +```bash +cd website && npm run clean +``` + +**No args** — Default to `build` then `test`. + +## Build pipeline + +`npm run build` runs `scripts/build.sh` which does: +1. `node scripts/copy-readmes.js` — Copies package READMEs into the site +2. `bash scripts/generate-api-docs.sh` — Generates API reference from Dart source +3. `npx eleventy` — Generates static site into `_site/` + +## Test files + +9 test specs in `website/tests/`: +- Page content, navigation, language switching +- Theme toggle (dark/light mode) +- Mobile responsiveness +- Code blocks and syntax highlighting + +## Prerequisites + +Playwright must be installed first. Run `/setup-playwright` if `npx playwright --version` fails. From 733c61eed3eb7805d77ebdd92474a50edfdde3a3 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 27 Jan 2026 21:28:24 +1100 Subject: [PATCH 5/8] Fix a dep --- AGENTS.md | 44 +++++++++++++------- packages/dart_node_express/package-lock.json | 7 ++-- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index cf9915b..7f6add4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,18 +1,20 @@ # CLAUDE.md -Dart packages for building Node.js apps. Typed Dart layer over JS interop. +Dart packages for building Node.js apps. Strongly Typed Dart layer over JS interop. + +## Rules + +⛔️ NEVER KILL (pkill) THE VSCODE PROCESS!!! +- Do not use Git unless asked by user ## Multi-Agent Coordination (Too Many Cooks) +- Keep your key! It's critical. Do not lose it! - Check messages regularly, lock files before editing, unlock after - Don't edit locked files; signal intent via plans and messages -- Coordinator: keep delegating via messages. Worker: keep asking for tasks via messages -- Clean up expired locks routinely - -## Code Rules **Language & Types** - All Dart, minimal JS. Use `dart:js_interop` (not deprecated `dart:js_util`/`package:js`) -- Never expose `JSObject`/`JSAny`/`dynamic` in public APIs—always typed +- AVOID `JSObject`/`JSAny`/`dynamic`! - Prefer typedef records over classes for data (structural typing) - ILLEGAL: `as`, `late`, `!`, `.then()`, global state @@ -21,17 +23,36 @@ Dart packages for building Node.js apps. Typed Dart layer over JS interop. - Return `Result` (nadz) instead of throwing exceptions - Functions < 20 lines, files < 500 LOC - Switch expressions/ternaries over if/else (except in declarative contexts) +- Where Typescript code exists with no Dart wrapper, create the Dart wrapper APIs and add to the appropriate packages. **Testing** - 100% coverage with high-level integration tests, not unit tests/mocks - Tests in separate files, not groups. Dart only (JS only for interop testing) -- Never skip tests. Never remove assertions. Failing tests OK, silent failures ILLEGAL +- Never skip tests. Never remove assertions. Failing tests OK, silent failures = ⛔️ ILLEGAL. Aggressively unskip tests. - NO PLACEHOLDERS—throw if incomplete **Dependencies** - All packages require: `austerity` (linting), `nadz` (Result types) - `node_preamble` for dart2js Node.js compatibility +**Pull Requests** +- Keep the documentation tight +- Use the template: .github/PULL_REQUEST_TEMPLATE.md +- Only use git diff with main. Ignore commit messages + +# Web & Translation + +- Optimize for AI Search and SEO +https://developers.google.com/search/blog/2025/05/succeeding-in-ai-search +https://developers.google.com/search/docs/fundamentals/seo-starter-guide + +- Always translate the English version to the target language directly. +- Be careful of cultural differences. +- Avoid literal translations that may offend the reader. +- Keep the code examples the same as the original but translate the comments to the target language +- Minimize CSS. +- Don't name CSS after sections. Name them after the HTML element + ## Codebase Structure ``` @@ -53,11 +74,4 @@ examples/ mobile/ # React Native example too_many_cooks/ # Multi-agent coordination server jsx_demo/ # JSX syntax demo -``` - -## Build & Test -```bash -dart run tools/build/build.dart # Build all -dart test # Run tests -dart analyze # Lint check -``` +``` \ No newline at end of file diff --git a/packages/dart_node_express/package-lock.json b/packages/dart_node_express/package-lock.json index d2b24f9..5582ebd 100644 --- a/packages/dart_node_express/package-lock.json +++ b/packages/dart_node_express/package-lock.json @@ -4,6 +4,7 @@ "requires": true, "packages": { "": { + "name": "dart_node_express", "dependencies": { "express": "^5.2.1" } @@ -580,9 +581,9 @@ } }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" From 8910e168281829aa51aaaefb466330d4ce911f66 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 27 Jan 2026 21:44:27 +1100 Subject: [PATCH 6/8] Upgrades --- .devcontainer/Dockerfile | 6 +- .devcontainer/devcontainer.json | 1 + examples/backend/package-lock.json | 134 ++++++++++++++++------ examples/too_many_cooks/package-lock.json | 42 ++++++- packages/dart_node_vsix/package-lock.json | 12 +- packages/dart_node_ws/package-lock.json | 7 +- 6 files changed, 147 insertions(+), 55 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 24a4c2c..de688d6 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -6,6 +6,7 @@ # │ │ # │ Dart SDK: 3.10.7 │ # │ Node.js: 20.20.0 │ +# │ npm: 11.8.0 │ # │ cspell: 9.6.0 │ # │ coverage: 1.15.0 │ # │ gh CLI: 2.67.0 (in devcontainer.json) │ @@ -14,6 +15,7 @@ FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04 ARG DART_VERSION=3.10.7 ARG NODE_VERSION=20.20.0 +ARG NPM_VERSION=11.8.0 ARG CSPELL_VERSION=9.6.0 ARG COVERAGE_VERSION=1.15.0 @@ -58,8 +60,8 @@ RUN set -eux; \ && rm /tmp/node.tar.xz \ && node --version && npm --version -# Global npm tools (pinned) -RUN npm install -g "cspell@${CSPELL_VERSION}" +# Upgrade npm itself (pinned), then global npm tools +RUN npm install -g "npm@${NPM_VERSION}" "cspell@${CSPELL_VERSION}" # Global Dart tools (pinned, as vscode user so pub-cache lands correctly) USER vscode diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 78f9653..a71da6b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,6 +5,7 @@ "args": { "DART_VERSION": "3.10.7", "NODE_VERSION": "20.20.0", + "NPM_VERSION": "11.8.0", "CSPELL_VERSION": "9.6.0", "COVERAGE_VERSION": "1.15.0" } diff --git a/examples/backend/package-lock.json b/examples/backend/package-lock.json index 2e8ad7e..3bdd2f6 100644 --- a/examples/backend/package-lock.json +++ b/examples/backend/package-lock.json @@ -30,29 +30,58 @@ "license": "MIT" }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -230,39 +259,39 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -573,12 +602,12 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -597,20 +626,49 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", diff --git a/examples/too_many_cooks/package-lock.json b/examples/too_many_cooks/package-lock.json index d6df992..579ca06 100644 --- a/examples/too_many_cooks/package-lock.json +++ b/examples/too_many_cooks/package-lock.json @@ -19,12 +19,25 @@ "node": ">=18.0.0" } }, + "node_modules/@hono/node-server": { + "version": "1.19.9", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", + "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.24.3", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.24.3.tgz", - "integrity": "sha512-YgSHW29fuzKKAHTGe9zjNoo+yF8KaQPzDC2W9Pv41E7/57IfY+AMGJ/aDFlgTLcVVELoggKE4syABCE75u3NCw==", + "version": "1.25.3", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.3.tgz", + "integrity": "sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==", "license": "MIT", "dependencies": { + "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", @@ -35,6 +48,7 @@ "express": "^5.0.1", "express-rate-limit": "^7.5.0", "jose": "^6.1.1", + "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", @@ -706,6 +720,16 @@ "node": ">= 0.4" } }, + "node_modules/hono": { + "version": "4.11.7", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz", + "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=16.9.0" + } + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -810,6 +834,12 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/json-schema-typed": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", + "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", + "license": "BSD-2-Clause" + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -1054,9 +1084,9 @@ } }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" diff --git a/packages/dart_node_vsix/package-lock.json b/packages/dart_node_vsix/package-lock.json index de0b84a..a97b2b8 100644 --- a/packages/dart_node_vsix/package-lock.json +++ b/packages/dart_node_vsix/package-lock.json @@ -1867,9 +1867,9 @@ } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -3131,9 +3131,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, diff --git a/packages/dart_node_ws/package-lock.json b/packages/dart_node_ws/package-lock.json index 8907977..40614e8 100644 --- a/packages/dart_node_ws/package-lock.json +++ b/packages/dart_node_ws/package-lock.json @@ -4,6 +4,7 @@ "requires": true, "packages": { "": { + "name": "dart_node_ws", "dependencies": { "express": "^5.2.1", "ws": "^8.18.3" @@ -581,9 +582,9 @@ } }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" From 54c8c2d106d41c207d29257269ebf1e723c1d468 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 27 Jan 2026 21:53:23 +1100 Subject: [PATCH 7/8] Fix skill --- .claude/skills/create-pr/SKILL.md | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/.claude/skills/create-pr/SKILL.md b/.claude/skills/create-pr/SKILL.md index c930232..cc55df8 100644 --- a/.claude/skills/create-pr/SKILL.md +++ b/.claude/skills/create-pr/SKILL.md @@ -18,23 +18,9 @@ Create a PR following the dart_node template and conventions. git log main..HEAD --oneline ``` -2. **Analyze all commits** from the branch (NOT just the latest — ALL commits since diverging from main). Use `git diff main` to understand the full scope. +2. **ignore all commits** do not pay attention to the commit messages -3. **Draft PR using the template** from `.github/PULL_REQUEST_TEMPLATE.md`: - - ``` - ## TLDR; - [One sentence summary] - - ## What Does This Do? - [Clear description of the change] - - ## Brief Details? - [Implementation details, design decisions] - - ## How Do The Tests Prove The Change Works? - [Describe test coverage and what the tests verify] - ``` +3. **Draft PR using the template** from `.github/PULL_REQUEST_TEMPLATE.md` 4. **Create the PR**: ```bash @@ -59,5 +45,4 @@ Create a PR following the dart_node template and conventions. - Keep the title under 70 chars - Keep documentation tight (per CLAUDE.md) - Only diff against `main` — ignore commit messages -- Push to remote with `-u` flag if needed - Return the PR URL when done From 0bc357f2393443c7072b82ddfbec95fd1092de61 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 27 Jan 2026 21:58:11 +1100 Subject: [PATCH 8/8] spelling --- cspell-dictionary.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cspell-dictionary.txt b/cspell-dictionary.txt index 4909ae0..7cc9e0e 100644 --- a/cspell-dictionary.txt +++ b/cspell-dictionary.txt @@ -129,6 +129,7 @@ unconfigured # Project-specific christianfindlay Findlay +taskflow toomanycooks Nimblesite @@ -246,6 +247,7 @@ minimumlog # Other technical LTWH +NTFS blockquotes Blockquotes strikethrough