Skip to content

hexplus/pegasus

Repository files navigation

Pegasus πŸͺΆ

⚠️ Work in progress β€” pre-release software. Pegasus is under active development and has not been published to npm. APIs, generated-code shape, schema syntax, and CLI flags can all change without notice. Don't use it for production projects yet; do try it, file issues, and read PLAN.md for what's stable vs. what's still moving.

YAML-driven full-stack app generator. Schemas β†’ working app, with a visual editor, multiple framework adapters, and one-click GitHub export.

Pegasus reads YAML schema files describing your data models, fields, relations, endpoints, and auth, and produces a runnable application β€” database schema, ORM models, API routes, auth flows, frontend pages, and project scaffolding (package.json, tsconfig.json, …) all included.

schemas (.pegasus/*.yml)  ──┐
                            β”‚   pegasus generate
config.yml                  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Ί production app
                            β”‚   (one of seven targets)
adapter selection β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Quick start

# Prereqs: Node 20+, pnpm (via corepack)
corepack enable
pnpm install
pnpm build

# Try Pegasus Studio in seconds β€” creates a sandbox project + opens
# the browser UI at http://127.0.0.1:3031
pnpm studio

Or hands-on with the CLI:

# 1. Scaffold a project
node packages/cli/bin/pegasus.js init my-app
cd my-app

# 2. Pick a backend adapter (any of: nextjs, express, fastapi, laravel)
node ../packages/cli/bin/pegasus.js adapters add @pegasus/adapter-nextjs

# 3. Generate
node ../packages/cli/bin/pegasus.js generate

# 4. Build the generated app
pnpm install
cp .env.example.generated .env       # set DATABASE_URL + JWT_SECRET
pnpm db:migrate
pnpm dev                              # http://localhost:3000

Once published to npm, the flow becomes the familiar npx @pegasus/cli init.

What you get

A pegasus generate against the bundled core schemas (10 base SaaS models) and @pegasus/adapter-nextjs produces:

  • Prisma schema β€” every model with FKs, indexes, @@unique composite indexes, soft-delete columns where declared
  • 20+ API route handlers β€” per-model CRUD with auth middleware, pagination (offset + cursor), owner-field scoping, admin-only field guards, hashed-field auto-hashing
  • Full auth surface β€” /api/auth/{login,register,refresh,logout,me,forgot-password,reset-password,verify-email,magic-link,oauth/[provider]}
  • Frontend pages β€” login, register, forgot/reset, magic-link, verify-email, dashboard with a typed <DataTable> component
  • Project scaffolding β€” package.json (pinned next/react/prisma/argon2/zod), tsconfig.json (strict, Next-matched), next.config.mjs, README.md, .env.example.generated

pnpm install && pnpm build produces a Vercel-ready app.

Studio

pnpm studio (or pegasus studio from any project root) launches a local browser UI at http://127.0.0.1:3031 for editing schemas without touching YAML directly.

Page What it does
/ Schema list with entry/partial tag chips
/schemas/[stem] Visual form editor β€” field/relation/endpoint rows; round-trips losslessly with un-exposed attrs (hooks, indexes, admin_only, hashed, …) preserved
/schemas/[stem]?view=yaml Raw YAML editor (the textarea, with rollback on validation failure)
/new New-model wizard β€” create a schema from a form
/project Visual .pegasus/config.yml editor with adapter dropdowns
/generate Read-only diff preview β€” classifies each planned file as new/updated/edited/protected/orphan/unchanged
/preview List of generated files currently on disk
/export/github Push the project to a fresh GitHub repo via the REST API in 6 calls (form takes a PAT, used once, never stored)

Loopback-only by default (127.0.0.1), CSP-clean, CSRF-guarded, accessible (skip-link, focus rings, aria-current, breadcrumbs), light + dark theme.

Adapters

Backend (pick one):

Package Stack Tests
@pegasus/adapter-nextjs Next.js 14 App Router + Prisma + JWT (full-stack β€” bundles a frontend) 101
@pegasus/adapter-express Express 4 + Prisma + JWT (pair with a frontend adapter) 12
@pegasus/adapter-fastapi FastAPI + SQLAlchemy 2 (async) + Pydantic v2 + argon2 (Python) 8
@pegasus/adapter-laravel Laravel 11: Eloquent + FormRequests + apiResource (PHP) 7

Frontend (pair with a non-bundling backend):

Package Stack Tests
@pegasus/adapter-react Vite + React 18 SPA, react-router, typed API client 7
@pegasus/adapter-vue Nuxt 3 + Vue 3 Composition API, typed useApi() / useAuth() 6

Meta:

Package Output Tests
@pegasus/adapter-openapi OpenAPI 3.1 spec from schemas β€” feed to Swagger UI / Redoc / openapi-generator 11

Discover community adapters with pegasus adapters search. Build your own in ~300 lines using the contract documented in ADAPTERS.md; @pegasus/adapter-openapi is the canonical reference implementation.

Databases

PostgreSQL Β· MySQL Β· SQLite β€” all three supported by the Next.js and Express adapters via Prisma. SQLite needs no server (zero-setup dev: DATABASE_URL="file:./dev.db"); enums and Json fall back to String with the API-layer Zod validators still enforcing constraints. PostgreSQL and MySQL get native enums and JSON columns.

Auth surface

Generated apps ship with:

  • Email + password with argon2id hashing
  • JWT access tokens (HS256, 15min default TTL, alg+typ header check)
  • Opaque refresh tokens (random 48 bytes, hashed at rest, rotation + reuse detection that revokes every active token for the user on reuse)
  • Forgot/reset password with purpose-bound JWTs (15min TTL, identical 200 response regardless of email existence β€” no enumeration oracle)
  • Email verification (24h TTL, idempotent confirm)
  • Magic-link sign-in (10min TTL, one-page form + auto-consume)
  • OAuth2 (Google + GitHub) β€” authorization-code flow, signed state cookie + double-check, email-based account linking, no SDK dependency
  • Per-IP rate limiting on login (10/min), register (20/min), forgot-password (5/min), magic-link (5/min) β€” in-memory LRU default, Upstash swap-in recipe in the file header

User-extensible via before/after_{create,update,delete} hooks β€” the adapter generates non-overwritable stubs at src/hooks/<name>.ts.

Repository layout

pegasus/
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ core/                     # @pegasus/core β€” engine
β”‚   β”œβ”€β”€ core-schemas/             # @pegasus/core-schemas β€” 10 base SaaS schemas
β”‚   β”œβ”€β”€ cli/                      # @pegasus/cli β€” the `pegasus` binary
β”‚   β”œβ”€β”€ studio/                   # @pegasus/studio β€” browser UI
β”‚   β”œβ”€β”€ adapter-nextjs/
β”‚   β”œβ”€β”€ adapter-express/
β”‚   β”œβ”€β”€ adapter-fastapi/
β”‚   β”œβ”€β”€ adapter-laravel/
β”‚   β”œβ”€β”€ adapter-react/
β”‚   β”œβ”€β”€ adapter-vue/
β”‚   └── adapter-openapi/
β”œβ”€β”€ scripts/
β”‚   └── studio.mjs                # `pnpm studio` launcher (sandbox project)
β”œβ”€β”€ ADAPTERS.md                   # Adapter-author guide
β”œβ”€β”€ CLOUD.md                      # Pegasus Cloud design sketch
β”œβ”€β”€ PLAN.md                       # Full design + roadmap
β”œβ”€β”€ turbo.json
β”œβ”€β”€ pnpm-workspace.yaml
└── tsconfig.base.json

CLI commands

pegasus init <name>             # scaffold a project
pegasus add model <name>        # add a new model schema
pegasus validate                # check schemas without generating
pegasus generate                # write generated code
pegasus generate --extend       # re-generate, preserving developer edits (via .pegasus/checksums.json)
pegasus generate --dry-run      # preview without writing
pegasus diff                    # classify each planned file (new/updated/edited/protected/orphan)
pegasus doctor                  # health check (schemas + config + adapter resolvable)
pegasus adapters list           # show first-party + configured adapters
pegasus adapters add <pkg>      # wire an adapter into config.yml
pegasus adapters search [q]     # discover community adapters via npm
pegasus studio [--port N]       # launch the browser UI

Development

pnpm install
pnpm build           # turbo β€” every package
pnpm test            # vitest across the workspace
pnpm typecheck       # strict TS across the workspace
pnpm lint
pnpm format
pnpm studio          # bring up the UI against scripts/studio-sandbox/

Single package:

pnpm --filter @pegasus/core test
pnpm --filter @pegasus/adapter-nextjs test:watch

Security posture

Security is a first-class concern. Highlights, by layer:

Engine (@pegasus/core)

  • No YAML code execution β€” every yaml.load uses JSON_SCHEMA (blocks !!js/function and custom tags)
  • Path traversal blocked at parse time + via fs.realpath containment
  • Prototype-pollution defense: strict Zod schemas + __proto__/constructor/prototype blocklist in deep-merge
  • DoS bounds: file size 256 KB, extends depth 16, files-per-dir 10 000

CLI (@pegasus/cli)

  • Output paths validated via assertProjectPath β€” refuses anything escaping the project root or landing in node_modules/
  • pegasus adapters search caps registry response at 2 MB (stream-with-cap reader, not buffer-all)

Studio (@pegasus/studio)

  • Loopback-bound by default; remote access is an explicit --host opt-in
  • Origin/Referer CSRF check on every state-changing request (works on Firefox via Referrer-Policy: same-origin)
  • 64 KB body cap; stricter stem regex + node_modules refusal on every file write
  • Strict CSP (default-src 'self'; 'unsafe-inline' only for the design-token <style> block)
  • Server-side validation for every external API user input β€” including GitHub-export owner/repo (regex-validated; client-side pattern= is never the only check)

Generated apps (@pegasus/adapter-nextjs)

  • argon2id password hashing
  • HttpOnly + SameSite=Strict refresh cookie; refresh-token rotation with reuse detection that revokes every active token for the user
  • Explicit alg + typ JWT header checks (alg-confusion defense)
  • Cache-Control: no-store on every auth response
  • Public POST /users suppressed on the JWT-owning schema (registration only via /auth/register); non-admin PATCH rejects bodies containing admin_only fields
  • Per-IP rate limiting on login/register/forgot-password/magic-link with true LRU eviction (under sustained churn an attacker can't bypass by cycling IPs)
  • OAuth2 same-origin returnTo validation at both /start and /callback (open-redirect defense); Google email_verified enforcement
  • Email-flow purpose tokens cross-purpose refusal (a reset token can't be replayed as a verify token, etc.)

Testing

350 tests across 11 packages:

Package Tests
@pegasus/core 48
@pegasus/core-schemas 10
@pegasus/cli 80
@pegasus/studio 60
@pegasus/adapter-nextjs 101
@pegasus/adapter-express 12
@pegasus/adapter-fastapi 8
@pegasus/adapter-laravel 7
@pegasus/adapter-react 7
@pegasus/adapter-vue 6
@pegasus/adapter-openapi 11

CI runs typecheck Β· lint Β· format:check Β· build Β· test Β· pnpm audit --prod --audit-level high on ubuntu Β· macos Β· windows Γ— Node 20 Β· 22.

Status

The OSS roadmap is feature-complete. Every line item in PLAN.md is [x] (done) or [~] with a documented deferred follow-up. Pegasus Cloud is scoped as a separate hosted product in CLOUD.md.

What's deliberately not in scope:

  • Hosting the generated app (deploy to whatever platform you already use)
  • Owning user data (apps connect to customer-managed databases)
  • Locking schemas in (pegasus generate is the source of truth β€” your .pegasus/ directory is portable, version-controllable, and works identically against the OSS CLI forever)

Documentation

  • PLAN.md β€” full design document + closeout roadmap
  • ADAPTERS.md β€” BackendAdapter contract + author's guide
  • CLOUD.md β€” Pegasus Cloud (hosted) design sketch
  • Each packages/<name>/README.md β€” package-specific surface

License

MIT β€” see LICENSE.

About

Stack-Agnostic Boilerplate Builder. Speed up your Saas MVP development.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors