YAML-based API mocking server
Project description
seyon
A YAML-driven API mocking tool that parses schema definitions from YAML files, validates them, generates databases (SQLite or PostgreSQL) with mock data, and serves a dynamic REST API — all from a single YAML spec.
Features
- Define your database schema (tables, columns, types, constraints) in YAML
- Validate the YAML schema for correctness
- Generate SQLite (local
.dbfile) or PostgreSQL (remote server) databases - Populate tables with realistic mock data (random phone numbers, emails, UUIDs, etc.)
- Serve a FastAPI REST server with auto-generated CRUD endpoints per model
- Pagination, filtering, sorting on all list endpoints
- Relation resolution — foreign keys auto-resolve to full referenced objects
- Handle
PRIMARY KEY,UNIQUE,NOT NULL,AUTOINCREMENT/SERIAL, andmax-lengthconstraints automatically - Support for Neon.tech serverless PostgreSQL (auto-resolves hostnames via Google DNS)
Project Structure
seyon/
├── src/
│ ├── seyon/
│ │ └── main.py # CLI entry point (start, generate, validate, serve)
│ ├── database/
│ │ ├── base.py # DatabaseAbstract — abstract base class
│ │ ├── factory.py # DataFactory — selects DB generator by type
│ │ ├── sqlite_generator.py # SQLiteGenerator — table creation & data insertion
│ │ └── postgress_generator.py # PostgressGenerator — PostgreSQL implementation
│ ├── parser/
│ │ └── yaml_load.py # load_yaml — reads and parses YAML files
│ ├── schema/
│ │ ├── constants.py # Elements — supported types & allowed properties
│ │ ├── field.py # Field — column definition & mock value generation
│ │ ├── model.py # Model — table definition & validation
│ │ └── project.py # Project — top-level spec & validation
│ ├── server/
│ │ ├── app.py # create_app(project) — FastAPI factory
│ │ ├── router_builder.py # Dynamic CRUD route registration per model
│ │ └── response_builder.py # Delegates to DB generator, resolves relations
│ └── util/
│ ├── config.py # Settings — paths, DB name, defaults
│ ├── exeception.py # ProjectException — structured error reporting
│ └── logging.py # Logging — file-based timestamped logs
├── employee.yaml # Example single-model YAML spec
├── test_multi.yaml # Example multi-model YAML spec
├── pyproject.toml # Package metadata & build config
├── requirements.txt # Python dependencies
├── skills/
│ └── skill.md # IDE skill for spec authoring
└── README.md
Installation
Prerequisites
- Python 3.10 or higher
- pip
- (Optional) PostgreSQL server or Neon.tech account for PSQL backend
Steps
-
Clone the repository
git clone <repo-url> cd seyon
-
Create a virtual environment (recommended)
python -m venv .venv .venv\Scripts\activate # Windows # source .venv/bin/activate # Linux/macOS
-
Install the package
pip install -e .
This installs the
seyonCLI command and dependencies (pyyaml,psycopg2-binary).
Usage
CLI Commands
seyon <command> --file <yaml-file>
| Command | Description |
|---|---|
validate |
Load and validate the YAML schema |
generate |
Validate, create tables, and populate with mock data |
start |
Validate and create tables only |
serve |
Validate, create tables, and start the REST API server |
Examples
# Validate a YAML file
seyon validate --file employee.yaml
# Generate SQLite database with mock data
seyon generate --file employee.yaml
# Generate PostgreSQL database with mock data
seyon generate --file test_multi.yaml
# Start the REST API server (FastAPI)
seyon serve --file test_multi.yaml --port 8000
SQLite: generates mock.db in the current directory.
PostgreSQL: connects to the remote server specified in the database: section.
Server API
When you run seyon serve, a FastAPI server starts with auto-generated CRUD endpoints for each model in the spec.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Project info + model list |
GET |
/{model_name} |
List rows (paginated) |
GET |
/{model_name}/{id} |
Get row by primary key |
POST |
/{model_name} |
Create a new row |
PUT |
/{model_name}/{id} |
Update row by primary key |
DELETE |
/{model_name}/{id} |
Delete row by primary key |
Interactive API docs at http://localhost:8000/docs (Swagger UI).
Pagination
GET /{model_name} returns a paginated envelope:
{ "total": 50, "skip": 0, "limit": 100, "data": [...] }
| Param | Default | Description |
|---|---|---|
skip |
0 |
Number of rows to skip |
limit |
100 |
Max rows to return (max 1000) |
Example: GET /employee?skip=10&limit=20
Filtering
Any query param matching a field name becomes an equality filter. Supports operators via __ suffix:
| Operator | Example |
|---|---|
eq (default) |
?name=John or ?name__eq=John |
ne |
?name__ne=John |
lt |
?age__lt=30 |
gt |
?age__gt=18 |
lte |
?age__lte=65 |
gte |
?age__gte=21 |
contains |
?name__contains=oh |
startswith |
?name__startswith=J |
endswith |
?name__endswith=n |
Example: GET /employee?department_id=1&age__gt=25
Sorting
| Param | Default | Description |
|---|---|---|
sort_by |
— | Field name to sort by |
sort_order |
asc |
asc or desc |
Example: GET /employee?sort_by=name&sort_order=desc
Relations
Fields with type: relation and references: are auto-resolved to full objects in responses:
models:
department:
fields:
id: { type: integer, primarykey: true }
name: { type: string }
employee:
fields:
id: { type: integer, primarykey: true }
department_id: { type: relation, references: department }
Response to GET /employee/1:
{
"id": 1,
"department_id": { "id": 1, "name": "Engineering" }
}
Use ?resolve_relations=false to get raw foreign key integers.
YAML Schema Reference
Database Backend Configuration
database:
type: sqlite | psql | postgresql # required — backend selection
# PostgreSQL-only fields (ignored for SQLite):
db_host: localhost # default: localhost
db_port: 5432 # default: 5432
db_name: mydb # default: mock
db_username: user # default: root
db_password: pass # default: root
db_sslmode: require # optional — e.g. require, disable, verify-full
db_options: endpoint=my-endpoint # optional — extra connection parameters
Neon.tech: Hostnames ending with
.neon.techare auto-resolved via Google DNS (8.8.8.8). The endpoint ID is extracted from the hostname and passed as a connection option automatically.
Supported Data Types
| Type | Description | Generated Value |
|---|---|---|
| integer | Whole number | 1 (sequential for primary keys) |
| string | Text | "example" |
| boolean | True/false | True |
| float | Decimal number | 1.0 |
| double | Double-precision float | 1.0 |
| bigint | Large integer | 1234567890123456789 |
| phone | Phone number | Random 10-digit Indian mobile |
| Email address | Random username@example.com |
|
| date | Calendar date | Current date |
| datetime | Date and time | Current timestamp |
| time | Time of day | Current time |
| text | Long text | Lorem ipsum placeholder |
| uuid | UUID v4 | Random UUID string |
| url | Web URL | https://example.com |
| json | JSON object | {"key": "value"} |
| relation | Foreign key to another model | Random valid PK from referenced model |
PostgreSQL Type Mapping
When using type: psql, YAML types are mapped to PostgreSQL column types:
| YAML type | PostgreSQL type |
|---|---|
| integer | INTEGER |
| bigint | BIGINT |
| float | REAL |
| double | DOUBLE PRECISION |
| string | VARCHAR(255) |
| text | TEXT |
| boolean | BOOLEAN |
| date | DATE |
| datetime | TIMESTAMP |
| time | TIME |
| VARCHAR(255) | |
| phone | VARCHAR(20) |
| password | VARCHAR(255) |
| url | VARCHAR(500) |
| uuid | UUID |
| json | JSONB |
| relation | INTEGER |
Constraints
primarykey: For integer primary keys, values autoincrement from 1.unique: Phone fields use sequential offset, email fields use indexed username, other string types get a_Nsuffix.required: AddsNOT NULLconstraint to the column.max-length: Optional positive integer. Forstring,email,password,url,phone, andtexttypes, setsVARCHAR(n)column length in DDL and limits generated mock values. Example:max-length: 100.autoincrement: Optional boolean. Only forintegertype. UsesAUTOINCREMENTin SQLite andSERIALin PostgreSQL. The field is omitted from INSERT statements so the DB assigns the value.
Example: SQLite (Single Model)
project: employee-management
database:
type: sqlite
models:
employee:
count: 100
fields:
id:
type: integer
primarykey: true
username:
type: string
unique: true
email:
type: email
mobile:
type: phone
Example: PostgreSQL (Multiple Models)
project: company-management
database:
type: psql
db_host: your-instance.region.neon.tech
db_port: 5432
db_name: neondb
db_username: neondb_owner
db_password: your-password
db_sslmode: require
models:
employee:
count: 50
fields:
id:
type: integer
primarykey: true
name:
type: string
email:
type: email
mobile:
type: phone
department_id:
type: relation
references: department
department:
count: 10
fields:
id:
type: integer
primarykey: true
name:
type: string
unique: true
head_count:
type: integer
project:
count: 30
fields:
id:
type: integer
primarykey: true
title:
type: string
unique: true
budget:
type: float
start_date:
type: date
Data Flow
YAML File
│
▼
parser/yaml_load.py ──► dict
│
▼
schema/ ──► Project (validated) ──► Model ──► Field
│
├── validate / generate ──────────────────► database/factory.py
│ │
│ ├── sqlite ────────────┤───► SQLiteGenerator
│ │ │ │
│ └── psql ──────────────┘───► PostgressGenerator
│ │
│ mock.db ◄───────┘
│ PostgreSQL ◄───────┘
│
└── serve ──► server/app.py (create_app)
│
▼
server/router_builder.py
│
▼
FastAPI routes per model
│
▼
server/response_builder.py
│
▼
database/generator CRUD methods
Logging
Logs are written to logs/<DD_MM_YYYY_HH>/<DD_MM_YYYY_HH>.log with timestamps and log levels.
Development
Running from source
python -m seyon.main generate --file employee.yaml
Adding a new database backend
- Create a new generator class in
src/database/implementingDatabaseAbstract - Implement
connect(),close(),generate_table(),generate_data(),get_all_data(),get_by_id(),insert(),update(),delete() - Register it in
src/database/factory.py - Add the dependency to
pyproject.tomlandrequirements.txt
Adding a new data type
- Add the type name to
Elements.SUPPORTED_DATA_TYPESinsrc/schema/constants.py - Add a
generate_valuebranch insrc/schema/field.py - If the type can be
unique, update uniqueness handling in all generators - For PostgreSQL, add the type to
TYPE_MAPinpostgress_generator.py
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file seyon-0.1.4.tar.gz.
File metadata
- Download URL: seyon-0.1.4.tar.gz
- Upload date:
- Size: 27.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a95aa2e52ac83ec1cc022ebd013f56260caee5243036b194e9f90807a45162d
|
|
| MD5 |
bce91e52752cfa964cf08f96143df216
|
|
| BLAKE2b-256 |
54ee4333d2e806443c22798c98659ed20319ed26ab47b19690eb7ce5a48ca0d2
|
File details
Details for the file seyon-0.1.4-py3-none-any.whl.
File metadata
- Download URL: seyon-0.1.4-py3-none-any.whl
- Upload date:
- Size: 28.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
296c80f2dc6e7bd3224c80cb9be81204da340b33e677caa0e4b5ec90ea676add
|
|
| MD5 |
2891738231b789784345fe277a5adafd
|
|
| BLAKE2b-256 |
288af41a080330ca27cb14f28930841337782c7b0c00ca3d255b3fe7250345f2
|