diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d77ef81..58c303cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,6 +105,51 @@ jobs: path: web/storybook-static/ retention-days: 30 + # ============================================================ + # JOB 0b3: Build API Documentation + # ============================================================ + build-docs: + name: Build documentation + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 + + - name: Build Rust docs + run: cargo doc --workspace --no-deps + + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version-file: web/.nvmrc + cache: yarn + cache-dependency-path: web/yarn.lock + + - name: Enable corepack + run: corepack enable + + - name: Install dependencies + run: cd web && yarn install --immutable + + - name: Build TypeScript docs + working-directory: web + run: yarn typedoc + + - name: Upload docs artifact + uses: actions/upload-artifact@v6 + with: + name: docs + path: | + target/doc + web/docs + retention-days: 7 + # ============================================================ # JOB 0c: Verify GraphQL codegen is up-to-date # ============================================================ @@ -726,40 +771,44 @@ jobs: kubectl get all -n default || true # ============================================================ - # JOB 3: Deploy reports to GitHub Pages + # JOB 3: Deploy to Cloudflare Pages # ============================================================ - deploy-pages: - name: Deploy to GitHub Pages + deploy-cloudflare: + name: Deploy to Cloudflare Pages runs-on: ubuntu-latest - needs: [integration-tests, storybook-build] + needs: [integration-tests, storybook-build, build-docs] if: always() && needs.integration-tests.result != 'cancelled' - concurrency: - group: gh-pages-deploy - cancel-in-progress: false permissions: - contents: write + contents: read + deployments: write pull-requests: write - env: - PAGES_BASE_URL: https://icook.github.io/tiny-congress steps: - - name: Checkout gh-pages branch + - name: Checkout for assets uses: actions/checkout@v6 with: - ref: gh-pages - fetch-depth: 0 + sparse-checkout: | + web/src/logo.png + web/src/favicon.ico + sparse-checkout-cone-mode: false + + - name: Create site directory + run: | + mkdir -p site + cp web/src/logo.png site/logo.png + cp web/src/favicon.ico site/favicon.ico - name: Download coverage report uses: actions/download-artifact@v6 with: name: coverage-report - path: artifacts/coverage + path: site/coverage continue-on-error: true - name: Download Storybook uses: actions/download-artifact@v6 with: name: storybook-static - path: artifacts/storybook + path: site/storybook continue-on-error: true - name: Download Playwright report @@ -769,126 +818,445 @@ jobs: path: artifacts/playwright continue-on-error: true - - name: Determine deployment paths - id: paths - run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - echo "is_pr=true" >> "$GITHUB_OUTPUT" - echo "pr_number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" - echo "base_path=pr/${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" - else - echo "is_pr=false" >> "$GITHUB_OUTPUT" - echo "base_path=" >> "$GITHUB_OUTPUT" - fi + - name: Download docs + uses: actions/download-artifact@v6 + with: + name: docs + path: artifacts/docs + continue-on-error: true - - name: Prepare deployment directory + - name: Download Rust coverage + uses: actions/download-artifact@v6 + with: + name: rust-coverage + path: artifacts/rust-coverage + continue-on-error: true + + - name: Organize artifacts + id: artifacts run: | - set -euo pipefail - BASE_PATH="${{ steps.paths.outputs.base_path }}" + # Playwright report is nested + if [ -d artifacts/playwright/playwright-report ]; then + mv artifacts/playwright/playwright-report site/playwright + fi - # For PRs, clean the PR-specific directory; for main, clean root reports - if [ -n "$BASE_PATH" ]; then - rm -rf "$BASE_PATH" - mkdir -p "$BASE_PATH" + # Rust docs + if [ -d artifacts/docs/target/doc ]; then + mv artifacts/docs/target/doc site/rust-docs fi - # Copy artifacts to appropriate locations - if [ -d artifacts/coverage ]; then - if [ -n "$BASE_PATH" ]; then - cp -r artifacts/coverage "$BASE_PATH/coverage" - else - rm -rf coverage - cp -r artifacts/coverage coverage - fi + # TypeScript docs + if [ -d artifacts/docs/web/docs ]; then + mv artifacts/docs/web/docs site/ts-docs fi - if [ -d artifacts/storybook ]; then - if [ -n "$BASE_PATH" ]; then - cp -r artifacts/storybook "$BASE_PATH/storybook" + # Extract coverage percentages from all test types + # Vitest + if [ -f site/coverage/vitest/coverage-summary.json ]; then + VITEST_LINES=$(jq -r '.total.lines.pct // 0' site/coverage/vitest/coverage-summary.json) + VITEST_BRANCHES=$(jq -r '.total.branches.pct // 0' site/coverage/vitest/coverage-summary.json) + VITEST_FUNCTIONS=$(jq -r '.total.functions.pct // 0' site/coverage/vitest/coverage-summary.json) + else + VITEST_LINES=0; VITEST_BRANCHES=0; VITEST_FUNCTIONS=0 + fi + echo "vitest_lines=${VITEST_LINES}" >> "$GITHUB_OUTPUT" + echo "vitest_branches=${VITEST_BRANCHES}" >> "$GITHUB_OUTPUT" + echo "vitest_functions=${VITEST_FUNCTIONS}" >> "$GITHUB_OUTPUT" + + # Playwright + if [ -f site/coverage/playwright/coverage-summary.json ]; then + PW_LINES=$(jq -r '.total.lines.pct // 0' site/coverage/playwright/coverage-summary.json) + PW_BRANCHES=$(jq -r '.total.branches.pct // 0' site/coverage/playwright/coverage-summary.json) + PW_FUNCTIONS=$(jq -r '.total.functions.pct // 0' site/coverage/playwright/coverage-summary.json) + else + PW_LINES=0; PW_BRANCHES=0; PW_FUNCTIONS=0 + fi + echo "pw_lines=${PW_LINES}" >> "$GITHUB_OUTPUT" + echo "pw_branches=${PW_BRANCHES}" >> "$GITHUB_OUTPUT" + echo "pw_functions=${PW_FUNCTIONS}" >> "$GITHUB_OUTPUT" + + # Rust (parse lcov file directly - must happen before artifacts cleanup) + RUST_LCOV="artifacts/rust-coverage/backend-unit.lcov" + if [ -f "$RUST_LCOV" ]; then + # Sum up LF (lines found) and LH (lines hit) from lcov + LINES_FOUND=$(grep "^LF:" "$RUST_LCOV" | cut -d: -f2 | awk '{s+=$1} END {print s+0}') + LINES_HIT=$(grep "^LH:" "$RUST_LCOV" | cut -d: -f2 | awk '{s+=$1} END {print s+0}') + FUNCS_FOUND=$(grep "^FNF:" "$RUST_LCOV" | cut -d: -f2 | awk '{s+=$1} END {print s+0}') + FUNCS_HIT=$(grep "^FNH:" "$RUST_LCOV" | cut -d: -f2 | awk '{s+=$1} END {print s+0}') + + if [ "$LINES_FOUND" -gt 0 ]; then + RUST_LINES=$(echo "scale=1; $LINES_HIT * 100 / $LINES_FOUND" | bc) else - rm -rf storybook - cp -r artifacts/storybook storybook + RUST_LINES=0 fi - fi - - if [ -d artifacts/playwright ]; then - # Playwright report is in playwright-report subdirectory - if [ -d artifacts/playwright/playwright-report ]; then - if [ -n "$BASE_PATH" ]; then - cp -r artifacts/playwright/playwright-report "$BASE_PATH/playwright" - else - rm -rf playwright - cp -r artifacts/playwright/playwright-report playwright - fi + if [ "$FUNCS_FOUND" -gt 0 ]; then + RUST_FUNCTIONS=$(echo "scale=1; $FUNCS_HIT * 100 / $FUNCS_FOUND" | bc) + else + RUST_FUNCTIONS=0 fi + else + RUST_LINES=0; RUST_FUNCTIONS=0 fi + echo "rust_lines=${RUST_LINES}" >> "$GITHUB_OUTPUT" + echo "rust_functions=${RUST_FUNCTIONS}" >> "$GITHUB_OUTPUT" - # Clean up artifacts directory + # Cleanup artifacts rm -rf artifacts - # Generate index page for PR previews - if [ -n "$BASE_PATH" ]; then - cat > "$BASE_PATH/index.html" <> "$GITHUB_OUTPUT" + + - name: Generate landing page + run: | + COMMIT_SHORT="${GITHUB_SHA:0:7}" + BUILD_DATE="$(date -u +"%Y-%m-%d %H:%M UTC")" + COVERAGE_PCT="${{ steps.artifacts.outputs.coverage_pct }}" + + # Coverage by test type + VITEST_LINES="${{ steps.artifacts.outputs.vitest_lines }}" + VITEST_BRANCHES="${{ steps.artifacts.outputs.vitest_branches }}" + VITEST_FUNCTIONS="${{ steps.artifacts.outputs.vitest_functions }}" + PW_LINES="${{ steps.artifacts.outputs.pw_lines }}" + PW_BRANCHES="${{ steps.artifacts.outputs.pw_branches }}" + PW_FUNCTIONS="${{ steps.artifacts.outputs.pw_functions }}" + RUST_LINES="${{ steps.artifacts.outputs.rust_lines }}" + RUST_FUNCTIONS="${{ steps.artifacts.outputs.rust_functions }}" + + cat > site/index.html < - + - PR #${{ steps.paths.outputs.pr_number }} Reports + + + Tiny Congress - Developer Resources + + -

