Adds anchor-based image album generation across docs, skeleton, and rendered
full-monorepo. One subject description + one anchor image + N directed shots,
covering personas, products, characters, and brand assets out of the box.
## What ships
**Skeleton packages:**
- pkg/album/types.go — Album, Shot, ShotStatus, ShotTemplate, AlbumUpdater
- pkg/album/templates.go — PortraitSession, ProductShoot, CharacterSheet built-ins
- pkg/album/handler.go — AnchorHandler + ShotHandler queue job handlers
- packages/realtime/src/useAlbumGeneration.ts — SSE hook owning all album state
- packages/ui/src/components/AlbumGrid.tsx — responsive shot grid with shimmer
- packages/ui/src/components/ShotCard.tsx — pending/generating/complete/failed states
- packages/ui/src/components/AnchorPreview.tsx — anchor CTA + image with controls
**Component service template:**
- internal/port/album.go — AlbumRepository interface
- internal/adapter/memory/album.go — in-memory repo for standalone dev
- internal/service/album.go — create, list, get, generateAnchor, generateAllShots
- internal/api/handlers/album.go — HTTP handlers (CRUD + 202 generation endpoints)
- Routes: GET/POST /albums, GET/DELETE /albums/{id}, POST /albums/{id}/anchor,
POST/DELETE /albums/{id}/shots, POST /albums/{id}/shots/{index}
**Documentation:**
- .claude/guides/album.md — full guide with API, SSE events, frontend usage
**Key architecture decisions:**
- Anchor bytes never stored in queue payload — workers fetch AnchorURL at runtime
- Generation order enforced: POST /shots returns 422 if no anchor exists
- All album SSE events on existing user:<userId> channel (no new channel)
- AlbumUpdater interface lets job handlers update repo from inside queue workers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
50 lines
1.5 KiB
Bash
Executable File
50 lines
1.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# generate-sdk.sh — Generate the @orchard9/rdev-sdk TypeScript SDK from the embedded OpenAPI spec.
|
|
# No server, DB, or K8s needed. The spec is exported directly from the Go binary.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ROOT="$SCRIPT_DIR/.."
|
|
SDK_DIR="$ROOT/sdk"
|
|
|
|
# 1. Check speakeasy is installed
|
|
if ! command -v speakeasy &>/dev/null; then
|
|
echo "speakeasy CLI not found. Installing..."
|
|
if command -v brew &>/dev/null; then
|
|
brew install speakeasy-api/speakeasy/speakeasy
|
|
else
|
|
# Install to ~/.local/bin (no sudo needed)
|
|
mkdir -p "$HOME/.local/bin"
|
|
curl -fsSL https://raw.githubusercontent.com/speakeasy-api/speakeasy/main/install.sh \
|
|
| INSTALL_DIR="$HOME/.local/bin" sh
|
|
export PATH="$HOME/.local/bin:$PATH"
|
|
fi
|
|
fi
|
|
|
|
# 2. Export the OpenAPI spec (no server needed — pure Go, no external deps)
|
|
echo "Exporting OpenAPI spec..."
|
|
go run "$ROOT/cmd/rdev-api" --export-openapi > "$SDK_DIR/openapi.json"
|
|
echo " -> $SDK_DIR/openapi.json"
|
|
|
|
# 3. Validate the spec
|
|
echo "Validating spec..."
|
|
speakeasy validate openapi -s "$SDK_DIR/openapi.json"
|
|
|
|
# 4. Generate the TypeScript SDK
|
|
echo "Generating TypeScript SDK..."
|
|
speakeasy generate sdk \
|
|
--schema "$SDK_DIR/openapi.json" \
|
|
--lang typescript \
|
|
--out "$SDK_DIR/typescript" \
|
|
--config "$SDK_DIR/.speakeasy/gen.yaml"
|
|
|
|
# 5. Install dependencies and build
|
|
echo "Building SDK..."
|
|
cd "$SDK_DIR/typescript"
|
|
npm install
|
|
npm run build
|
|
|
|
echo ""
|
|
echo "Done! SDK generated at sdk/typescript/"
|
|
echo "Test with: cd sdk/typescript && npm pack --dry-run"
|