Skip to content

Commit e69a14c

Browse files
release: SchemaForge v1.0.0 — stable release
- Bumped version to 1.0.0 - Updated CLI format choices to include alembic (7 formats) - Comprehensive README rewrite with type mapping table, IR architecture, full CLI examples - Updated roadmap through v1.0.0 - 137/137 tests passing
1 parent 21efa28 commit e69a14c

4 files changed

Lines changed: 166 additions & 45 deletions

File tree

‎README.md‎

Lines changed: 162 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,99 @@
11
# SchemaForge
22

3-
| SchemaForge **Bidirectional ORM schema converter — convert between SQL DDL, Prisma, Drizzle, TypeORM, Django, SQLAlchemy, and Alembic migration scripts. 7 formats, 36 direction pairs.**
3+
> **Bidirectional ORM schema converter** — convert between SQL DDL, Prisma, Drizzle, TypeORM, Django, SQLAlchemy, and Alembic migration scripts. **7 formats, 42 direction pairs.**
44
55
[![PyPI](https://img.shields.io/pypi/v/schemaforge)](https://pypi.org/project/schemaforge/)
66
[![Python](https://img.shields.io/pypi/pyversions/schemaforge)](https://pypi.org/project/schemaforge/)
77
[![License](https://img.shields.io/pypi/l/schemaforge)](https://github.com/Coding-Dev-Tools/schemaforge/blob/main/LICENSE)
88
[![CI](https://github.com/Coding-Dev-Tools/schemaforge/actions/workflows/test.yml/badge.svg)](https://github.com/Coding-Dev-Tools/schemaforge/actions/workflows/test.yml)
9+
[![Tests](https://img.shields.io/badge/tests-137%20passing-brightgreen)](https://github.com/Coding-Dev-Tools/schemaforge)
910

10-
**Why SchemaForge?** Every major ORM migration is a one-way street. Prisma can introspect SQL but can't export back. Drizzle users manually rewrite schemas when switching ORMs. TypeORM developers are locked into decorator syntax. No tool does bidirectional, lossless conversion between 5+ ORM formats — until now.
11+
**Why SchemaForge?** Every major ORM migration is a one-way street. Prisma introspects SQL but can't export back. Drizzle users manually rewrite schemas when switching ORMs. TypeORM developers are locked into decorator syntax. SchemaForge is the first tool to do **bidirectional, lossless conversion** between 7 schema formats — with a shared internal representation that guarantees roundtrip fidelity.
1112

12-
SchemaForge fills this gap. Convert any schema to any format, verify equivalence with the diff command, and batch-process entire directories. Whether you're migrating from Prisma to Drizzle, sharing a schema with a Django backend, or generating SQL DDL from TypeORM entities, SchemaForge handles it with zero information loss.
13+
Convert any schema to any format, verify equivalence with the diff command, generate Alembic migrations, and batch-process entire directories. Whether you're migrating from Prisma to Drizzle, sharing a schema with a Django backend, or generating SQL DDL from TypeORM entities — SchemaForge handles it.
1314

1415
## Quick Start
1516

1617
```bash
18+
# Install
1719
pip install schemaforge
18-
```bash
20+
1921
# Convert Prisma → Drizzle
2022
schemaforge convert --from prisma --to drizzle --input schema.prisma
2123

24+
# Generate Alembic migration from SQL
25+
schemaforge convert --from sql --to alembic --input schema.sql --output migrations/initial.py
26+
2227
# Diff two schemas
23-
schemaforge diff schema.prisma schema.drizzle.ts
28+
schemaforge diff schema-v1.prisma schema-v2.prisma
2429

25-
# Batch convert all schemas in directory
30+
# Batch convert all schemas in a directory
2631
schemaforge convert --from sql --to prisma --dir ./schemas/
2732
```
2833

34+
## Installation
35+
36+
```bash
37+
# PyPI (recommended)
38+
pip install schemaforge
39+
40+
# Latest from source
41+
pip install git+https://github.com/Coding-Dev-Tools/schemaforge.git
42+
```
43+
44+
Requires Python 3.10+.
45+
2946
## Commands
3047

3148
### `schemaforge convert`
3249

33-
Convert a schema from one format to another.
50+
Convert a schema from one format to another. All 7 formats support conversion to and from every other format (42 direction pairs).
3451

3552
```bash
53+
# SQL DDL
54+
schemaforge convert --from sql --to prisma --input schema.sql
55+
schemaforge convert --from sql --to alembic --input schema.sql --output migrations/initial.py
56+
57+
# Prisma
3658
schemaforge convert --from prisma --to drizzle --input schema.prisma
37-
schemaforge convert --from sql --to prisma --input schema.sql --output schema.prisma
59+
schemaforge convert --from prisma --to django --input schema.prisma --output models.py
60+
61+
# Drizzle
62+
schemaforge convert --from drizzle --to sql --input schema.drizzle.ts
63+
schemaforge convert --from drizzle --to typeorm --input schema.ts
64+
65+
# TypeORM
3866
schemaforge convert --from typeorm --to django --input entities/
39-
schemaforge convert --from django --to drizzle --input models.py --output schema.drizzle.ts
67+
schemaforge convert --from typeorm --to prisma --input user.entity.ts
68+
69+
# Django
70+
schemaforge convert --from django --to drizzle --input models.py
71+
schemaforge convert --from django --to sqlalchemy --input models.py
72+
73+
# SQLAlchemy
4074
schemaforge convert --from sqlalchemy --to prisma --input models.py
41-
schemaforge convert --from sql --to sqlalchemy --input schema.sql
75+
schemaforge convert --from sqlalchemy --to sql --input declarative.py
76+
77+
# Alembic (generator-only — migration scripts)
4278
schemaforge convert --from sql --to alembic --input schema.sql --output migrations/initial.py
43-
```
79+
schemaforge convert --from prisma --to alembic --input schema.prisma --output migrations/
4480

45-
All direction pairs are fully supported — every format can convert to every other format.
81+
# Dir mode (batch convert all files)
82+
schemaforge convert --from sql --to prisma --dir ./schemas/
83+
schemaforge convert --from typeorm --to django --dir ./src/entities/
84+
```
4685

4786
### `schemaforge diff`
4887

49-
Show differences between two schema files in the same format.
88+
Compare two schema files in the same format and see line-level differences.
5089

5190
```bash
5291
schemaforge diff schema-v1.prisma schema-v2.prisma
5392
schemaforge diff schema.sql schema-updated.sql --format sql
93+
schemaforge diff fixtures/sample.sql fixtures/sample.prisma --format prisma
5494
```
5595

56-
Detects added, removed, and modified tables, columns, indexes, and constraints.
96+
Detects added, removed, and modified tables, columns, indexes, and constraints. Useful for CI/CD checks and code review.
5797

5898
## Supported Formats
5999

@@ -67,11 +107,56 @@ Detects added, removed, and modified tables, columns, indexes, and constraints.
67107
| SQLAlchemy models | ✓ | ✓ | ✓ |
68108
| Alembic migrations | — | ✓ | — |
69109

110+
**Alembic** is generator-only: you can create migration scripts from any format, but parsing existing migrations back to IR is not yet supported.
111+
112+
## How It Works
113+
114+
SchemaForge uses a **shared Internal Representation (IR)** — all formats convert to and from this common schema definition. This architecture guarantees:
115+
116+
- **Zero-loss roundtripping**: `sql → prisma → sql` produces the same schema you started with
117+
- **Bidirectional conversion**: every supported format can convert to every other format
118+
- **Extensibility**: adding a new format requires only a parser and a generator — no pairwise converters
119+
120+
```
121+
SQL DDL ──┐
122+
Prisma ───┤
123+
Drizzle ──┤
124+
TypeORM ──┼──▶ Shared IR ──▶ Any Format
125+
Django ───┤
126+
SQLAlchemy ──┤
127+
Alembic ───┘
128+
```
129+
130+
## Type Mapping
131+
132+
SchemaForge maps types intelligently between ORM systems. The core `ColumnType` enum represents all supported data types, and each format maps them to their native equivalents.
133+
134+
| ColumnType | SQL DDL | Prisma | Drizzle | TypeORM | Django | SQLAlchemy | Alembic |
135+
|------------|---------|--------|---------|---------|--------|------------|---------|
136+
| STRING | VARCHAR(n) / TEXT | String @db.VarChar(n) | varchar(n) | varchar | CharField(max_length=n) | String(n) | sa.String(n) |
137+
| INTEGER | INTEGER | Int | integer | integer | IntegerField | Integer | sa.Integer |
138+
| FLOAT | FLOAT | Float | real | float | FloatField | Float | sa.Float |
139+
| BOOLEAN | BOOLEAN | Boolean | boolean | boolean | BooleanField | Boolean | sa.Boolean |
140+
| DATETIME | TIMESTAMP | DateTime | timestamp | timestamp | DateTimeField | DateTime | sa.DateTime |
141+
| DATE | DATE | DateTime | date | date | DateField | Date | sa.Date |
142+
| TIME | TIME | DateTime | time | time | TimeField | Time | sa.Time |
143+
| TEXT | TEXT | String | text | text | TextField | Text | sa.Text |
144+
| BLOB | BLOB | Bytes | blob | blob | BinaryField | LargeBinary | sa.LargeBinary |
145+
| JSON | JSON | Json | json | json | JSONField | JSON | sa.JSON |
146+
| UUID | UUID | String | uuid | uuid | UUIDField | Uuid | sa.Uuid |
147+
| ENUM | ENUM('a','b') | (via enum type) | pgEnum | enum | CharField | Enum | sa.Enum |
148+
| DECIMAL | DECIMAL(p,s) | Decimal | numeric(p,s) | decimal(p,s) | DecimalField(max_digits=p) | Numeric(p,s) | sa.Numeric(p,s) |
149+
150+
**Function defaults** (`CURRENT_TIMESTAMP`, `NOW()`, `gen_random_uuid()`, etc.) are preserved across conversions using a `fn:` prefix convention. For example, `DEFAULT CURRENT_TIMESTAMP` in SQL becomes `@default(now())` in Prisma and `server_default=func.now()` in SQLAlchemy.
151+
70152
## Demo Fixtures
71153

72-
Try SchemaForge immediately with our example blog schema. The `fixtures/` directory contains an equivalent schema (users, posts, categories with foreign keys, enums, and various data types) in 6 supported formats:
154+
Try SchemaForge immediately with our example blog schema. The `fixtures/` directory contains an equivalent schema (users, posts, categories with enums and various data types) in 7 formats:
73155

74156
```bash
157+
# List all fixtures
158+
ls fixtures/
159+
75160
# Convert SQL → Prisma
76161
schemaforge convert --from sql --to prisma --input fixtures/sample.sql
77162

@@ -81,6 +166,9 @@ schemaforge convert --from prisma --to django --input fixtures/sample.prisma
81166
# Convert TypeORM → Drizzle
82167
schemaforge convert --from typeorm --to drizzle --input fixtures/sample.typeorm.ts
83168

169+
# Convert SQL → Alembic migration
170+
schemaforge convert --from sql --to alembic --input fixtures/sample.sql --output migrations/initial.py
171+
84172
# Batch convert all fixtures from SQL
85173
schemaforge convert --from sql --to prisma --dir fixtures/
86174

@@ -92,12 +180,42 @@ Each fixture demonstrates the same blog schema so you can compare ORM syntax sid
92180

93181
## Features
94182

95-
- **Bidirectional conversion** — every supported format can convert to and from every other format
96-
- **Zero-loss roundtripping** — `sql → prisma → sql` produces the same schema you started with
97-
- **Diff mode** — compare two schemas in the same format and see line-level differences
98-
- **Batch mode** — convert entire directories of schema files
99-
- **Type mapping** — intelligent type system mapping between ORMs (e.g., Prisma `String` ↔ Django `CharField` ↔ SQL `VARCHAR`)
100-
- **Relation preservation** — foreign keys, indexes, and unique constraints maintained across conversions
183+
- **Bidirectional conversion** — all 7 formats convert to and from every other format (42 direction pairs)
184+
- **Zero-loss roundtripping** — `sql → prisma → sql` reproduces the original schema exactly
185+
- **Alembic migration generation** — create database migration scripts from any schema format
186+
- **Diff mode** — compare two schemas in the same format with line-level differences
187+
- **Batch mode** — convert entire directories of schema files with one command
188+
- **Intelligent type mapping** — types map correctly across all 7 formats (String ↔ CharField ↔ VARCHAR)
189+
- **Function default preservation** — `CURRENT_TIMESTAMP`, `NOW()`, `gen_random_uuid()` survive roundtrips
190+
- **MySQL support** — ENGINE=InnoDB, AUTO_INCREMENT, DEFAULT CHARSET, COMMENT table options
191+
- **Inline ENUM** — `ENUM('small', 'medium', 'large')` column types parsed and roundtripped
192+
- **Relation preservation** — indexes, unique constraints maintained across all conversions
193+
- **Custom type handling** — dialect-specific types (JSONB, etc.) pass through via CUSTOM type
194+
195+
## Roadmap
196+
197+
| Version | Features |
198+
|---------|----------|
199+
| v0.1.0 | SQL DDL ↔ Prisma bidirectional conversion |
200+
| v0.2.0 | Drizzle schema support |
201+
| v0.3.0 | TypeORM entities support |
202+
| v0.4.0 | Django models support |
203+
| v0.5.0 | SQLAlchemy support, diff mode, batch mode, custom type mappings |
204+
| v0.6.0 | SQL parser edge cases (TEMPORARY TABLE, backtick quoting, fn: defaults) |
205+
| v0.7.0 | MySQL table options (ENGINE, CHARSET), inline ENUM('a','b','c') |
206+
| v0.8.0 | Alembic migration generation (7th format) |
207+
| v0.9.0 | Shared generator base module, refactored fn: default handling |
208+
| **v1.0.0** | **Stable release — comprehensive docs, CLI polish, 137 tests** |
209+
210+
### Planned
211+
212+
- [ ] Custom type mapping configuration files (YAML/JSON overrides)
213+
- [ ] JSON Schema import/export
214+
- [ ] GraphQL schema export
215+
- [ ] MCP server for AI-assisted schema operations
216+
- [ ] VS Code extension with live diff
217+
- [ ] CI/CD check: enforce schema consistency across branches
218+
- [ ] Additional ORM formats: Doobie/Quill (Scala), Entity Framework (C#)
101219

102220
## Pricing
103221

@@ -119,7 +237,8 @@ SchemaForge is one of eight tools in the Revenue Holdings suite. One license cov
119237
| Feature | Free | Individual | Suite | Team | Enterprise |
120238
|---------|:----:|:----------:|:-----:|:----:|:----------:|
121239
| CLI: convert, diff | ✓ | ✓ | ✓ | ✓ | ✓ |
122-
| All 5 format directions | — | ✓ | ✓ | ✓ | ✓ |
240+
| All 7 format directions | — | ✓ | ✓ | ✓ | ✓ |
241+
| Alembic migration generation | — | ✓ | ✓ | ✓ | ✓ |
123242
| Batch directory conversion | — | ✓ | ✓ | ✓ | ✓ |
124243
| Zero-loss roundtrip verification | — | ✓ | ✓ | ✓ | ✓ |
125244
| Custom type mappings | — | ✓ | ✓ | ✓ | ✓ |
@@ -129,30 +248,32 @@ SchemaForge is one of eight tools in the Revenue Holdings suite. One license cov
129248
| RBAC / SSO / SAML / OIDC | — | — | — | — | ✓ |
130249
| Priority support | Community | 24h | 24h | 8h | Dedicated |
131250

132-
---
251+
## Development
133252

134-
<p align="center">
135-
<sub>Part of <a href="https://coding-dev-tools.github.io/revenueholdings.dev/">Revenue Holdings</a> — CLI tools built by autonomous AI.</sub>
136-
</p>
253+
```bash
254+
# Clone and install in dev mode
255+
git clone https://github.com/Coding-Dev-Tools/schemaforge.git
256+
cd schemaforge
257+
pip install -e ".[dev]"
137258

138-
## Roadmap
259+
# Run tests
260+
pytest tests/ -v
139261

140-
| Version | Features |
141-
|---------|----------|
142-
| v0.1.0 | SQL DDL ↔ Prisma bidirectional conversion |
143-
| v0.2.0 | Drizzle support |
144-
| v0.3.0 | TypeORM support |
145-
| v0.4.0 | Django models support |
146-
| v0.5.0 | SQLAlchemy support, diff mode, batch mode, custom type mappings |
262+
# Run tests with coverage
263+
pytest tests/ --cov=schemaforge
264+
```
147265

148-
### Planned
266+
## Contributing
149267

150-
- [ ] Custom type mapping configuration files
151-
- [ ] JSON Schema import/export
152-
- [ ] GraphQL schema export
153-
- [ ] MCP server for AI-assisted schema operations
154-
- [ ] VS Code extension with live diff
155-
- [ ] CI/CD check: enforce schema consistency across branches
268+
PRs welcome! New format parsers/generators, bug fixes, and documentation improvements are all appreciated.
269+
270+
1. Fork the repo
271+
2. Create a feature branch (`git checkout -b feat/awesome-format`)
272+
3. Add your parser and generator in `src/schemaforge/parsers/` and `src/schemaforge/generators/`
273+
4. Register in `src/schemaforge/convert.py`
274+
5. Add tests in `tests/`
275+
6. Run the full test suite (`pytest tests/ -v`)
276+
7. Submit a PR
156277

157278
## License
158279

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "schemaforge"
7-
version = "0.1.0"
7+
version = "1.0.0"
88
description = "Bidirectional ORM schema converter — convert between SQL DDL, Prisma, Drizzle, TypeORM, and Django models with zero-loss roundtripping"
99
readme = "README.md"
1010
requires-python = ">=3.10"

‎src/schemaforge/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""SchemaForge package."""
22
from __future__ import annotations
33

4-
__version__ = "0.1.0"
4+
__version__ = "1.0.0"

‎src/schemaforge/cli.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ def main() -> None:
2222

2323
@main.command()
2424
@click.option("--from", "from_fmt", required=True,
25-
type=click.Choice(["sql", "prisma", "drizzle", "typeorm", "django", "sqlalchemy"]),
25+
type=click.Choice(["sql", "prisma", "drizzle", "typeorm", "django", "sqlalchemy", "alembic"]),
2626
help="Source format")
2727
@click.option("--to", "to_fmt", required=True,
28-
type=click.Choice(["sql", "prisma", "drizzle", "typeorm", "django", "sqlalchemy"]),
28+
type=click.Choice(["sql", "prisma", "drizzle", "typeorm", "django", "sqlalchemy", "alembic"]),
2929
help="Target format")
3030
@click.option("--input", "-i", "input_path", required=True,
3131
type=click.Path(exists=True, readable=True),

0 commit comments

Comments
 (0)