PR #${{ steps.paths.outputs.pr_number }} Reports

- -

Generated: $(date -u +"%Y-%m-%d %H:%M:%S UTC")

+
+
+ +

Tiny Congress

+ + πŸ“Š ${COVERAGE_PCT}% coverage + +
+
+
+ Commit + ${COMMIT_SHORT} +
+
+ Branch + ${GITHUB_REF_NAME} +
+
+ Built + ${BUILD_DATE} +
+
+ Workflow + #${GITHUB_RUN_NUMBER} +
+
+
+ +
+

πŸ“š API Documentation

+ +
+ +
+

πŸ“Š Coverage Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test TypeLinesBranchesFunctionsDetails
πŸ§ͺ Vitest Unit Tests${VITEST_LINES}%${VITEST_BRANCHES}%${VITEST_FUNCTIONS}%View Report
🎭 Playwright E2E${PW_LINES}%${PW_BRANCHES}%${PW_FUNCTIONS}%View Report
πŸ¦€ Rust Backend${RUST_LINES}%N/A${RUST_FUNCTIONS}%View Report
+
+ View Full Coverage Report β†’ +
+
+ +
+

πŸ§ͺ Test Reports

+ +
EOF - fi - - name: Commit and push to gh-pages - run: | - set -euo pipefail - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - git add -A - if git diff --staged --quiet; then - echo "No changes to deploy" - exit 0 - fi - - if [ "${{ steps.paths.outputs.is_pr }}" = "true" ]; then - git commit -m "Deploy PR #${{ steps.paths.outputs.pr_number }} reports" - else - git commit -m "Deploy main branch reports from ${{ github.sha }}" - fi - - git push origin gh-pages + - name: Deploy to Cloudflare Pages + id: deploy + uses: cloudflare/pages-action@v1 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + projectName: tiny-congress + directory: site + gitHubToken: ${{ secrets.GITHUB_TOKEN }} - name: Add PR comment with report links - if: steps.paths.outputs.is_pr == 'true' + if: github.event_name == 'pull_request' uses: marocchino/sticky-pull-request-comment@v2 with: header: pages-reports message: | - ## πŸ“Š CI Reports + ## πŸ›οΈ CI Reports + + **[πŸ“‹ All Reports](${{ steps.deploy.outputs.url }}/)** + + ### πŸ“š API Documentation + | | | + |---|---| + | πŸ¦€ [Rust API Docs](${{ steps.deploy.outputs.url }}/rust-docs/tinycongress_api/) | πŸ“˜ [TypeScript Docs](${{ steps.deploy.outputs.url }}/ts-docs/) | - | Report | Link | - |--------|------| - | πŸ“Š Coverage | [${{ env.PAGES_BASE_URL }}/pr/${{ steps.paths.outputs.pr_number }}/coverage/](${{ env.PAGES_BASE_URL }}/pr/${{ steps.paths.outputs.pr_number }}/coverage/) | - | πŸ“š Storybook | [${{ env.PAGES_BASE_URL }}/pr/${{ steps.paths.outputs.pr_number }}/storybook/](${{ env.PAGES_BASE_URL }}/pr/${{ steps.paths.outputs.pr_number }}/storybook/) | - | 🎭 Playwright | [${{ env.PAGES_BASE_URL }}/pr/${{ steps.paths.outputs.pr_number }}/playwright/](${{ env.PAGES_BASE_URL }}/pr/${{ steps.paths.outputs.pr_number }}/playwright/) | - | πŸ“‹ API Schemas | [GraphQL](${{ env.PAGES_BASE_URL }}/pr/${{ steps.paths.outputs.pr_number }}/coverage/schemas/graphql-viewer.html) Β· [OpenAPI](${{ env.PAGES_BASE_URL }}/pr/${{ steps.paths.outputs.pr_number }}/coverage/schemas/swagger-ui.html) | + ### πŸ§ͺ Test Artifacts + | | | + |---|---| + | πŸ“Š [Coverage](${{ steps.deploy.outputs.url }}/coverage/) | πŸ“š [Storybook](${{ steps.deploy.outputs.url }}/storybook/) | + | 🎭 [Playwright](${{ steps.deploy.outputs.url }}/playwright/) | | - πŸ€– Reports auto-generated from commit ${{ github.sha }} + πŸ€– Generated from commit ${{ github.sha }} diff --git a/.github/workflows/cleanup-pr-previews.yml b/.github/workflows/cleanup-pr-previews.yml deleted file mode 100644 index 0963e49e..00000000 --- a/.github/workflows/cleanup-pr-previews.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Cleanup PR Previews - -on: - pull_request: - types: [closed] - -jobs: - cleanup: - name: Remove PR preview from GitHub Pages - runs-on: ubuntu-latest - concurrency: - group: gh-pages-deploy - cancel-in-progress: false - permissions: - contents: write - steps: - - name: Checkout gh-pages branch - uses: actions/checkout@v6 - with: - ref: gh-pages - fetch-depth: 0 - - - name: Remove PR directory - run: | - set -euo pipefail - PR_DIR="pr/${{ github.event.pull_request.number }}" - - if [ -d "$PR_DIR" ]; then - echo "Removing $PR_DIR" - rm -rf "$PR_DIR" - - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - git add -A - if ! git diff --staged --quiet; then - git commit -m "Cleanup: Remove PR #${{ github.event.pull_request.number }} preview" - git push origin gh-pages - echo "Successfully removed PR #${{ github.event.pull_request.number }} preview" - else - echo "No changes to commit (directory may have been empty)" - fi - else - echo "PR directory $PR_DIR does not exist, nothing to clean up" - fi diff --git a/docs/plans/2025-12-20-source-generated-docs-design.md b/docs/plans/2025-12-20-source-generated-docs-design.md new file mode 100644 index 00000000..eab04ca8 --- /dev/null +++ b/docs/plans/2025-12-20-source-generated-docs-design.md @@ -0,0 +1,341 @@ +# Design: Source-Generated Docs on GitHub Pages + +**Ticket:** #215 - [Docs] Publish source-generated docs to GitHub Pages +**Date:** 2025-12-20 +**Status:** Approved + +## Overview + +Publish browsable API documentation generated from source code (Rust and TypeScript) to a public URL. Contributors can navigate types, modules, and public APIs without cloning the repo. + +## Decisions + +| Decision | Choice | Rationale | +|----------|--------|-----------| +| Scope | Rust + TypeScript | Both are core to the project; TypeDoc adds minimal complexity | +| Directory structure | Flat (`/rust-docs/`, `/ts-docs/`) | Matches existing pattern (`/coverage/`, `/storybook/`) | +| Hosting | Cloudflare Pages | No git storage overhead, native PR previews, 25MB/file limit works for Playwright videos | +| PR previews | Yes, for all reports including docs | Enables iteration; CF provides automatic preview URLs | +| Landing page | Simple static HTML | 11ty was vestigial; just need links | +| Sequencing | Single PR, two commits | Migration first, then docs | + +## Architecture + +### Deployment Flow + +``` +CI Build Jobs Cloudflare Pages +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ integration-tests│────┐ β”‚ β”‚ +β”‚ (coverage, β”‚ β”‚ β”‚ Production β”‚ +β”‚ playwright) β”‚ β”‚ β”‚ tiny-congress. β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β–Ό β”‚ pages.dev β”‚ +β”‚ storybook-build │──►Assemble──► β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Site β”‚ PR Previews β”‚ +β”‚ build-docs β”‚β”€β”€β”€β”€β”˜ β”‚ abc123.tiny- β”‚ +β”‚ (rust, ts) β”‚ β”‚ congress. β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ pages.dev β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Site Structure + +``` +site/ +β”œβ”€β”€ index.html # Landing page with links to all resources +β”œβ”€β”€ coverage/ # Unified coverage report (existing) +β”œβ”€β”€ storybook/ # Storybook component library (existing) +β”œβ”€β”€ playwright/ # Playwright test report (existing) +β”œβ”€β”€ rust-docs/ # cargo doc output +β”‚ β”œβ”€β”€ tinycongress_api/ +β”‚ β”œβ”€β”€ tc_crypto/ +β”‚ └── ... +└── ts-docs/ # TypeDoc output + └── ... +``` + +## Implementation + +### Commit 1: Migrate to Cloudflare Pages + +**Remove gh-pages branch approach:** +- Delete vestigial 11ty scaffolding from gh-pages +- Remove `deploy-pages` job that commits to gh-pages branch +- Remove PR cleanup workflow for gh-pages + +**Add Cloudflare Pages deployment:** + +```yaml +# .github/workflows/ci.yml + +deploy-cloudflare: + name: Deploy to Cloudflare Pages + runs-on: ubuntu-latest + needs: [integration-tests, storybook-build] + if: always() && needs.integration-tests.result != 'cancelled' + permissions: + contents: read + deployments: write + pull-requests: write + steps: + - name: Download coverage report + uses: actions/download-artifact@v6 + with: + name: coverage-report + path: site/coverage + continue-on-error: true + + - name: Download Storybook + uses: actions/download-artifact@v6 + with: + name: storybook-static + path: site/storybook + continue-on-error: true + + - name: Download Playwright report + uses: actions/download-artifact@v6 + with: + name: playwright-test-results + path: artifacts/playwright + continue-on-error: true + + - name: Organize Playwright report + run: | + if [ -d artifacts/playwright/playwright-report ]; then + mv artifacts/playwright/playwright-report site/playwright + fi + rm -rf artifacts + + - name: Generate landing page + run: | + cat > site/index.html <<'EOF' + + + + Tiny Congress - Developer Resources + + + +

Tiny Congress

+

Reports

+ +

Generated: $(date -u +"%Y-%m-%d %H:%M:%S UTC")

+ + + EOF + + - name: Deploy to Cloudflare Pages + uses: cloudflare/pages-action@v1 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + projectName: tiny-congress + directory: site + gitHubToken: ${{ secrets.GITHUB_TOKEN }} + + - name: Add PR comment with report links + if: github.event_name == 'pull_request' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: pages-reports + message: | + ## CI Reports + + | Report | Link | + |--------|------| + | Coverage | ${{ steps.deploy.outputs.url }}/coverage/ | + | Storybook | ${{ steps.deploy.outputs.url }}/storybook/ | + | Playwright | ${{ steps.deploy.outputs.url }}/playwright/ | + + Generated from commit ${{ github.sha }} +``` + +**Secrets required (already configured):** +- `CLOUDFLARE_ACCOUNT_ID`: `927a5895b62dabc04eab63dcd8bbdecd` +- `CLOUDFLARE_API_TOKEN`: (set via gh secret) + +### Commit 2: Add Documentation Generation + +**Add build-docs job:** + +```yaml +build-docs: + name: Build documentation + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 + + - name: Build Rust docs + run: cargo doc --workspace --no-deps + + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version-file: web/.nvmrc + cache: yarn + cache-dependency-path: web/yarn.lock + + - name: Enable corepack + run: corepack enable + + - name: Install dependencies + run: cd web && yarn install --immutable + + - name: Build TypeScript docs + working-directory: web + run: yarn typedoc + + - name: Upload docs artifact + uses: actions/upload-artifact@v6 + with: + name: docs + path: | + target/doc + web/docs + retention-days: 7 +``` + +**Add TypeDoc configuration (`web/typedoc.json`):** + +```json +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": ["src"], + "entryPointStrategy": "expand", + "out": "docs", + "exclude": [ + "**/*.test.ts", + "**/*.test.tsx", + "**/__mocks__/**", + "**/test-utils/**", + "src/wasm/**" + ], + "excludePrivate": true, + "excludeInternal": true, + "readme": "none" +} +``` + +**Add TypeDoc dev dependency:** + +```bash +cd web && yarn add -D typedoc +``` + +**Update deploy job to include docs:** + +```yaml +- name: Download docs + uses: actions/download-artifact@v6 + with: + name: docs + path: artifacts/docs + continue-on-error: true + +- name: Organize docs + run: | + if [ -d artifacts/docs/target/doc ]; then + mv artifacts/docs/target/doc site/rust-docs + fi + if [ -d artifacts/docs/web/docs ]; then + mv artifacts/docs/web/docs site/ts-docs + fi + rm -rf artifacts/docs +``` + +**Update landing page to include docs:** + +```html +

API Documentation

+ +

Reports

+... +``` + +**Update PR comment:** + +```markdown +| Rust Docs | ${{ steps.deploy.outputs.url }}/rust-docs/tinycongress_api/ | +| TS Docs | ${{ steps.deploy.outputs.url }}/ts-docs/ | +``` + +### Local Development + +**Add to justfile:** + +```just +# ============================================================================= +# Documentation +# ============================================================================= + +# Build and preview all docs locally +docs: + cargo doc --workspace --no-deps + cd web && yarn typedoc + @echo "Rust docs: target/doc/tinycongress_api/index.html" + @echo "TS docs: web/docs/index.html" + +# Build and open Rust docs +docs-rust: + cargo doc --workspace --no-deps --open + +# Build and open TypeScript docs +docs-ts: + cd web && yarn typedoc + open web/docs/index.html +``` + +**Update web/.gitignore:** + +``` +docs/ +``` + +## Cleanup + +After migration is verified working: + +1. Delete gh-pages branch: `git push origin --delete gh-pages` +2. Update repo Settings β†’ Pages β†’ Source to "GitHub Actions" (or leave as-is since we're using CF) +3. Remove `cleanup-pr-previews.yml` workflow (CF handles this automatically) + +## Acceptance Criteria + +- [ ] HTML docs are generated from source code (no manual copy) +- [ ] Docs are published to Cloudflare Pages on merges to master +- [ ] PR previews include docs at unique URLs +- [ ] Landing page links to each generated doc set +- [ ] Build runs in CI without secrets issues and uses pinned tool versions +- [ ] Local preview steps are documented (`just docs`, `just docs-rust`, `just docs-ts`) +- [ ] PR comments include links to rust-docs and ts-docs + +## Risks & Mitigations + +| Risk | Mitigation | +|------|------------| +| Cloudflare outage | Docs are non-critical; acceptable downtime | +| 25MB file limit | Playwright videos may need compression; monitor | +| TypeDoc config issues | Start simple, iterate based on output quality | +| Breaking existing PR comments | Test on a single PR first before merging | diff --git a/docs/plans/2025-12-20-source-generated-docs-implementation.md b/docs/plans/2025-12-20-source-generated-docs-implementation.md new file mode 100644 index 00000000..2ed5028e --- /dev/null +++ b/docs/plans/2025-12-20-source-generated-docs-implementation.md @@ -0,0 +1,487 @@ +# Source-Generated Docs Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Publish Rust and TypeScript API documentation to Cloudflare Pages with PR previews. + +**Architecture:** Replace gh-pages branch deployment with Cloudflare Pages. Add cargo doc and TypeDoc generation as a new CI job. Merge all artifacts (coverage, storybook, playwright, docs) into a single site deployed to CF. + +**Tech Stack:** Cloudflare Pages, cargo doc, TypeDoc, GitHub Actions + +--- + +## Task 1: Add TypeDoc Dependency + +**Files:** +- Modify: `web/package.json` + +**Step 1: Add typedoc as dev dependency** + +```bash +cd web && yarn add -D typedoc +``` + +**Step 2: Verify installation** + +Run: `cd web && yarn typedoc --version` +Expected: Version number (e.g., `0.27.x`) + +**Step 3: Commit** + +```bash +git add web/package.json web/yarn.lock +git commit -m "chore(web): add typedoc dependency" +``` + +--- + +## Task 2: Create TypeDoc Configuration + +**Files:** +- Create: `web/typedoc.json` +- Modify: `web/.gitignore` + +**Step 1: Create typedoc.json** + +Create file `web/typedoc.json`: + +```json +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": ["src"], + "entryPointStrategy": "expand", + "out": "docs", + "exclude": [ + "**/*.test.ts", + "**/*.test.tsx", + "**/__mocks__/**", + "**/test-utils/**", + "src/wasm/**" + ], + "excludePrivate": true, + "excludeInternal": true, + "readme": "none", + "name": "Tiny Congress Frontend" +} +``` + +**Step 2: Add docs/ to .gitignore** + +Add to `web/.gitignore`: + +``` +# TypeDoc output +docs/ +``` + +**Step 3: Test TypeDoc locally** + +Run: `cd web && yarn typedoc` +Expected: `Documentation generated at ./docs` + +Run: `ls web/docs/` +Expected: `index.html` and other generated files + +**Step 4: Commit** + +```bash +git add web/typedoc.json web/.gitignore +git commit -m "chore(web): add typedoc configuration" +``` + +--- + +## Task 3: Add Justfile Documentation Recipes + +**Files:** +- Modify: `justfile` + +**Step 1: Add docs recipes to justfile** + +Add after the "Utility Commands" section, before "Git Workflows": + +```just +# ============================================================================= +# Documentation +# ============================================================================= + +# Build all documentation locally +docs: docs-rust docs-ts + @echo "βœ“ All docs built" + @echo " Rust: target/doc/tinycongress_api/index.html" + @echo " TypeScript: web/docs/index.html" + +# Build and open Rust API docs +docs-rust: + cargo doc --workspace --no-deps --open + +# Build TypeScript docs +docs-ts: + cd web && yarn typedoc + @echo "TypeScript docs: web/docs/index.html" +``` + +**Step 2: Test recipes** + +Run: `just docs-rust` +Expected: Browser opens with Rust documentation + +Run: `just docs-ts` +Expected: `TypeScript docs: web/docs/index.html` + +**Step 3: Commit** + +```bash +git add justfile +git commit -m "chore: add documentation build recipes to justfile" +``` + +--- + +## Task 4: Add build-docs CI Job + +**Files:** +- Modify: `.github/workflows/ci.yml` + +**Step 1: Add build-docs job** + +Add after the `storybook-build` job (around line 106): + +```yaml + # ============================================================ + # JOB 0b3: Build API Documentation + # ============================================================ + build-docs: + name: Build documentation + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 + + - name: Build Rust docs + run: cargo doc --workspace --no-deps + + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version-file: web/.nvmrc + cache: yarn + cache-dependency-path: web/yarn.lock + + - name: Enable corepack + run: corepack enable + + - name: Install dependencies + run: cd web && yarn install --immutable + + - name: Build TypeScript docs + working-directory: web + run: yarn typedoc + + - name: Upload docs artifact + uses: actions/upload-artifact@v6 + with: + name: docs + path: | + target/doc + web/docs + retention-days: 7 +``` + +**Step 2: Commit** + +```bash +git add .github/workflows/ci.yml +git commit -m "ci: add build-docs job for Rust and TypeScript documentation" +``` + +--- + +## Task 5: Replace deploy-pages with Cloudflare Deployment + +**Files:** +- Modify: `.github/workflows/ci.yml` +- Delete: `.github/workflows/cleanup-pr-previews.yml` + +**Step 1: Replace deploy-pages job** + +Replace the entire `deploy-pages` job (lines 731-895) with: + +```yaml + # ============================================================ + # JOB 3: Deploy to Cloudflare Pages + # ============================================================ + deploy-cloudflare: + name: Deploy to Cloudflare Pages + runs-on: ubuntu-latest + needs: [integration-tests, storybook-build, build-docs] + if: always() && needs.integration-tests.result != 'cancelled' + permissions: + contents: read + deployments: write + pull-requests: write + steps: + - name: Create site directory + run: mkdir -p site + + - name: Download coverage report + uses: actions/download-artifact@v6 + with: + name: coverage-report + path: site/coverage + continue-on-error: true + + - name: Download Storybook + uses: actions/download-artifact@v6 + with: + name: storybook-static + path: site/storybook + continue-on-error: true + + - name: Download Playwright report + uses: actions/download-artifact@v6 + with: + name: playwright-test-results + path: artifacts/playwright + continue-on-error: true + + - name: Download docs + uses: actions/download-artifact@v6 + with: + name: docs + path: artifacts/docs + continue-on-error: true + + - name: Organize artifacts + run: | + # Playwright report is nested + if [ -d artifacts/playwright/playwright-report ]; then + mv artifacts/playwright/playwright-report site/playwright + fi + + # Rust docs + if [ -d artifacts/docs/target/doc ]; then + mv artifacts/docs/target/doc site/rust-docs + fi + + # TypeScript docs + if [ -d artifacts/docs/web/docs ]; then + mv artifacts/docs/web/docs site/ts-docs + fi + + rm -rf artifacts + + - name: Generate landing page + run: | + cat > site/index.html <<'EOF' + + + + Tiny Congress - Developer Resources + + + +

Tiny Congress

+

API Documentation

+ +

Reports

+ +

Generated from commit ${GITHUB_SHA:0:7} on $(date -u +"%Y-%m-%d %H:%M UTC")

+ + + EOF + + - name: Deploy to Cloudflare Pages + id: deploy + uses: cloudflare/pages-action@v1 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + projectName: tiny-congress + directory: site + gitHubToken: ${{ secrets.GITHUB_TOKEN }} + + - name: Add PR comment with report links + if: github.event_name == 'pull_request' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: pages-reports + message: | + ## CI Reports + + | Report | Link | + |--------|------| + | Rust Docs | [${{ steps.deploy.outputs.url }}/rust-docs/tinycongress_api/](${{ steps.deploy.outputs.url }}/rust-docs/tinycongress_api/) | + | TS Docs | [${{ steps.deploy.outputs.url }}/ts-docs/](${{ steps.deploy.outputs.url }}/ts-docs/) | + | Coverage | [${{ steps.deploy.outputs.url }}/coverage/](${{ steps.deploy.outputs.url }}/coverage/) | + | Storybook | [${{ steps.deploy.outputs.url }}/storybook/](${{ steps.deploy.outputs.url }}/storybook/) | + | Playwright | [${{ steps.deploy.outputs.url }}/playwright/](${{ steps.deploy.outputs.url }}/playwright/) | + + Generated from commit ${{ github.sha }} +``` + +**Step 2: Delete cleanup-pr-previews.yml** + +Cloudflare handles preview cleanup automatically. + +```bash +rm .github/workflows/cleanup-pr-previews.yml +``` + +**Step 3: Commit** + +```bash +git add .github/workflows/ci.yml +git rm .github/workflows/cleanup-pr-previews.yml +git commit -m "ci: migrate from GitHub Pages to Cloudflare Pages + +- Replace deploy-pages job with deploy-cloudflare +- Add docs artifacts to deployment +- Remove cleanup-pr-previews.yml (CF handles automatically) +- Update PR comment with docs links" +``` + +--- + +## Task 6: Squash into Two Logical Commits + +**Step 1: Interactive rebase to squash** + +We now have 5 commits that need to become 2: +1. Commits 1-3 β†’ "feat: add documentation generation" +2. Commits 4-5 β†’ "ci: migrate to Cloudflare Pages with docs" + +```bash +git rebase -i HEAD~5 +``` + +Reorder and squash: +``` +pick chore(web): add typedoc dependency +squash chore(web): add typedoc configuration +squash chore: add documentation build recipes to justfile +pick ci: add build-docs job for Rust and TypeScript documentation +squash ci: migrate from GitHub Pages to Cloudflare Pages +``` + +**Step 2: Edit commit messages** + +First commit message: +``` +feat: add documentation generation for Rust and TypeScript + +- Add TypeDoc dependency and configuration +- Add justfile recipes: docs, docs-rust, docs-ts +- Configure TypeDoc to exclude tests and internal modules + +Part of #215 +``` + +Second commit message: +``` +ci: migrate to Cloudflare Pages with source-generated docs + +- Replace gh-pages branch deployment with Cloudflare Pages +- Add build-docs CI job for cargo doc and TypeDoc +- Deploy rust-docs and ts-docs alongside existing reports +- Update PR comments with documentation links +- Remove cleanup-pr-previews.yml (CF handles automatically) + +Closes #215 +``` + +**Step 3: Verify commits** + +```bash +git log --oneline -3 +``` + +Expected: Two new commits plus the design doc commit + +--- + +## Task 7: Push and Verify + +**Step 1: Push branch** + +```bash +git push origin 215-generate-docs +``` + +**Step 2: Monitor CI** + +```bash +gh run watch --branch 215-generate-docs +``` + +**Step 3: Verify Cloudflare deployment** + +After CI passes, check: +- PR comment appears with links +- Click each link to verify: + - `/rust-docs/tinycongress_api/` - Rust API documentation + - `/ts-docs/` - TypeScript documentation + - `/coverage/` - Coverage report + - `/storybook/` - Storybook + - `/playwright/` - Playwright report + +**Step 4: Test local recipes** + +```bash +just docs +``` + +Expected: Both doc sets build successfully + +--- + +## Task 8: Cleanup (Post-Merge) + +After PR is merged: + +**Step 1: Delete gh-pages branch** + +```bash +git push origin --delete gh-pages +``` + +**Step 2: Update repo settings (manual)** + +Go to: Repository β†’ Settings β†’ Pages +- Note: No changes needed since we're using Cloudflare, not GitHub Pages + +--- + +## Verification Checklist + +- [ ] `just docs` builds Rust and TypeScript docs locally +- [ ] `just docs-rust` opens Rust docs in browser +- [ ] CI build-docs job passes +- [ ] Cloudflare deployment succeeds +- [ ] PR comment shows all report links +- [ ] Landing page at root URL shows all links +- [ ] Rust docs are browsable at `/rust-docs/tinycongress_api/` +- [ ] TypeScript docs are browsable at `/ts-docs/` +- [ ] PR preview URLs work (unique per commit) diff --git a/justfile b/justfile index d495d6be..b914b440 100644 --- a/justfile +++ b/justfile @@ -369,6 +369,25 @@ clean: clean-wasm cd web && rm -rf node_modules/.cache dist .vite @echo "βœ“ Build artifacts cleaned" +# ============================================================================= +# Documentation +# ============================================================================= + +# Build all documentation locally +docs: docs-rust docs-ts + @echo "βœ“ All docs built" + @echo " Rust: target/doc/tinycongress_api/index.html" + @echo " TypeScript: web/docs/index.html" + +# Build and open Rust API docs +docs-rust: + cargo doc --workspace --no-deps --open + +# Build TypeScript docs +docs-ts: + cd web && yarn typedoc + @echo "TypeScript docs: web/docs/index.html" + # ============================================================================= # Git Workflows # ============================================================================= diff --git a/service/Dockerfile.dev b/service/Dockerfile.dev index f8c56f56..174c37c7 100644 --- a/service/Dockerfile.dev +++ b/service/Dockerfile.dev @@ -43,7 +43,5 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry \ RUN install -m 0755 bin/dev-entrypoint.sh /usr/local/bin/dev-entrypoint -ENV PATH="/usr/local/cargo/bin:${PATH}" - # Default command: run the hot-reload dev entrypoint CMD ["/usr/local/bin/dev-entrypoint"] diff --git a/web/.gitignore b/web/.gitignore index 5abe9e35..d706886f 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -140,3 +140,6 @@ reports/ # Storybook build output storybook-static + +# TypeDoc output +docs/ diff --git a/web/package.json b/web/package.json index 86b70fca..cc21f6c8 100644 --- a/web/package.json +++ b/web/package.json @@ -99,6 +99,7 @@ "storybook": "^10.1.7", "stylelint": "^16.26.1", "stylelint-config-standard-scss": "^16.0.0", + "typedoc": "^0.28.15", "typescript": "^5.9.3", "typescript-eslint": "^8.49.0", "vite": "^7.2.7", diff --git a/web/scripts/build-coverage-report.mjs b/web/scripts/build-coverage-report.mjs index 408e6427..0552e723 100644 --- a/web/scripts/build-coverage-report.mjs +++ b/web/scripts/build-coverage-report.mjs @@ -318,6 +318,14 @@ function generateIndexHtml(reports, schemas = []) { padding: 2rem; } .container { max-width: 900px; margin: 0 auto; } + .back-link { + display: inline-block; + color: var(--accent); + text-decoration: none; + font-size: 0.875rem; + margin-bottom: 1.5rem; + } + .back-link:hover { text-decoration: underline; } h1 { font-size: 1.75rem; margin-bottom: 0.5rem; @@ -378,6 +386,7 @@ function generateIndexHtml(reports, schemas = []) {
+ ← Back to Developer Resources

Coverage Report

Generated ${new Date().toISOString().split('T')[0]}

diff --git a/web/typedoc.json b/web/typedoc.json new file mode 100644 index 00000000..642a29b5 --- /dev/null +++ b/web/typedoc.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": ["src"], + "entryPointStrategy": "expand", + "out": "docs", + "exclude": [ + "**/*.test.ts", + "**/*.test.tsx", + "**/__mocks__/**", + "**/test-utils/**", + "src/wasm/**", + "**/__tests__/**" + ], + "excludePrivate": true, + "excludeInternal": true, + "readme": "none", + "name": "Tiny Congress Frontend", + "skipErrorChecking": true +} diff --git a/web/yarn.lock b/web/yarn.lock index 0973bfcf..dc6197f1 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -778,6 +778,19 @@ __metadata: languageName: node linkType: hard +"@gerrit0/mini-shiki@npm:^3.17.0": + version: 3.20.0 + resolution: "@gerrit0/mini-shiki@npm:3.20.0" + dependencies: + "@shikijs/engine-oniguruma": "npm:^3.20.0" + "@shikijs/langs": "npm:^3.20.0" + "@shikijs/themes": "npm:^3.20.0" + "@shikijs/types": "npm:^3.20.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + checksum: 10c0/d362ea7c20709ddfaa651003d8013d58aa6e63ff1ec49f20461ce49708ad5963c2aec3c3b4c322bb4646b9c8c761ccbf5acfe7a29d8507930de163ba3591d4af + languageName: node + linkType: hard + "@graphql-codegen/add@npm:^6.0.0": version: 6.0.0 resolution: "@graphql-codegen/add@npm:6.0.0" @@ -2353,6 +2366,51 @@ __metadata: languageName: node linkType: hard +"@shikijs/engine-oniguruma@npm:^3.20.0": + version: 3.20.0 + resolution: "@shikijs/engine-oniguruma@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + checksum: 10c0/4a5a8f316a8482e799cd836c8e3f8ba83274b3631b2d66ec82ad839b0ee1dd3df50a08480f791d59f22e42bf6b707032f043a9f651445efc04e59b7ec9e669c9 + languageName: node + linkType: hard + +"@shikijs/langs@npm:^3.20.0": + version: 3.20.0 + resolution: "@shikijs/langs@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + checksum: 10c0/6830460025d0df4c527ffeacf0a78cd4331ffde1cfcd1e8028aa9814be8a4cea84367dd938528a9b55de72b163c58ad3576915ea08c3d0a29ef1dc80e120116c + languageName: node + linkType: hard + +"@shikijs/themes@npm:^3.20.0": + version: 3.20.0 + resolution: "@shikijs/themes@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + checksum: 10c0/d6fc059c51c3c0694e026cc1f80eed927d9b91adaeda0fb3fd5725eabc6d066aaf022919def435245446ae91e3da541ed6d88d875cf59a35bfbabb6920efb6da + languageName: node + linkType: hard + +"@shikijs/types@npm:3.20.0, @shikijs/types@npm:^3.20.0": + version: 3.20.0 + resolution: "@shikijs/types@npm:3.20.0" + dependencies: + "@shikijs/vscode-textmate": "npm:^10.0.2" + "@types/hast": "npm:^3.0.4" + checksum: 10c0/7faea130362a6cdf3d66fcb47d6b609a8e0209e76ba86688f56a65411b6ae400a37414cd1a3a2fe1ee3fe39f18e274585d3972129c7e79244aaa0c15bc8f1c21 + languageName: node + linkType: hard + +"@shikijs/vscode-textmate@npm:^10.0.2": + version: 10.0.2 + resolution: "@shikijs/vscode-textmate@npm:10.0.2" + checksum: 10c0/36b682d691088ec244de292dc8f91b808f95c89466af421cf84cbab92230f03c8348649c14b3251991b10ce632b0c715e416e992dd5f28ff3221dc2693fd9462 + languageName: node + linkType: hard + "@standard-schema/spec@npm:^1.0.0": version: 1.1.0 resolution: "@standard-schema/spec@npm:1.1.0" @@ -2818,6 +2876,15 @@ __metadata: languageName: node linkType: hard +"@types/hast@npm:^3.0.4": + version: 3.0.4 + resolution: "@types/hast@npm:3.0.4" + dependencies: + "@types/unist": "npm:*" + checksum: 10c0/3249781a511b38f1d330fd1e3344eed3c4e7ea8eff82e835d35da78e637480d36fad37a78be5a7aed8465d237ad0446abc1150859d0fde395354ea634decf9f7 + languageName: node + linkType: hard + "@types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.6 resolution: "@types/istanbul-lib-coverage@npm:2.0.6" @@ -2866,6 +2933,13 @@ __metadata: languageName: node linkType: hard +"@types/unist@npm:*": + version: 3.0.3 + resolution: "@types/unist@npm:3.0.3" + checksum: 10c0/2b1e4adcab78388e088fcc3c0ae8700f76619dbcb4741d7d201f87e2cb346bfc29a89003cfea2d76c996e1061452e14fcd737e8b25aacf949c1f2d6b2bc3dd60 + languageName: node + linkType: hard + "@types/use-sync-external-store@npm:^0.0.6": version: 0.0.6 resolution: "@types/use-sync-external-store@npm:0.0.6" @@ -4667,6 +4741,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^4.4.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250 + languageName: node + linkType: hard + "entities@npm:^6.0.0": version: 6.0.1 resolution: "entities@npm:6.0.1" @@ -6947,6 +7028,15 @@ __metadata: languageName: node linkType: hard +"linkify-it@npm:^5.0.0": + version: 5.0.0 + resolution: "linkify-it@npm:5.0.0" + dependencies: + uc.micro: "npm:^2.0.0" + checksum: 10c0/ff4abbcdfa2003472fc3eb4b8e60905ec97718e11e33cca52059919a4c80cc0e0c2a14d23e23d8c00e5402bc5a885cdba8ca053a11483ab3cc8b3c7a52f88e2d + languageName: node + linkType: hard + "lint-staged@npm:^16.2.7": version: 16.2.7 resolution: "lint-staged@npm:16.2.7" @@ -7113,6 +7203,13 @@ __metadata: languageName: node linkType: hard +"lunr@npm:^2.3.9": + version: 2.3.9 + resolution: "lunr@npm:2.3.9" + checksum: 10c0/77d7dbb4fbd602aac161e2b50887d8eda28c0fa3b799159cee380fbb311f1e614219126ecbbd2c3a9c685f1720a8109b3c1ca85cc893c39b6c9cc6a62a1d8a8b + languageName: node + linkType: hard + "lz-string@npm:^1.5.0": version: 1.5.0 resolution: "lz-string@npm:1.5.0" @@ -7245,6 +7342,7 @@ __metadata: storybook: "npm:^10.1.7" stylelint: "npm:^16.26.1" stylelint-config-standard-scss: "npm:^16.0.0" + typedoc: "npm:^0.28.15" typescript: "npm:^5.9.3" typescript-eslint: "npm:^8.49.0" vite: "npm:^7.2.7" @@ -7262,6 +7360,22 @@ __metadata: languageName: node linkType: hard +"markdown-it@npm:^14.1.0": + version: 14.1.0 + resolution: "markdown-it@npm:14.1.0" + dependencies: + argparse: "npm:^2.0.1" + entities: "npm:^4.4.0" + linkify-it: "npm:^5.0.0" + mdurl: "npm:^2.0.0" + punycode.js: "npm:^2.3.1" + uc.micro: "npm:^2.1.0" + bin: + markdown-it: bin/markdown-it.mjs + checksum: 10c0/9a6bb444181d2db7016a4173ae56a95a62c84d4cbfb6916a399b11d3e6581bf1cc2e4e1d07a2f022ae72c25f56db90fbe1e529fca16fbf9541659dc53480d4b4 + languageName: node + linkType: hard + "math-intrinsics@npm:^1.1.0": version: 1.1.0 resolution: "math-intrinsics@npm:1.1.0" @@ -7290,6 +7404,13 @@ __metadata: languageName: node linkType: hard +"mdurl@npm:^2.0.0": + version: 2.0.0 + resolution: "mdurl@npm:2.0.0" + checksum: 10c0/633db522272f75ce4788440669137c77540d74a83e9015666a9557a152c02e245b192edc20bc90ae953bbab727503994a53b236b4d9c99bdaee594d0e7dd2ce0 + languageName: node + linkType: hard + "meow@npm:^13.2.0": version: 13.2.0 resolution: "meow@npm:13.2.0" @@ -8249,6 +8370,13 @@ __metadata: languageName: node linkType: hard +"punycode.js@npm:^2.3.1": + version: 2.3.1 + resolution: "punycode.js@npm:2.3.1" + checksum: 10c0/1d12c1c0e06127fa5db56bd7fdf698daf9a78104456a6b67326877afc21feaa821257b171539caedd2f0524027fa38e67b13dd094159c8d70b6d26d2bea4dfdb + languageName: node + linkType: hard + "punycode@npm:^2.1.0, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" @@ -9911,6 +10039,23 @@ __metadata: languageName: node linkType: hard +"typedoc@npm:^0.28.15": + version: 0.28.15 + resolution: "typedoc@npm:0.28.15" + dependencies: + "@gerrit0/mini-shiki": "npm:^3.17.0" + lunr: "npm:^2.3.9" + markdown-it: "npm:^14.1.0" + minimatch: "npm:^9.0.5" + yaml: "npm:^2.8.1" + peerDependencies: + typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x + bin: + typedoc: bin/typedoc + checksum: 10c0/b5988ebebb367fed44f110bbd37baee85fe95fe10c8d5a511c33d787eb1e924e66ba54cb0763d63ed2c406adbd32fcb87bcbc3fd61b0bc8ab6f3a6c06f2de978 + languageName: node + linkType: hard + "typescript-eslint@npm:^8.49.0": version: 8.50.0 resolution: "typescript-eslint@npm:8.50.0" @@ -9955,6 +10100,13 @@ __metadata: languageName: node linkType: hard +"uc.micro@npm:^2.0.0, uc.micro@npm:^2.1.0": + version: 2.1.0 + resolution: "uc.micro@npm:2.1.0" + checksum: 10c0/8862eddb412dda76f15db8ad1c640ccc2f47cdf8252a4a30be908d535602c8d33f9855dfcccb8b8837855c1ce1eaa563f7fa7ebe3c98fd0794351aab9b9c55fa + languageName: node + linkType: hard + "uglify-js@npm:^3.1.4": version: 3.19.3 resolution: "uglify-js@npm:3.19.3"