Updated Readme files
This commit is contained in:
54
README.md
54
README.md
@@ -16,19 +16,47 @@ RelSpec provides bidirectional conversion and comparison between various databas
|
||||
|
||||
## Features
|
||||
|
||||
### Input Formats
|
||||
- **XML** - Generic XML schema definitions
|
||||
- **JSON** - JSON-based schema specifications
|
||||
- **Clarion DCTX** - Clarion database dictionary format
|
||||
- **Database Inspection** - Direct database introspection
|
||||
- **GORM Models** - Read existing GORM Go structs
|
||||
- **Bun Models** - Read existing Bun Go structs
|
||||
### Readers (Input Formats)
|
||||
|
||||
### Output Formats
|
||||
- **GORM Models** - Generate GORM-compatible Go structs
|
||||
- **Bun Models** - Generate Bun-compatible Go structs
|
||||
- **JSON** - Standard JSON schema output
|
||||
- **YAML** - Human-readable YAML format
|
||||
RelSpec can read database schemas from multiple sources:
|
||||
|
||||
#### ORM Models
|
||||
- [GORM](pkg/readers/gorm/README.md) - Go GORM model definitions
|
||||
- [Bun](pkg/readers/bun/README.md) - Go Bun model definitions
|
||||
- [Drizzle](pkg/readers/drizzle/README.md) - TypeScript Drizzle ORM schemas
|
||||
- [Prisma](pkg/readers/prisma/README.md) - Prisma schema language
|
||||
- [TypeORM](pkg/readers/typeorm/README.md) - TypeScript TypeORM entities
|
||||
|
||||
#### Database Inspection
|
||||
- [PostgreSQL](pkg/readers/pgsql/README.md) - Direct PostgreSQL database introspection
|
||||
|
||||
#### Schema Formats
|
||||
- [DBML](pkg/readers/dbml/README.md) - Database Markup Language (dbdiagram.io)
|
||||
- [DCTX](pkg/readers/dctx/README.md) - Clarion database dictionary format
|
||||
- [DrawDB](pkg/readers/drawdb/README.md) - DrawDB JSON format
|
||||
- [JSON](pkg/readers/json/README.md) - RelSpec canonical JSON format
|
||||
- [YAML](pkg/readers/yaml/README.md) - RelSpec canonical YAML format
|
||||
|
||||
### Writers (Output Formats)
|
||||
|
||||
RelSpec can write database schemas to multiple formats:
|
||||
|
||||
#### ORM Models
|
||||
- [GORM](pkg/writers/gorm/README.md) - Generate GORM-compatible Go structs
|
||||
- [Bun](pkg/writers/bun/README.md) - Generate Bun-compatible Go structs
|
||||
- [Drizzle](pkg/writers/drizzle/README.md) - Generate Drizzle ORM TypeScript schemas
|
||||
- [Prisma](pkg/writers/prisma/README.md) - Generate Prisma schema files
|
||||
- [TypeORM](pkg/writers/typeorm/README.md) - Generate TypeORM TypeScript entities
|
||||
|
||||
#### Database DDL
|
||||
- [PostgreSQL](pkg/writers/pgsql/README.md) - PostgreSQL DDL (CREATE TABLE, etc.)
|
||||
|
||||
#### Schema Formats
|
||||
- [DBML](pkg/writers/dbml/README.md) - Database Markup Language
|
||||
- [DCTX](pkg/writers/dctx/README.md) - Clarion database dictionary format
|
||||
- [DrawDB](pkg/writers/drawdb/README.md) - DrawDB JSON format
|
||||
- [JSON](pkg/writers/json/README.md) - RelSpec canonical JSON format
|
||||
- [YAML](pkg/writers/yaml/README.md) - RelSpec canonical YAML format
|
||||
|
||||
|
||||
## Use of AI
|
||||
@@ -98,7 +126,7 @@ go test ./...
|
||||
|
||||
Apache License 2.0 - See [LICENSE](LICENSE) for details.
|
||||
|
||||
Copyright 2025 wdevs
|
||||
Copyright 2025 Warky Devs
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
106
pkg/readers/bun/README.md
Normal file
106
pkg/readers/bun/README.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Bun Reader
|
||||
|
||||
Reads Go source files containing Bun model definitions and extracts database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The Bun Reader parses Go source code files that define Bun models (structs with `bun` struct tags) and converts them into RelSpec's internal database model representation.
|
||||
|
||||
## Features
|
||||
|
||||
- Parses Bun struct tags to extract column definitions
|
||||
- Extracts table names from `bun:"table:tablename"` tags
|
||||
- Identifies primary keys, foreign keys, and indexes
|
||||
- Supports relationship detection
|
||||
- Handles both single files and directories
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/bun"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/models.go",
|
||||
}
|
||||
|
||||
reader := bun.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read Bun models and convert to JSON
|
||||
relspec --input bun --in-file models/ --output json --out-file schema.json
|
||||
|
||||
# Convert Bun models to GORM
|
||||
relspec --input bun --in-file models.go --output gorm --out-file gorm_models.go
|
||||
```
|
||||
|
||||
## Supported Bun Tags
|
||||
|
||||
The reader recognizes the following Bun struct tags:
|
||||
|
||||
- `table` - Table name
|
||||
- `column` - Column name
|
||||
- `type` - SQL data type
|
||||
- `pk` - Primary key
|
||||
- `notnull` - NOT NULL constraint
|
||||
- `autoincrement` - Auto-increment column
|
||||
- `default` - Default value
|
||||
- `unique` - Unique constraint
|
||||
- `rel` - Relationship definition
|
||||
|
||||
## Example Bun Model
|
||||
|
||||
```go
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
bun.BaseModel `bun:"table:users,alias:u"`
|
||||
|
||||
ID int64 `bun:"id,pk,autoincrement"`
|
||||
Username string `bun:"username,notnull,unique"`
|
||||
Email string `bun:"email,notnull"`
|
||||
CreatedAt time.Time `bun:"created_at,notnull,default:now()"`
|
||||
|
||||
Posts []*Post `bun:"rel:has-many,join:id=user_id"`
|
||||
}
|
||||
|
||||
type Post struct {
|
||||
bun.BaseModel `bun:"table:posts,alias:p"`
|
||||
|
||||
ID int64 `bun:"id,pk"`
|
||||
UserID int64 `bun:"user_id,notnull"`
|
||||
Title string `bun:"title,notnull"`
|
||||
Content string `bun:"content"`
|
||||
|
||||
User *User `bun:"rel:belongs-to,join:user_id=id"`
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Test files (ending in `_test.go`) are automatically excluded
|
||||
- The `bun.BaseModel` embedded struct is automatically recognized
|
||||
- Schema defaults to `public` if not specified
|
||||
101
pkg/readers/dbml/README.md
Normal file
101
pkg/readers/dbml/README.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# DBML Reader
|
||||
|
||||
Reads Database Markup Language (DBML) files and extracts database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The DBML Reader parses `.dbml` files that define database schemas using the DBML syntax (used by dbdiagram.io) and converts them into RelSpec's internal database model representation.
|
||||
|
||||
## Features
|
||||
|
||||
- Parses DBML syntax
|
||||
- Extracts tables, columns, and relationships
|
||||
- Supports DBML-specific features:
|
||||
- Table groups and notes
|
||||
- Enum definitions
|
||||
- Indexes
|
||||
- Foreign key relationships
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/dbml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/schema.dbml",
|
||||
}
|
||||
|
||||
reader := dbml.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read DBML file and convert to JSON
|
||||
relspec --input dbml --in-file schema.dbml --output json --out-file schema.json
|
||||
|
||||
# Convert DBML to GORM models
|
||||
relspec --input dbml --in-file database.dbml --output gorm --out-file models.go
|
||||
```
|
||||
|
||||
## Example DBML File
|
||||
|
||||
```dbml
|
||||
Table users {
|
||||
id bigserial [pk, increment]
|
||||
username varchar(50) [not null, unique]
|
||||
email varchar(100) [not null]
|
||||
created_at timestamp [not null, default: `now()`]
|
||||
|
||||
Note: 'Users table'
|
||||
}
|
||||
|
||||
Table posts {
|
||||
id bigserial [pk]
|
||||
user_id bigint [not null, ref: > users.id]
|
||||
title varchar(200) [not null]
|
||||
content text
|
||||
|
||||
indexes {
|
||||
user_id
|
||||
(user_id, created_at) [name: 'idx_user_posts']
|
||||
}
|
||||
}
|
||||
|
||||
Ref: posts.user_id > users.id [delete: cascade]
|
||||
```
|
||||
|
||||
## DBML Features Supported
|
||||
|
||||
- Table definitions with columns
|
||||
- Primary keys (`pk`)
|
||||
- Not null constraints (`not null`)
|
||||
- Unique constraints (`unique`)
|
||||
- Default values (`default`)
|
||||
- Inline references (`ref`)
|
||||
- Standalone `Ref` blocks
|
||||
- Indexes and composite indexes
|
||||
- Table notes and column notes
|
||||
- Enums
|
||||
|
||||
## Notes
|
||||
|
||||
- DBML is designed for database documentation and diagramming
|
||||
- Schema name defaults to `public`
|
||||
- Relationship cardinality is preserved
|
||||
96
pkg/readers/dctx/README.md
Normal file
96
pkg/readers/dctx/README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# DCTX Reader
|
||||
|
||||
Reads Clarion database dictionary (DCTX) files and extracts database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The DCTX Reader parses Clarion dictionary files (`.dctx`) that define database structures in the Clarion development system and converts them into RelSpec's internal database model representation.
|
||||
|
||||
## Features
|
||||
|
||||
- Parses Clarion DCTX XML format
|
||||
- Extracts file (table) and field (column) definitions
|
||||
- Supports Clarion data types
|
||||
- Handles keys (indexes) and relationships
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/dctx"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/database.dctx",
|
||||
}
|
||||
|
||||
reader := dctx.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read DCTX file and convert to JSON
|
||||
relspec --input dctx --in-file legacy.dctx --output json --out-file schema.json
|
||||
|
||||
# Convert DCTX to GORM models for migration
|
||||
relspec --input dctx --in-file app.dctx --output gorm --out-file models.go
|
||||
|
||||
# Export DCTX to PostgreSQL DDL
|
||||
relspec --input dctx --in-file database.dctx --output pgsql --out-file schema.sql
|
||||
```
|
||||
|
||||
## Example DCTX Structure
|
||||
|
||||
DCTX files are XML-based Clarion dictionary files that define:
|
||||
|
||||
- Files (equivalent to tables)
|
||||
- Fields (columns) with Clarion-specific types
|
||||
- Keys (indexes)
|
||||
- Relationships between files
|
||||
|
||||
Common Clarion data types:
|
||||
- `STRING` - Fixed-length string
|
||||
- `CSTRING` - C-style null-terminated string
|
||||
- `LONG` - 32-bit integer
|
||||
- `SHORT` - 16-bit integer
|
||||
- `DECIMAL` - Decimal number
|
||||
- `REAL` - Floating point
|
||||
- `DATE` - Date field
|
||||
- `TIME` - Time field
|
||||
|
||||
## Type Mapping
|
||||
|
||||
The reader automatically maps Clarion data types to standard SQL types:
|
||||
|
||||
| Clarion Type | SQL Type |
|
||||
|--------------|----------|
|
||||
| STRING | VARCHAR |
|
||||
| CSTRING | VARCHAR |
|
||||
| LONG | INTEGER |
|
||||
| SHORT | SMALLINT |
|
||||
| DECIMAL | NUMERIC |
|
||||
| REAL | REAL |
|
||||
| DATE | DATE |
|
||||
| TIME | TIME |
|
||||
|
||||
## Notes
|
||||
|
||||
- DCTX is specific to Clarion development platform
|
||||
- Useful for migrating legacy Clarion applications
|
||||
- Schema name defaults to `public`
|
||||
- Preserves field properties and constraints where possible
|
||||
96
pkg/readers/drawdb/README.md
Normal file
96
pkg/readers/drawdb/README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# DrawDB Reader
|
||||
|
||||
Reads DrawDB schema files and extracts database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The DrawDB Reader parses JSON files exported from DrawDB (a free online database design tool) and converts them into RelSpec's internal database model representation.
|
||||
|
||||
## Features
|
||||
|
||||
- Parses DrawDB JSON format
|
||||
- Extracts tables, fields, and relationships
|
||||
- Supports DrawDB-specific metadata
|
||||
- Preserves visual layout information
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/drawdb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/diagram.json",
|
||||
}
|
||||
|
||||
reader := drawdb.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read DrawDB export and convert to JSON schema
|
||||
relspec --input drawdb --in-file diagram.json --output json --out-file schema.json
|
||||
|
||||
# Convert DrawDB design to GORM models
|
||||
relspec --input drawdb --in-file design.json --output gorm --out-file models.go
|
||||
```
|
||||
|
||||
## Example DrawDB Export
|
||||
|
||||
DrawDB exports database designs as JSON files containing:
|
||||
|
||||
```json
|
||||
{
|
||||
"tables": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "users",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "BIGINT",
|
||||
"primary": true,
|
||||
"autoIncrement": true
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"type": "VARCHAR",
|
||||
"size": 50,
|
||||
"notNull": true,
|
||||
"unique": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"relationships": [
|
||||
{
|
||||
"source": "posts",
|
||||
"target": "users",
|
||||
"type": "many-to-one"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- DrawDB is a free online database designer at drawdb.vercel.app
|
||||
- Export format preserves visual design metadata
|
||||
- Useful for converting visual designs to code
|
||||
- Schema defaults to `public`
|
||||
90
pkg/readers/drizzle/README.md
Normal file
90
pkg/readers/drizzle/README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Drizzle Reader
|
||||
|
||||
Reads TypeScript/JavaScript files containing Drizzle ORM schema definitions and extracts database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The Drizzle Reader parses Drizzle ORM schema files (TypeScript/JavaScript) that define database tables using Drizzle's schema builder and converts them into RelSpec's internal database model representation.
|
||||
|
||||
## Features
|
||||
|
||||
- Parses Drizzle schema definitions
|
||||
- Extracts table, column, and relationship information
|
||||
- Supports various Drizzle column types
|
||||
- Handles constraints and indexes
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/drizzle"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/schema.ts",
|
||||
}
|
||||
|
||||
reader := drizzle.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read Drizzle schema and convert to JSON
|
||||
relspec --input drizzle --in-file schema.ts --output json --out-file schema.json
|
||||
|
||||
# Convert Drizzle to GORM models
|
||||
relspec --input drizzle --in-file schema/ --output gorm --out-file models.go
|
||||
```
|
||||
|
||||
## Example Drizzle Schema
|
||||
|
||||
```typescript
|
||||
import { pgTable, serial, varchar, text, timestamp, integer } from 'drizzle-orm/pg-core';
|
||||
import { relations } from 'drizzle-orm';
|
||||
|
||||
export const users = pgTable('users', {
|
||||
id: serial('id').primaryKey(),
|
||||
username: varchar('username', { length: 50 }).notNull().unique(),
|
||||
email: varchar('email', { length: 100 }).notNull(),
|
||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||
});
|
||||
|
||||
export const posts = pgTable('posts', {
|
||||
id: serial('id').primaryKey(),
|
||||
userId: integer('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
|
||||
title: varchar('title', { length: 200 }).notNull(),
|
||||
content: text('content'),
|
||||
});
|
||||
|
||||
export const usersRelations = relations(users, ({ many }) => ({
|
||||
posts: many(posts),
|
||||
}));
|
||||
|
||||
export const postsRelations = relations(posts, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [posts.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Supports both PostgreSQL and MySQL Drizzle schemas
|
||||
- Extracts relationship information from `relations` definitions
|
||||
- Schema defaults to `public` for PostgreSQL
|
||||
141
pkg/readers/gorm/README.md
Normal file
141
pkg/readers/gorm/README.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# GORM Reader
|
||||
|
||||
Reads Go source files containing GORM model definitions and extracts database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The GORM Reader parses Go source code files that define GORM models (structs with `gorm` struct tags) and converts them into RelSpec's internal database model representation. It supports reading from individual files or entire directories.
|
||||
|
||||
## Features
|
||||
|
||||
- Parses GORM struct tags to extract column definitions
|
||||
- Extracts table names from `TableName()` methods
|
||||
- Identifies primary keys, foreign keys, and indexes
|
||||
- Supports relationship detection (has-many, belongs-to)
|
||||
- Handles both single files and directories
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/gorm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Read from a single file
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/models.go",
|
||||
}
|
||||
|
||||
reader := gorm.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### Reading from Directory
|
||||
|
||||
```go
|
||||
// Read all .go files from a directory
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/models/",
|
||||
}
|
||||
|
||||
reader := gorm.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read GORM models and convert to JSON
|
||||
relspec --input gorm --in-file models/ --output json --out-file schema.json
|
||||
|
||||
# Convert GORM models to Bun
|
||||
relspec --input gorm --in-file models.go --output bun --out-file bun_models.go
|
||||
```
|
||||
|
||||
## Supported GORM Tags
|
||||
|
||||
The reader recognizes the following GORM struct tags:
|
||||
|
||||
- `column` - Column name
|
||||
- `type` - SQL data type (e.g., `varchar(255)`, `bigint`)
|
||||
- `primaryKey` or `primary_key` - Mark as primary key
|
||||
- `not null` - NOT NULL constraint
|
||||
- `autoIncrement` - Auto-increment column
|
||||
- `default` - Default value
|
||||
- `size` - Column size/length
|
||||
- `index` - Create index
|
||||
- `uniqueIndex` - Create unique index
|
||||
- `unique` - Unique constraint
|
||||
- `foreignKey` - Foreign key column
|
||||
- `references` - Referenced column
|
||||
- `constraint` - Constraint behavior (OnDelete, OnUpdate)
|
||||
|
||||
## Example GORM Model
|
||||
|
||||
```go
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ModelUser struct {
|
||||
gorm.Model
|
||||
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement"`
|
||||
Username string `gorm:"column:username;type:varchar(50);not null;uniqueIndex"`
|
||||
Email string `gorm:"column:email;type:varchar(100);not null"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:now()"`
|
||||
|
||||
// Relationships
|
||||
Posts []*ModelPost `gorm:"foreignKey:UserID;references:ID;constraint:OnDelete:CASCADE"`
|
||||
}
|
||||
|
||||
func (ModelUser) TableName() string {
|
||||
return "public.users"
|
||||
}
|
||||
|
||||
type ModelPost struct {
|
||||
ID int64 `gorm:"column:id;type:bigint;primaryKey"`
|
||||
UserID int64 `gorm:"column:user_id;type:bigint;not null"`
|
||||
Title string `gorm:"column:title;type:varchar(200);not null"`
|
||||
Content string `gorm:"column:content;type:text"`
|
||||
|
||||
// Belongs-to relationship
|
||||
User *ModelUser `gorm:"foreignKey:UserID;references:ID"`
|
||||
}
|
||||
|
||||
func (ModelPost) TableName() string {
|
||||
return "public.posts"
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Test files (ending in `_test.go`) are automatically excluded
|
||||
- The `gorm.Model` embedded struct is automatically recognized and skipped
|
||||
- Table names are derived from struct names if `TableName()` method is not present
|
||||
- Schema defaults to `public` if not specified in `TableName()`
|
||||
- Relationships are inferred from GORM relationship tags
|
||||
|
||||
## Limitations
|
||||
|
||||
- Complex relationship types (many-to-many with join tables) may need manual verification
|
||||
- Custom GORM types may not be fully supported
|
||||
- Some advanced GORM features may not be captured
|
||||
152
pkg/readers/json/README.md
Normal file
152
pkg/readers/json/README.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# JSON Reader
|
||||
|
||||
Reads database schema definitions from JSON files.
|
||||
|
||||
## Overview
|
||||
|
||||
The JSON Reader parses JSON files that define database schemas in RelSpec's canonical JSON format and converts them into RelSpec's internal database model representation.
|
||||
|
||||
## Features
|
||||
|
||||
- Reads RelSpec's standard JSON schema format
|
||||
- Supports complete schema representation including:
|
||||
- Databases and schemas
|
||||
- Tables, columns, and data types
|
||||
- Constraints (PK, FK, unique, check)
|
||||
- Indexes
|
||||
- Relationships
|
||||
- Views and sequences
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/json"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/schema.json",
|
||||
}
|
||||
|
||||
reader := json.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read JSON schema and convert to GORM models
|
||||
relspec --input json --in-file schema.json --output gorm --out-file models.go
|
||||
|
||||
# Convert JSON to PostgreSQL DDL
|
||||
relspec --input json --in-file database.json --output pgsql --out-file schema.sql
|
||||
|
||||
# Transform JSON to YAML
|
||||
relspec --input json --in-file schema.json --output yaml --out-file schema.yaml
|
||||
```
|
||||
|
||||
## Example JSON Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "myapp",
|
||||
"database_type": "postgresql",
|
||||
"schemas": [
|
||||
{
|
||||
"name": "public",
|
||||
"tables": [
|
||||
{
|
||||
"name": "users",
|
||||
"schema": "public",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "bigint",
|
||||
"not_null": true,
|
||||
"is_primary_key": true,
|
||||
"auto_increment": true,
|
||||
"sequence": 1
|
||||
},
|
||||
"username": {
|
||||
"name": "username",
|
||||
"type": "varchar",
|
||||
"length": 50,
|
||||
"not_null": true,
|
||||
"sequence": 2
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar",
|
||||
"length": 100,
|
||||
"not_null": true,
|
||||
"sequence": 3
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"pk_users": {
|
||||
"name": "pk_users",
|
||||
"type": "PRIMARY KEY",
|
||||
"columns": ["id"]
|
||||
},
|
||||
"uq_users_username": {
|
||||
"name": "uq_users_username",
|
||||
"type": "UNIQUE",
|
||||
"columns": ["username"]
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"idx_users_email": {
|
||||
"name": "idx_users_email",
|
||||
"columns": ["email"],
|
||||
"unique": false,
|
||||
"type": "btree"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Schema Structure
|
||||
|
||||
The JSON format follows RelSpec's internal model structure:
|
||||
|
||||
- `Database` - Top-level container
|
||||
- `name` - Database name
|
||||
- `database_type` - Database system (postgresql, mysql, etc.)
|
||||
- `schemas[]` - Array of schemas
|
||||
|
||||
- `Schema` - Schema/namespace
|
||||
- `name` - Schema name
|
||||
- `tables[]` - Array of tables
|
||||
- `views[]` - Array of views
|
||||
- `sequences[]` - Array of sequences
|
||||
|
||||
- `Table` - Table definition
|
||||
- `name` - Table name
|
||||
- `columns{}` - Map of columns
|
||||
- `constraints{}` - Map of constraints
|
||||
- `indexes{}` - Map of indexes
|
||||
- `relationships{}` - Map of relationships
|
||||
|
||||
## Notes
|
||||
|
||||
- This is RelSpec's native interchange format
|
||||
- Preserves complete schema information
|
||||
- Ideal for version control and schema documentation
|
||||
- Can be used as an intermediate format for transformations
|
||||
138
pkg/readers/pgsql/README.md
Normal file
138
pkg/readers/pgsql/README.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# PostgreSQL Reader
|
||||
|
||||
Reads schema information directly from a live PostgreSQL database.
|
||||
|
||||
## Overview
|
||||
|
||||
The PostgreSQL Reader connects to a PostgreSQL database and introspects its schema, extracting complete information about tables, columns, constraints, indexes, views, and sequences.
|
||||
|
||||
## Features
|
||||
|
||||
- Direct database introspection
|
||||
- Extracts complete schema information including:
|
||||
- Tables and columns
|
||||
- Primary keys, foreign keys, unique constraints, check constraints
|
||||
- Indexes
|
||||
- Views
|
||||
- Sequences
|
||||
- Supports multiple schemas
|
||||
- Captures constraint actions (ON DELETE, ON UPDATE)
|
||||
- Derives relationships from foreign keys
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/pgsql"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
ConnectionString: "postgres://user:password@localhost:5432/mydb?sslmode=disable",
|
||||
}
|
||||
|
||||
reader := pgsql.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Database: %s\n", db.Name)
|
||||
fmt.Printf("Schemas: %d\n", len(db.Schemas))
|
||||
for _, schema := range db.Schemas {
|
||||
fmt.Printf(" Schema: %s, Tables: %d\n", schema.Name, len(schema.Tables))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Inspect PostgreSQL database and export to JSON
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://user:password@localhost:5432/mydb" \
|
||||
--output json \
|
||||
--out-file schema.json
|
||||
|
||||
# Generate GORM models from PostgreSQL database
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://user:password@localhost:5432/mydb" \
|
||||
--output gorm \
|
||||
--out-file models.go
|
||||
|
||||
# Export database structure to YAML
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb?sslmode=disable" \
|
||||
--output yaml \
|
||||
--out-file schema.yaml
|
||||
```
|
||||
|
||||
## Connection String Format
|
||||
|
||||
The reader uses PostgreSQL connection strings in the format:
|
||||
|
||||
```
|
||||
postgres://username:password@hostname:port/database?parameters
|
||||
```
|
||||
|
||||
Examples:
|
||||
```
|
||||
postgres://localhost/mydb
|
||||
postgres://user:pass@localhost:5432/mydb
|
||||
postgres://user@localhost/mydb?sslmode=disable
|
||||
postgres://user:pass@db.example.com:5432/production?sslmode=require
|
||||
```
|
||||
|
||||
## Extracted Information
|
||||
|
||||
### Tables
|
||||
- Table name and schema
|
||||
- Comments/descriptions
|
||||
- All columns with data types, nullable, defaults
|
||||
- Sequences
|
||||
|
||||
### Columns
|
||||
- Column name, data type, length/precision
|
||||
- NULL/NOT NULL constraints
|
||||
- Default values
|
||||
- Auto-increment information
|
||||
- Primary key designation
|
||||
|
||||
### Constraints
|
||||
- Primary keys
|
||||
- Foreign keys (with ON DELETE/UPDATE actions)
|
||||
- Unique constraints
|
||||
- Check constraints
|
||||
|
||||
### Indexes
|
||||
- Index name and type (btree, hash, gist, gin, etc.)
|
||||
- Columns in index
|
||||
- Unique/non-unique
|
||||
- Partial indexes
|
||||
|
||||
### Views
|
||||
- View definitions
|
||||
- Column information
|
||||
|
||||
### Sequences
|
||||
- Sequence properties
|
||||
- Associated tables
|
||||
|
||||
## Notes
|
||||
|
||||
- Requires PostgreSQL connection permissions
|
||||
- Reads all non-system schemas (excludes pg_catalog, information_schema, pg_toast)
|
||||
- Captures PostgreSQL-specific data types
|
||||
- Automatically maps PostgreSQL types to canonical types
|
||||
- Preserves relationship metadata for downstream conversion
|
||||
|
||||
## Requirements
|
||||
|
||||
- Go library: `github.com/jackc/pgx/v5`
|
||||
- Database user must have SELECT permissions on system catalogs
|
||||
103
pkg/readers/prisma/README.md
Normal file
103
pkg/readers/prisma/README.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Prisma Reader
|
||||
|
||||
Reads Prisma schema files and extracts database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The Prisma Reader parses `.prisma` schema files that define database models using Prisma's schema language and converts them into RelSpec's internal database model representation.
|
||||
|
||||
## Features
|
||||
|
||||
- Parses Prisma schema syntax
|
||||
- Extracts models, fields, and relationships
|
||||
- Supports Prisma attributes and directives
|
||||
- Handles enums and composite types
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/prisma"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/schema.prisma",
|
||||
}
|
||||
|
||||
reader := prisma.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read Prisma schema and convert to JSON
|
||||
relspec --input prisma --in-file schema.prisma --output json --out-file schema.json
|
||||
|
||||
# Convert Prisma to GORM models
|
||||
relspec --input prisma --in-file schema.prisma --output gorm --out-file models.go
|
||||
```
|
||||
|
||||
## Example Prisma Schema
|
||||
|
||||
```prisma
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique @db.VarChar(50)
|
||||
email String @db.VarChar(100)
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
posts Post[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model Post {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int @map("user_id")
|
||||
title String @db.VarChar(200)
|
||||
content String @db.Text
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("posts")
|
||||
}
|
||||
```
|
||||
|
||||
## Supported Prisma Attributes
|
||||
|
||||
- `@id` - Primary key
|
||||
- `@unique` - Unique constraint
|
||||
- `@default` - Default value
|
||||
- `@map` - Column name mapping
|
||||
- `@@map` - Table name mapping
|
||||
- `@relation` - Relationship definition
|
||||
- `@db.*` - Database-specific type annotations
|
||||
|
||||
## Notes
|
||||
|
||||
- Extracts datasource provider information
|
||||
- Supports `@@map` for custom table names
|
||||
- Handles Prisma-specific types and converts them to standard SQL types
|
||||
122
pkg/readers/typeorm/README.md
Normal file
122
pkg/readers/typeorm/README.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# TypeORM Reader
|
||||
|
||||
Reads TypeScript files containing TypeORM entity definitions and extracts database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The TypeORM Reader parses TypeScript source files that define TypeORM entities (classes with TypeORM decorators) and converts them into RelSpec's internal database model representation.
|
||||
|
||||
## Features
|
||||
|
||||
- Parses TypeORM decorators and entity definitions
|
||||
- Extracts table, column, and relationship information
|
||||
- Supports various TypeORM column types and options
|
||||
- Handles constraints, indexes, and relationships
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/typeorm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/entities/",
|
||||
}
|
||||
|
||||
reader := typeorm.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read TypeORM entities and convert to JSON
|
||||
relspec --input typeorm --in-file entities/ --output json --out-file schema.json
|
||||
|
||||
# Convert TypeORM to GORM models
|
||||
relspec --input typeorm --in-file User.ts --output gorm --out-file models.go
|
||||
```
|
||||
|
||||
## Example TypeORM Entity
|
||||
|
||||
```typescript
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
OneToMany,
|
||||
} from 'typeorm';
|
||||
import { Post } from './Post';
|
||||
|
||||
@Entity('users')
|
||||
export class User {
|
||||
@PrimaryGeneratedColumn('increment')
|
||||
id: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, unique: true })
|
||||
username: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 100 })
|
||||
email: string;
|
||||
|
||||
@CreateDateColumn({ name: 'created_at' })
|
||||
createdAt: Date;
|
||||
|
||||
@OneToMany(() => Post, (post) => post.user)
|
||||
posts: Post[];
|
||||
}
|
||||
|
||||
@Entity('posts')
|
||||
export class Post {
|
||||
@PrimaryGeneratedColumn('increment')
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id' })
|
||||
userId: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 200 })
|
||||
title: string;
|
||||
|
||||
@Column({ type: 'text' })
|
||||
content: string;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.posts, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'user_id' })
|
||||
user: User;
|
||||
}
|
||||
```
|
||||
|
||||
## Supported TypeORM Decorators
|
||||
|
||||
- `@Entity()` - Entity/table definition
|
||||
- `@PrimaryGeneratedColumn()` - Auto-increment primary key
|
||||
- `@PrimaryColumn()` - Primary key
|
||||
- `@Column()` - Column definition
|
||||
- `@CreateDateColumn()` - Auto-set creation timestamp
|
||||
- `@UpdateDateColumn()` - Auto-update timestamp
|
||||
- `@OneToMany()` - One-to-many relationship
|
||||
- `@ManyToOne()` - Many-to-one relationship
|
||||
- `@JoinColumn()` - Foreign key column
|
||||
- `@Index()` - Index definition
|
||||
- `@Unique()` - Unique constraint
|
||||
|
||||
## Notes
|
||||
|
||||
- Schema name can be specified in `@Entity()` decorator
|
||||
- Supports both JavaScript and TypeScript entity files
|
||||
- Relationship metadata is extracted from decorators
|
||||
159
pkg/readers/yaml/README.md
Normal file
159
pkg/readers/yaml/README.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# YAML Reader
|
||||
|
||||
Reads database schema definitions from YAML files.
|
||||
|
||||
## Overview
|
||||
|
||||
The YAML Reader parses YAML files that define database schemas in RelSpec's canonical YAML format and converts them into RelSpec's internal database model representation.
|
||||
|
||||
## Features
|
||||
|
||||
- Reads RelSpec's standard YAML schema format
|
||||
- Human-readable alternative to JSON format
|
||||
- Supports complete schema representation including:
|
||||
- Databases and schemas
|
||||
- Tables, columns, and data types
|
||||
- Constraints (PK, FK, unique, check)
|
||||
- Indexes
|
||||
- Relationships
|
||||
- Views and sequences
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/readers/yaml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &readers.ReaderOptions{
|
||||
FilePath: "/path/to/schema.yaml",
|
||||
}
|
||||
|
||||
reader := yaml.NewReader(options)
|
||||
db, err := reader.ReadDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d schemas\n", len(db.Schemas))
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Example
|
||||
|
||||
```bash
|
||||
# Read YAML schema and convert to GORM models
|
||||
relspec --input yaml --in-file schema.yaml --output gorm --out-file models.go
|
||||
|
||||
# Convert YAML to PostgreSQL DDL
|
||||
relspec --input yaml --in-file database.yaml --output pgsql --out-file schema.sql
|
||||
|
||||
# Transform YAML to JSON
|
||||
relspec --input yaml --in-file schema.yaml --output json --out-file schema.json
|
||||
```
|
||||
|
||||
## Example YAML Schema
|
||||
|
||||
```yaml
|
||||
name: myapp
|
||||
database_type: postgresql
|
||||
schemas:
|
||||
- name: public
|
||||
tables:
|
||||
- name: users
|
||||
schema: public
|
||||
columns:
|
||||
id:
|
||||
name: id
|
||||
type: bigint
|
||||
not_null: true
|
||||
is_primary_key: true
|
||||
auto_increment: true
|
||||
sequence: 1
|
||||
username:
|
||||
name: username
|
||||
type: varchar
|
||||
length: 50
|
||||
not_null: true
|
||||
sequence: 2
|
||||
email:
|
||||
name: email
|
||||
type: varchar
|
||||
length: 100
|
||||
not_null: true
|
||||
sequence: 3
|
||||
constraints:
|
||||
pk_users:
|
||||
name: pk_users
|
||||
type: PRIMARY KEY
|
||||
columns:
|
||||
- id
|
||||
uq_users_username:
|
||||
name: uq_users_username
|
||||
type: UNIQUE
|
||||
columns:
|
||||
- username
|
||||
indexes:
|
||||
idx_users_email:
|
||||
name: idx_users_email
|
||||
columns:
|
||||
- email
|
||||
unique: false
|
||||
type: btree
|
||||
- name: posts
|
||||
schema: public
|
||||
columns:
|
||||
id:
|
||||
name: id
|
||||
type: bigint
|
||||
not_null: true
|
||||
is_primary_key: true
|
||||
sequence: 1
|
||||
user_id:
|
||||
name: user_id
|
||||
type: bigint
|
||||
not_null: true
|
||||
sequence: 2
|
||||
title:
|
||||
name: title
|
||||
type: varchar
|
||||
length: 200
|
||||
not_null: true
|
||||
sequence: 3
|
||||
constraints:
|
||||
fk_posts_user_id:
|
||||
name: fk_posts_user_id
|
||||
type: FOREIGN KEY
|
||||
columns:
|
||||
- user_id
|
||||
referenced_table: users
|
||||
referenced_schema: public
|
||||
referenced_columns:
|
||||
- id
|
||||
on_delete: CASCADE
|
||||
on_update: NO ACTION
|
||||
```
|
||||
|
||||
## Schema Structure
|
||||
|
||||
The YAML format mirrors RelSpec's internal model structure with human-readable syntax:
|
||||
|
||||
- Database level: `name`, `database_type`, `schemas`
|
||||
- Schema level: `name`, `tables`, `views`, `sequences`
|
||||
- Table level: `name`, `schema`, `columns`, `constraints`, `indexes`, `relationships`
|
||||
- Column level: `name`, `type`, `length`, `not_null`, `default`, etc.
|
||||
|
||||
## Notes
|
||||
|
||||
- YAML format is more human-readable than JSON
|
||||
- Ideal for manual editing and version control
|
||||
- Comments are supported in YAML
|
||||
- Preserves complete schema information
|
||||
- Can be used for configuration and documentation
|
||||
129
pkg/writers/bun/README.md
Normal file
129
pkg/writers/bun/README.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Bun Writer
|
||||
|
||||
Generates Go source files with Bun model definitions from database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The Bun Writer converts RelSpec's internal database model representation into Go source code with Bun struct definitions, complete with proper tags, relationships, and table configuration.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates Bun-compatible Go structs
|
||||
- Creates proper `bun` struct tags
|
||||
- Adds relationship fields
|
||||
- Supports both single-file and multi-file output
|
||||
- Maps SQL types to Go types
|
||||
- Handles nullable fields with sql.Null* types
|
||||
- Generates table aliases
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/bun"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "models.go",
|
||||
PackageName: "models",
|
||||
}
|
||||
|
||||
writer := bun.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate Bun models from PostgreSQL database
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output bun \
|
||||
--out-file models.go \
|
||||
--package models
|
||||
|
||||
# Convert GORM models to Bun
|
||||
relspec --input gorm --in-file gorm_models.go --output bun --out-file bun_models.go
|
||||
|
||||
# Multi-file output
|
||||
relspec --input json --in-file schema.json --output bun --out-file models/
|
||||
```
|
||||
|
||||
## Generated Code Example
|
||||
|
||||
```go
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
"database/sql"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
bun.BaseModel `bun:"table:users,alias:u"`
|
||||
|
||||
ID int64 `bun:"id,pk,autoincrement" json:"id"`
|
||||
Username string `bun:"username,notnull,unique" json:"username"`
|
||||
Email string `bun:"email,notnull" json:"email"`
|
||||
Bio sql.NullString `bun:"bio" json:"bio,omitempty"`
|
||||
CreatedAt time.Time `bun:"created_at,notnull,default:now()" json:"created_at"`
|
||||
|
||||
// Relationships
|
||||
Posts []*Post `bun:"rel:has-many,join:id=user_id" json:"posts,omitempty"`
|
||||
}
|
||||
|
||||
type Post struct {
|
||||
bun.BaseModel `bun:"table:posts,alias:p"`
|
||||
|
||||
ID int64 `bun:"id,pk" json:"id"`
|
||||
UserID int64 `bun:"user_id,notnull" json:"user_id"`
|
||||
Title string `bun:"title,notnull" json:"title"`
|
||||
Content sql.NullString `bun:"content" json:"content,omitempty"`
|
||||
|
||||
// Belongs to
|
||||
User *User `bun:"rel:belongs-to,join:user_id=id" json:"user,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
## Supported Bun Tags
|
||||
|
||||
- `table` - Table name and alias
|
||||
- `column` - Column name (auto-derived if not specified)
|
||||
- `pk` - Primary key
|
||||
- `autoincrement` - Auto-increment
|
||||
- `notnull` - NOT NULL constraint
|
||||
- `unique` - Unique constraint
|
||||
- `default` - Default value
|
||||
- `rel` - Relationship definition
|
||||
- `type` - Explicit SQL type
|
||||
|
||||
## Type Mapping
|
||||
|
||||
| SQL Type | Go Type | Nullable Type |
|
||||
|----------|---------|---------------|
|
||||
| bigint | int64 | sql.NullInt64 |
|
||||
| integer | int | sql.NullInt32 |
|
||||
| varchar, text | string | sql.NullString |
|
||||
| boolean | bool | sql.NullBool |
|
||||
| timestamp | time.Time | sql.NullTime |
|
||||
| numeric | float64 | sql.NullFloat64 |
|
||||
|
||||
## Notes
|
||||
|
||||
- Model names are derived from table names (singularized, PascalCase)
|
||||
- Table aliases are auto-generated from table names
|
||||
- Multi-file mode: one file per table named `sql_{schema}_{table}.go`
|
||||
- Generated code is auto-formatted
|
||||
- JSON tags are automatically added
|
||||
161
pkg/writers/dbml/README.md
Normal file
161
pkg/writers/dbml/README.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# DBML Writer
|
||||
|
||||
Generates Database Markup Language (DBML) files from database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The DBML Writer converts RelSpec's internal database model representation into DBML syntax, suitable for use with dbdiagram.io and other DBML-compatible tools.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates DBML syntax
|
||||
- Creates table definitions with columns
|
||||
- Defines relationships
|
||||
- Includes indexes
|
||||
- Adds notes and documentation
|
||||
- Supports enums
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/dbml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "schema.dbml",
|
||||
}
|
||||
|
||||
writer := dbml.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate DBML from PostgreSQL database
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output dbml \
|
||||
--out-file schema.dbml
|
||||
|
||||
# Convert GORM models to DBML
|
||||
relspec --input gorm --in-file models.go --output dbml --out-file database.dbml
|
||||
|
||||
# Convert JSON to DBML for visualization
|
||||
relspec --input json --in-file schema.json --output dbml --out-file diagram.dbml
|
||||
```
|
||||
|
||||
## Generated DBML Example
|
||||
|
||||
```dbml
|
||||
Project MyDatabase {
|
||||
database_type: 'PostgreSQL'
|
||||
}
|
||||
|
||||
Table users {
|
||||
id bigserial [pk, increment]
|
||||
username varchar(50) [not null, unique]
|
||||
email varchar(100) [not null]
|
||||
bio text [null]
|
||||
created_at timestamp [not null, default: `now()`]
|
||||
|
||||
Note: 'Users table'
|
||||
|
||||
indexes {
|
||||
email [name: 'idx_users_email']
|
||||
}
|
||||
}
|
||||
|
||||
Table posts {
|
||||
id bigserial [pk, increment]
|
||||
user_id bigint [not null]
|
||||
title varchar(200) [not null]
|
||||
content text [null]
|
||||
created_at timestamp [default: `now()`]
|
||||
|
||||
indexes {
|
||||
user_id [name: 'idx_posts_user_id']
|
||||
(user_id, created_at) [name: 'idx_posts_user_created']
|
||||
}
|
||||
}
|
||||
|
||||
Ref: posts.user_id > users.id [delete: cascade, update: no action]
|
||||
```
|
||||
|
||||
## DBML Features
|
||||
|
||||
### Table Definitions
|
||||
```dbml
|
||||
Table table_name {
|
||||
column_name type [attributes]
|
||||
}
|
||||
```
|
||||
|
||||
### Column Attributes
|
||||
- `pk` - Primary key
|
||||
- `increment` - Auto-increment
|
||||
- `not null` - NOT NULL constraint
|
||||
- `null` - Nullable (explicit)
|
||||
- `unique` - Unique constraint
|
||||
- `default: value` - Default value
|
||||
- `note: 'text'` - Column note
|
||||
|
||||
### Relationships
|
||||
```dbml
|
||||
Ref: table1.column > table2.column
|
||||
Ref: table1.column < table2.column
|
||||
Ref: table1.column - table2.column
|
||||
```
|
||||
|
||||
Relationship types:
|
||||
- `>` - Many-to-one
|
||||
- `<` - One-to-many
|
||||
- `-` - One-to-one
|
||||
|
||||
Relationship actions:
|
||||
```dbml
|
||||
Ref: posts.user_id > users.id [delete: cascade, update: restrict]
|
||||
```
|
||||
|
||||
### Indexes
|
||||
```dbml
|
||||
indexes {
|
||||
column_name
|
||||
(column1, column2) [name: 'idx_name', unique]
|
||||
}
|
||||
```
|
||||
|
||||
## Type Mapping
|
||||
|
||||
| SQL Type | DBML Type |
|
||||
|----------|-----------|
|
||||
| bigint | bigint |
|
||||
| integer | int |
|
||||
| varchar(n) | varchar(n) |
|
||||
| text | text |
|
||||
| boolean | boolean |
|
||||
| timestamp | timestamp |
|
||||
| date | date |
|
||||
| json | json |
|
||||
| uuid | uuid |
|
||||
|
||||
## Notes
|
||||
|
||||
- DBML is designed for database visualization
|
||||
- Can be imported into dbdiagram.io
|
||||
- Human-readable format
|
||||
- Schema names can be included in table names
|
||||
- Comments and notes are preserved
|
||||
- Ideal for documentation and sharing designs
|
||||
111
pkg/writers/dctx/README.md
Normal file
111
pkg/writers/dctx/README.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# DCTX Writer
|
||||
|
||||
Generates Clarion database dictionary (DCTX) files from database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The DCTX Writer converts RelSpec's internal database model representation into Clarion dictionary XML format, used by the Clarion development platform.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates DCTX XML format
|
||||
- Creates file (table) definitions
|
||||
- Defines fields (columns) with Clarion types
|
||||
- Includes keys (indexes)
|
||||
- Handles relationships
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/dctx"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "database.dctx",
|
||||
}
|
||||
|
||||
writer := dctx.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate DCTX from PostgreSQL database (for Clarion migration)
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output dctx \
|
||||
--out-file app.dctx
|
||||
|
||||
# Convert GORM models to DCTX
|
||||
relspec --input gorm --in-file models.go --output dctx --out-file legacy.dctx
|
||||
|
||||
# Convert JSON schema to DCTX
|
||||
relspec --input json --in-file schema.json --output dctx --out-file database.dctx
|
||||
```
|
||||
|
||||
## Type Mapping
|
||||
|
||||
Converts standard SQL types to Clarion types:
|
||||
|
||||
| SQL Type | Clarion Type | Notes |
|
||||
|----------|--------------|-------|
|
||||
| VARCHAR(n) | STRING(n) | Fixed-length string |
|
||||
| TEXT | STRING | Variable length |
|
||||
| INTEGER | LONG | 32-bit integer |
|
||||
| BIGINT | DECIMAL(20,0) | Large integer |
|
||||
| SMALLINT | SHORT | 16-bit integer |
|
||||
| NUMERIC(p,s) | DECIMAL(p,s) | Decimal number |
|
||||
| REAL, FLOAT | REAL | Floating point |
|
||||
| BOOLEAN | BYTE | 0/1 value |
|
||||
| DATE | DATE | Date field |
|
||||
| TIME | TIME | Time field |
|
||||
| TIMESTAMP | LONG | Unix timestamp |
|
||||
|
||||
## DCTX Structure
|
||||
|
||||
DCTX files are XML-based with this structure:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0"?>
|
||||
<dictionary>
|
||||
<file name="USERS" driver="TOPSPEED">
|
||||
<record>
|
||||
<field name="ID" type="LONG" />
|
||||
<field name="USERNAME" type="STRING" bytes="50" />
|
||||
<field name="EMAIL" type="STRING" bytes="100" />
|
||||
</record>
|
||||
<key name="KEY_PRIMARY" primary="true">
|
||||
<field name="ID" />
|
||||
</key>
|
||||
</file>
|
||||
</dictionary>
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- File definitions (equivalent to tables)
|
||||
- Field definitions with Clarion-specific types
|
||||
- Key definitions (primary and foreign)
|
||||
- Relationships between files
|
||||
- Driver specifications (TOPSPEED, SQL, etc.)
|
||||
|
||||
## Notes
|
||||
|
||||
- DCTX is specific to Clarion development
|
||||
- Useful for legacy system integration
|
||||
- Field names are typically uppercase in Clarion
|
||||
- Supports Clarion-specific attributes
|
||||
- Can be imported into Clarion IDE
|
||||
182
pkg/writers/drawdb/README.md
Normal file
182
pkg/writers/drawdb/README.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# DrawDB Writer
|
||||
|
||||
Generates DrawDB-compatible JSON files from database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The DrawDB Writer converts RelSpec's internal database model representation into JSON format compatible with DrawDB, a free online database design tool.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates DrawDB JSON format
|
||||
- Creates table and field definitions
|
||||
- Defines relationships
|
||||
- Includes visual layout information
|
||||
- Preserves constraints and indexes
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/drawdb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "diagram.json",
|
||||
}
|
||||
|
||||
writer := drawdb.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate DrawDB diagram from PostgreSQL database
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output drawdb \
|
||||
--out-file diagram.json
|
||||
|
||||
# Convert GORM models to DrawDB for visualization
|
||||
relspec --input gorm --in-file models.go --output drawdb --out-file design.json
|
||||
|
||||
# Convert JSON schema to DrawDB
|
||||
relspec --input json --in-file schema.json --output drawdb --out-file diagram.json
|
||||
```
|
||||
|
||||
## Generated JSON Example
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0",
|
||||
"database": "PostgreSQL",
|
||||
"tables": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "users",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"fields": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "id",
|
||||
"type": "BIGINT",
|
||||
"primary": true,
|
||||
"autoIncrement": true,
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "username",
|
||||
"type": "VARCHAR",
|
||||
"size": 50,
|
||||
"notNull": true,
|
||||
"unique": true
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"name": "email",
|
||||
"type": "VARCHAR",
|
||||
"size": 100,
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
{
|
||||
"name": "idx_users_email",
|
||||
"fields": ["email"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "posts",
|
||||
"x": 400,
|
||||
"y": 100,
|
||||
"fields": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "id",
|
||||
"type": "BIGINT",
|
||||
"primary": true
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "user_id",
|
||||
"type": "BIGINT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"name": "title",
|
||||
"type": "VARCHAR",
|
||||
"size": 200,
|
||||
"notNull": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"relationships": [
|
||||
{
|
||||
"id": "1",
|
||||
"source": "2",
|
||||
"target": "1",
|
||||
"sourceField": "user_id",
|
||||
"targetField": "id",
|
||||
"type": "many-to-one",
|
||||
"onDelete": "CASCADE"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## DrawDB Features
|
||||
|
||||
### Table Properties
|
||||
- `id` - Unique table identifier
|
||||
- `name` - Table name
|
||||
- `x`, `y` - Position in diagram
|
||||
- `fields` - Array of field definitions
|
||||
- `indexes` - Array of index definitions
|
||||
|
||||
### Field Properties
|
||||
- `id` - Unique field identifier
|
||||
- `name` - Field name
|
||||
- `type` - Data type (BIGINT, VARCHAR, etc.)
|
||||
- `size` - Length for string types
|
||||
- `primary` - Primary key flag
|
||||
- `notNull` - NOT NULL constraint
|
||||
- `unique` - Unique constraint
|
||||
- `autoIncrement` - Auto-increment flag
|
||||
- `default` - Default value
|
||||
|
||||
### Relationship Properties
|
||||
- `id` - Unique relationship identifier
|
||||
- `source` - Source table ID
|
||||
- `target` - Target table ID
|
||||
- `sourceField` - Foreign key field
|
||||
- `targetField` - Referenced field
|
||||
- `type` - Relationship type (one-to-one, one-to-many, many-to-one)
|
||||
- `onDelete` - Delete action
|
||||
- `onUpdate` - Update action
|
||||
|
||||
## Notes
|
||||
|
||||
- DrawDB is available at drawdb.vercel.app
|
||||
- Generated files can be imported for visual editing
|
||||
- Visual positions (x, y) are auto-generated
|
||||
- Ideal for creating ERD diagrams
|
||||
- Supports modern database features
|
||||
- Free and open-source tool
|
||||
120
pkg/writers/drizzle/README.md
Normal file
120
pkg/writers/drizzle/README.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# Drizzle Writer
|
||||
|
||||
Generates TypeScript/JavaScript files with Drizzle ORM schema definitions from database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The Drizzle Writer converts RelSpec's internal database model representation into TypeScript source code with Drizzle ORM schema definitions, including tables, columns, relationships, and constraints.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates Drizzle-compatible TypeScript schema
|
||||
- Supports PostgreSQL and MySQL schemas
|
||||
- Creates table definitions with proper column types
|
||||
- Generates relationship definitions
|
||||
- Handles constraints and indexes
|
||||
- Outputs formatted TypeScript code
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/drizzle"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "schema.ts",
|
||||
Metadata: map[string]interface{}{
|
||||
"database_type": "postgresql", // or "mysql"
|
||||
},
|
||||
}
|
||||
|
||||
writer := drizzle.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate Drizzle schema from PostgreSQL database
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output drizzle \
|
||||
--out-file schema.ts
|
||||
|
||||
# Convert GORM models to Drizzle
|
||||
relspec --input gorm --in-file models.go --output drizzle --out-file schema.ts
|
||||
|
||||
# Convert JSON schema to Drizzle
|
||||
relspec --input json --in-file schema.json --output drizzle --out-file db/schema.ts
|
||||
```
|
||||
|
||||
## Generated Code Example
|
||||
|
||||
```typescript
|
||||
import { pgTable, serial, varchar, text, timestamp, integer } from 'drizzle-orm/pg-core';
|
||||
import { relations } from 'drizzle-orm';
|
||||
|
||||
export const users = pgTable('users', {
|
||||
id: serial('id').primaryKey(),
|
||||
username: varchar('username', { length: 50 }).notNull().unique(),
|
||||
email: varchar('email', { length: 100 }).notNull(),
|
||||
bio: text('bio'),
|
||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||
});
|
||||
|
||||
export const posts = pgTable('posts', {
|
||||
id: serial('id').primaryKey(),
|
||||
userId: integer('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
|
||||
title: varchar('title', { length: 200 }).notNull(),
|
||||
content: text('content'),
|
||||
});
|
||||
|
||||
export const usersRelations = relations(users, ({ many }) => ({
|
||||
posts: many(posts),
|
||||
}));
|
||||
|
||||
export const postsRelations = relations(posts, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [posts.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
```
|
||||
|
||||
## Supported Column Types
|
||||
|
||||
### PostgreSQL
|
||||
- `serial`, `bigserial` - Auto-increment integers
|
||||
- `integer`, `bigint`, `smallint` - Integer types
|
||||
- `varchar`, `text` - String types
|
||||
- `boolean` - Boolean
|
||||
- `timestamp`, `date`, `time` - Date/time types
|
||||
- `json`, `jsonb` - JSON types
|
||||
- `uuid` - UUID type
|
||||
|
||||
### MySQL
|
||||
- `int`, `bigint`, `smallint` - Integer types
|
||||
- `varchar`, `text` - String types
|
||||
- `boolean` - Boolean
|
||||
- `datetime`, `timestamp` - Date/time types
|
||||
- `json` - JSON type
|
||||
|
||||
## Notes
|
||||
|
||||
- Table names and column names are preserved as-is
|
||||
- Relationships are generated as separate relation definitions
|
||||
- Constraint actions (CASCADE, etc.) are included in references
|
||||
- Schema names other than 'public' are supported
|
||||
- Output is formatted TypeScript code
|
||||
176
pkg/writers/gorm/README.md
Normal file
176
pkg/writers/gorm/README.md
Normal file
@@ -0,0 +1,176 @@
|
||||
# GORM Writer
|
||||
|
||||
Generates Go source files with GORM model definitions from database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The GORM Writer converts RelSpec's internal database model representation into Go source code with GORM struct definitions, complete with proper tags, relationships, and methods.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates GORM-compatible Go structs
|
||||
- Creates proper `gorm` struct tags
|
||||
- Generates `TableName()` methods
|
||||
- Adds relationship fields (belongs-to, has-many)
|
||||
- Supports both single-file and multi-file output
|
||||
- Auto-generates helper methods (optional)
|
||||
- Maps SQL types to Go types
|
||||
- Handles nullable fields with custom sql_types
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/gorm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Assume db is a *models.Database from a reader
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "models.go",
|
||||
PackageName: "models",
|
||||
}
|
||||
|
||||
writer := gorm.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate GORM models from PostgreSQL database (single file)
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output gorm \
|
||||
--out-file models.go \
|
||||
--package models
|
||||
|
||||
# Generate GORM models with multi-file output (one file per table)
|
||||
relspec --input json \
|
||||
--in-file schema.json \
|
||||
--output gorm \
|
||||
--out-file models/ \
|
||||
--package models
|
||||
|
||||
# Convert DBML to GORM models
|
||||
relspec --input dbml --in-file schema.dbml --output gorm --out-file models.go
|
||||
```
|
||||
|
||||
## Output Modes
|
||||
|
||||
### Single File Mode
|
||||
|
||||
Generates all models in one file:
|
||||
|
||||
```bash
|
||||
relspec --input pgsql --conn "..." --output gorm --out-file models.go
|
||||
```
|
||||
|
||||
### Multi-File Mode
|
||||
|
||||
Generates one file per table (auto-detected when output is a directory):
|
||||
|
||||
```bash
|
||||
relspec --input pgsql --conn "..." --output gorm --out-file models/
|
||||
```
|
||||
|
||||
Files are named: `sql_{schema}_{table}.go`
|
||||
|
||||
## Generated Code Example
|
||||
|
||||
```go
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
sql_types "git.warky.dev/wdevs/sql_types"
|
||||
)
|
||||
|
||||
type ModelUser struct {
|
||||
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement" json:"id"`
|
||||
Username string `gorm:"column:username;type:varchar(50);not null;uniqueIndex" json:"username"`
|
||||
Email string `gorm:"column:email;type:varchar(100);not null" json:"email"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:now()" json:"created_at"`
|
||||
|
||||
// Relationships
|
||||
Pos []*ModelPost `gorm:"foreignKey:UserID;references:ID;constraint:OnDelete:CASCADE" json:"pos,omitempty"`
|
||||
}
|
||||
|
||||
func (ModelUser) TableName() string {
|
||||
return "public.users"
|
||||
}
|
||||
|
||||
type ModelPost struct {
|
||||
ID int64 `gorm:"column:id;type:bigint;primaryKey" json:"id"`
|
||||
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
|
||||
Title string `gorm:"column:title;type:varchar(200);not null" json:"title"`
|
||||
Content sql_types.SqlString `gorm:"column:content;type:text" json:"content,omitempty"`
|
||||
|
||||
// Belongs to
|
||||
Use *ModelUser `gorm:"foreignKey:UserID;references:ID" json:"use,omitempty"`
|
||||
}
|
||||
|
||||
func (ModelPost) TableName() string {
|
||||
return "public.posts"
|
||||
}
|
||||
```
|
||||
|
||||
## Writer Options
|
||||
|
||||
### Metadata Options
|
||||
|
||||
Configure the writer behavior using metadata in `WriterOptions`:
|
||||
|
||||
```go
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "models.go",
|
||||
PackageName: "models",
|
||||
Metadata: map[string]interface{}{
|
||||
"multi_file": true, // Enable multi-file mode
|
||||
"populate_refs": true, // Populate RefDatabase/RefSchema
|
||||
"generate_get_id_str": true, // Generate GetIDStr() methods
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Type Mapping
|
||||
|
||||
| SQL Type | Go Type | Notes |
|
||||
|----------|---------|-------|
|
||||
| bigint, int8 | int64 | - |
|
||||
| integer, int, int4 | int | - |
|
||||
| smallint, int2 | int16 | - |
|
||||
| varchar, text | string | Not nullable |
|
||||
| varchar, text (nullable) | sql_types.SqlString | Nullable |
|
||||
| boolean, bool | bool | - |
|
||||
| timestamp, timestamptz | time.Time | - |
|
||||
| numeric, decimal | float64 | - |
|
||||
| uuid | string | - |
|
||||
| json, jsonb | string | - |
|
||||
|
||||
## Relationship Generation
|
||||
|
||||
The writer automatically generates relationship fields:
|
||||
|
||||
- **Belongs-to**: Generated for tables with foreign keys
|
||||
- **Has-many**: Generated for tables referenced by foreign keys
|
||||
- Relationship field names use 3-letter prefixes
|
||||
- Includes proper `gorm` tags with `foreignKey` and `references`
|
||||
|
||||
## Notes
|
||||
|
||||
- Model names are prefixed with "Model" (e.g., `ModelUser`)
|
||||
- Nullable columns use `sql_types.SqlString`, `sql_types.SqlInt64`, etc.
|
||||
- Generated code is auto-formatted with `go fmt`
|
||||
- JSON tags are automatically added
|
||||
- Supports schema-qualified table names in `TableName()` method
|
||||
277
pkg/writers/json/README.md
Normal file
277
pkg/writers/json/README.md
Normal file
@@ -0,0 +1,277 @@
|
||||
# JSON Writer
|
||||
|
||||
Generates database schema definitions in JSON format.
|
||||
|
||||
## Overview
|
||||
|
||||
The JSON Writer converts RelSpec's internal database model representation into JSON format, providing a complete, structured representation of the database schema.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates RelSpec's canonical JSON schema format
|
||||
- Complete schema representation including:
|
||||
- Databases and schemas
|
||||
- Tables, columns, and data types
|
||||
- Constraints (PK, FK, unique, check)
|
||||
- Indexes
|
||||
- Relationships
|
||||
- Views and sequences
|
||||
- Pretty-printed, human-readable output
|
||||
- Suitable for version control
|
||||
- Ideal interchange format
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/json"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "schema.json",
|
||||
}
|
||||
|
||||
writer := json.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Export PostgreSQL database to JSON
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output json \
|
||||
--out-file schema.json
|
||||
|
||||
# Convert GORM models to JSON
|
||||
relspec --input gorm --in-file models.go --output json --out-file schema.json
|
||||
|
||||
# Convert DBML to JSON
|
||||
relspec --input dbml --in-file diagram.dbml --output json --out-file schema.json
|
||||
```
|
||||
|
||||
## Generated JSON Example
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "myapp",
|
||||
"description": "",
|
||||
"database_type": "postgresql",
|
||||
"database_version": "",
|
||||
"source_format": "pgsql",
|
||||
"schemas": [
|
||||
{
|
||||
"name": "public",
|
||||
"description": "",
|
||||
"tables": [
|
||||
{
|
||||
"name": "users",
|
||||
"schema": "public",
|
||||
"description": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"table": "users",
|
||||
"schema": "public",
|
||||
"type": "bigint",
|
||||
"length": 0,
|
||||
"precision": 0,
|
||||
"scale": 0,
|
||||
"not_null": true,
|
||||
"is_primary_key": true,
|
||||
"auto_increment": true,
|
||||
"default": "",
|
||||
"sequence": 1
|
||||
},
|
||||
"username": {
|
||||
"name": "username",
|
||||
"table": "users",
|
||||
"schema": "public",
|
||||
"type": "varchar",
|
||||
"length": 50,
|
||||
"not_null": true,
|
||||
"is_primary_key": false,
|
||||
"auto_increment": false,
|
||||
"sequence": 2
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"table": "users",
|
||||
"schema": "public",
|
||||
"type": "varchar",
|
||||
"length": 100,
|
||||
"not_null": true,
|
||||
"sequence": 3
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"pk_users": {
|
||||
"name": "pk_users",
|
||||
"type": "PRIMARY KEY",
|
||||
"table": "users",
|
||||
"schema": "public",
|
||||
"columns": ["id"]
|
||||
},
|
||||
"uq_users_username": {
|
||||
"name": "uq_users_username",
|
||||
"type": "UNIQUE",
|
||||
"table": "users",
|
||||
"schema": "public",
|
||||
"columns": ["username"]
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"idx_users_email": {
|
||||
"name": "idx_users_email",
|
||||
"table": "users",
|
||||
"schema": "public",
|
||||
"columns": ["email"],
|
||||
"unique": false,
|
||||
"type": "btree"
|
||||
}
|
||||
},
|
||||
"relationships": {}
|
||||
},
|
||||
{
|
||||
"name": "posts",
|
||||
"schema": "public",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "bigint",
|
||||
"not_null": true,
|
||||
"is_primary_key": true,
|
||||
"sequence": 1
|
||||
},
|
||||
"user_id": {
|
||||
"name": "user_id",
|
||||
"type": "bigint",
|
||||
"not_null": true,
|
||||
"sequence": 2
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "varchar",
|
||||
"length": 200,
|
||||
"not_null": true,
|
||||
"sequence": 3
|
||||
},
|
||||
"content": {
|
||||
"name": "content",
|
||||
"type": "text",
|
||||
"not_null": false,
|
||||
"sequence": 4
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fk_posts_user_id": {
|
||||
"name": "fk_posts_user_id",
|
||||
"type": "FOREIGN KEY",
|
||||
"table": "posts",
|
||||
"schema": "public",
|
||||
"columns": ["user_id"],
|
||||
"referenced_table": "users",
|
||||
"referenced_schema": "public",
|
||||
"referenced_columns": ["id"],
|
||||
"on_delete": "CASCADE",
|
||||
"on_update": "NO ACTION"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"idx_posts_user_id": {
|
||||
"name": "idx_posts_user_id",
|
||||
"columns": ["user_id"],
|
||||
"unique": false,
|
||||
"type": "btree"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"sequences": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Schema Structure
|
||||
|
||||
The JSON format includes:
|
||||
|
||||
### Database Level
|
||||
- `name` - Database name
|
||||
- `description` - Database description
|
||||
- `database_type` - Database system type
|
||||
- `database_version` - Version information
|
||||
- `source_format` - Original source format
|
||||
- `schemas` - Array of schema objects
|
||||
|
||||
### Schema Level
|
||||
- `name` - Schema name
|
||||
- `description` - Schema description
|
||||
- `tables` - Array of table objects
|
||||
- `views` - Array of view objects
|
||||
- `sequences` - Array of sequence objects
|
||||
|
||||
### Table Level
|
||||
- `name` - Table name
|
||||
- `schema` - Schema name
|
||||
- `description` - Table description
|
||||
- `columns` - Map of column objects
|
||||
- `constraints` - Map of constraint objects
|
||||
- `indexes` - Map of index objects
|
||||
- `relationships` - Map of relationship objects
|
||||
|
||||
### Column Level
|
||||
- `name` - Column name
|
||||
- `type` - Data type
|
||||
- `length` - Type length
|
||||
- `precision`, `scale` - Numeric precision
|
||||
- `not_null` - NOT NULL flag
|
||||
- `is_primary_key` - Primary key flag
|
||||
- `auto_increment` - Auto-increment flag
|
||||
- `default` - Default value
|
||||
- `sequence` - Column order
|
||||
|
||||
### Constraint Level
|
||||
- `name` - Constraint name
|
||||
- `type` - Constraint type (PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK)
|
||||
- `columns` - Constrained columns
|
||||
- `referenced_table`, `referenced_schema` - FK references
|
||||
- `referenced_columns` - Referenced columns
|
||||
- `on_delete`, `on_update` - FK actions
|
||||
|
||||
### Index Level
|
||||
- `name` - Index name
|
||||
- `columns` - Indexed columns
|
||||
- `unique` - Unique flag
|
||||
- `type` - Index type
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **Version Control** - Track schema changes in git
|
||||
- **Documentation** - Human-readable schema documentation
|
||||
- **Interchange** - Standard format for tool integration
|
||||
- **Backup** - Schema backup without database access
|
||||
- **Testing** - Test data for schema validation
|
||||
- **API** - Schema information for APIs
|
||||
|
||||
## Notes
|
||||
|
||||
- Output is pretty-printed with 2-space indentation
|
||||
- Preserves all schema metadata
|
||||
- Can be round-tripped (read and write) without loss
|
||||
- Schema-agnostic format
|
||||
- Ideal for automation and tooling
|
||||
195
pkg/writers/pgsql/README.md
Normal file
195
pkg/writers/pgsql/README.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# PostgreSQL Writer
|
||||
|
||||
Generates PostgreSQL DDL (Data Definition Language) SQL scripts from database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The PostgreSQL Writer converts RelSpec's internal database model representation into PostgreSQL-compatible SQL DDL scripts, including CREATE TABLE statements, constraints, indexes, views, and sequences.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates complete PostgreSQL DDL
|
||||
- Creates schemas, tables, columns
|
||||
- Defines constraints (PK, FK, unique, check)
|
||||
- Creates indexes
|
||||
- Generates views and sequences
|
||||
- Supports migration scripts
|
||||
- Includes audit triggers (optional)
|
||||
- Handles PostgreSQL-specific data types
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/pgsql"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "schema.sql",
|
||||
}
|
||||
|
||||
writer := pgsql.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate PostgreSQL DDL from JSON schema
|
||||
relspec --input json \
|
||||
--in-file schema.json \
|
||||
--output pgsql \
|
||||
--out-file schema.sql
|
||||
|
||||
# Convert GORM models to PostgreSQL DDL
|
||||
relspec --input gorm \
|
||||
--in-file models.go \
|
||||
--output pgsql \
|
||||
--out-file create_tables.sql
|
||||
|
||||
# Export live database schema to SQL
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/source_db" \
|
||||
--output pgsql \
|
||||
--out-file backup_schema.sql
|
||||
```
|
||||
|
||||
## Generated SQL Example
|
||||
|
||||
```sql
|
||||
-- Schema: public
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS public;
|
||||
|
||||
-- Table: public.users
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.users (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL,
|
||||
email VARCHAR(100) NOT NULL,
|
||||
bio TEXT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Constraints for public.users
|
||||
|
||||
ALTER TABLE public.users
|
||||
ADD CONSTRAINT uq_users_username UNIQUE (username);
|
||||
|
||||
-- Indexes for public.users
|
||||
|
||||
CREATE INDEX idx_users_email ON public.users (email);
|
||||
|
||||
-- Table: public.posts
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.posts (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
content TEXT,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Foreign Keys for public.posts
|
||||
|
||||
ALTER TABLE public.posts
|
||||
ADD CONSTRAINT fk_posts_user_id
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES public.users (id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE NO ACTION;
|
||||
|
||||
-- Indexes for public.posts
|
||||
|
||||
CREATE INDEX idx_posts_user_id ON public.posts (user_id);
|
||||
```
|
||||
|
||||
## Writer Options
|
||||
|
||||
### Metadata Options
|
||||
|
||||
```go
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "schema.sql",
|
||||
Metadata: map[string]interface{}{
|
||||
"include_drop": true, // Include DROP statements
|
||||
"include_audit": true, // Include audit triggers
|
||||
"if_not_exists": true, // Use IF NOT EXISTS
|
||||
"migration_mode": false, // Generate migration script
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### Full DDL Generation
|
||||
|
||||
Generates complete database structure:
|
||||
- CREATE SCHEMA statements
|
||||
- CREATE TABLE with all columns and types
|
||||
- PRIMARY KEY constraints
|
||||
- FOREIGN KEY constraints with actions
|
||||
- UNIQUE constraints
|
||||
- CHECK constraints
|
||||
- CREATE INDEX statements
|
||||
- CREATE VIEW statements
|
||||
- CREATE SEQUENCE statements
|
||||
|
||||
### Migration Mode
|
||||
|
||||
When `migration_mode` is enabled, generates migration scripts with:
|
||||
- Version tracking
|
||||
- Up/down migrations
|
||||
- Transactional DDL
|
||||
- Rollback support
|
||||
|
||||
### Audit Triggers
|
||||
|
||||
When `include_audit` is enabled, adds:
|
||||
- Created/updated timestamp triggers
|
||||
- Audit logging functionality
|
||||
- Change tracking
|
||||
|
||||
## PostgreSQL-Specific Features
|
||||
|
||||
- Serial types (SERIAL, BIGSERIAL)
|
||||
- Advanced types (UUID, JSONB, ARRAY)
|
||||
- Schema-qualified names
|
||||
- Constraint actions (CASCADE, RESTRICT, SET NULL)
|
||||
- Partial indexes
|
||||
- Function-based indexes
|
||||
- Check constraints with expressions
|
||||
|
||||
## Data Types
|
||||
|
||||
Supports all PostgreSQL data types:
|
||||
- Integer types: SMALLINT, INTEGER, BIGINT, SERIAL, BIGSERIAL
|
||||
- Numeric types: NUMERIC, DECIMAL, REAL, DOUBLE PRECISION
|
||||
- String types: VARCHAR, CHAR, TEXT
|
||||
- Date/Time: DATE, TIME, TIMESTAMP, TIMESTAMPTZ, INTERVAL
|
||||
- Boolean: BOOLEAN
|
||||
- Binary: BYTEA
|
||||
- JSON: JSON, JSONB
|
||||
- UUID: UUID
|
||||
- Network: INET, CIDR, MACADDR
|
||||
- Special: ARRAY, HSTORE
|
||||
|
||||
## Notes
|
||||
|
||||
- Generated SQL is formatted and readable
|
||||
- Comments are preserved from source schema
|
||||
- Schema names are fully qualified
|
||||
- Default values are properly quoted
|
||||
- Constraint names follow PostgreSQL conventions
|
||||
- Compatible with PostgreSQL 12+
|
||||
135
pkg/writers/prisma/README.md
Normal file
135
pkg/writers/prisma/README.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# Prisma Writer
|
||||
|
||||
Generates Prisma schema files from database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The Prisma Writer converts RelSpec's internal database model representation into Prisma schema language (`.prisma` files), complete with models, fields, relationships, and attributes.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates Prisma schema syntax
|
||||
- Creates model definitions with proper field types
|
||||
- Adds Prisma attributes (@id, @unique, @default, etc.)
|
||||
- Generates relationship fields
|
||||
- Includes datasource and generator configurations
|
||||
- Maps table/column names with @map and @@map
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/prisma"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "schema.prisma",
|
||||
Metadata: map[string]interface{}{
|
||||
"datasource_provider": "postgresql",
|
||||
},
|
||||
}
|
||||
|
||||
writer := prisma.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate Prisma schema from PostgreSQL database
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output prisma \
|
||||
--out-file schema.prisma
|
||||
|
||||
# Convert GORM models to Prisma
|
||||
relspec --input gorm --in-file models.go --output prisma --out-file schema.prisma
|
||||
|
||||
# Convert JSON to Prisma schema
|
||||
relspec --input json --in-file database.json --output prisma --out-file prisma/schema.prisma
|
||||
```
|
||||
|
||||
## Generated Code Example
|
||||
|
||||
```prisma
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique @db.VarChar(50)
|
||||
email String @db.VarChar(100)
|
||||
bio String? @db.Text
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
posts Post[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model Post {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int @map("user_id")
|
||||
title String @db.VarChar(200)
|
||||
content String? @db.Text
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("posts")
|
||||
}
|
||||
```
|
||||
|
||||
## Supported Prisma Attributes
|
||||
|
||||
### Field Attributes
|
||||
- `@id` - Primary key
|
||||
- `@unique` - Unique constraint
|
||||
- `@default()` - Default value
|
||||
- `@map()` - Column name mapping
|
||||
- `@db.*` - Database-specific types
|
||||
- `@relation()` - Relationship definition
|
||||
|
||||
### Model Attributes
|
||||
- `@@map()` - Table name mapping
|
||||
- `@@unique()` - Composite unique constraints
|
||||
- `@@index()` - Index definitions
|
||||
- `@@id()` - Composite primary keys
|
||||
|
||||
## Type Mapping
|
||||
|
||||
| SQL Type | Prisma Type | Database Type |
|
||||
|----------|-------------|---------------|
|
||||
| bigint | Int | @db.BigInt |
|
||||
| integer | Int | - |
|
||||
| varchar(n) | String | @db.VarChar(n) |
|
||||
| text | String | @db.Text |
|
||||
| boolean | Boolean | - |
|
||||
| timestamp | DateTime | @db.Timestamp |
|
||||
| uuid | String | @db.Uuid |
|
||||
| json | Json | - |
|
||||
|
||||
## Notes
|
||||
|
||||
- Model names are PascalCase (e.g., `User`, `Post`)
|
||||
- Field names are camelCase with `@map` for snake_case columns
|
||||
- Table names use `@@map` when different from model name
|
||||
- Nullable fields are marked with `?`
|
||||
- Relationship fields are automatically generated
|
||||
- Datasource provider defaults to `postgresql`
|
||||
169
pkg/writers/typeorm/README.md
Normal file
169
pkg/writers/typeorm/README.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# TypeORM Writer
|
||||
|
||||
Generates TypeScript files with TypeORM entity definitions from database schema information.
|
||||
|
||||
## Overview
|
||||
|
||||
The TypeORM Writer converts RelSpec's internal database model representation into TypeScript source code with TypeORM entity classes, including proper decorators, relationships, and column configurations.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates TypeORM-compatible TypeScript entities
|
||||
- Creates proper decorator usage (@Entity, @Column, etc.)
|
||||
- Adds relationship decorators (@OneToMany, @ManyToOne, @JoinColumn)
|
||||
- Handles column types and options
|
||||
- Supports constraints and indexes
|
||||
- Outputs formatted TypeScript code
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/typeorm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "entities/",
|
||||
}
|
||||
|
||||
writer := typeorm.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate TypeORM entities from PostgreSQL database
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output typeorm \
|
||||
--out-file entities/
|
||||
|
||||
# Convert GORM models to TypeORM
|
||||
relspec --input gorm --in-file models.go --output typeorm --out-file src/entities/
|
||||
|
||||
# Convert JSON to TypeORM entities
|
||||
relspec --input json --in-file schema.json --output typeorm --out-file entities/
|
||||
```
|
||||
|
||||
## Generated Code Example
|
||||
|
||||
```typescript
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
OneToMany,
|
||||
ManyToOne,
|
||||
JoinColumn,
|
||||
Index,
|
||||
} from 'typeorm';
|
||||
import { Post } from './Post';
|
||||
|
||||
@Entity('users')
|
||||
export class User {
|
||||
@PrimaryGeneratedColumn('increment')
|
||||
id: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, unique: true })
|
||||
@Index()
|
||||
username: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 100 })
|
||||
email: string;
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
bio: string | null;
|
||||
|
||||
@CreateDateColumn({ name: 'created_at' })
|
||||
createdAt: Date;
|
||||
|
||||
@OneToMany(() => Post, (post) => post.user)
|
||||
posts: Post[];
|
||||
}
|
||||
|
||||
@Entity('posts')
|
||||
export class Post {
|
||||
@PrimaryGeneratedColumn('increment')
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id' })
|
||||
userId: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 200 })
|
||||
title: string;
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
content: string | null;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.posts, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'user_id' })
|
||||
user: User;
|
||||
}
|
||||
```
|
||||
|
||||
## Supported TypeORM Decorators
|
||||
|
||||
### Entity Decorators
|
||||
- `@Entity()` - Define entity/table
|
||||
- `@PrimaryGeneratedColumn()` - Auto-increment primary key
|
||||
- `@PrimaryColumn()` - Primary key
|
||||
- `@Column()` - Column definition
|
||||
- `@CreateDateColumn()` - Auto-set creation timestamp
|
||||
- `@UpdateDateColumn()` - Auto-update timestamp
|
||||
|
||||
### Relationship Decorators
|
||||
- `@OneToMany()` - One-to-many relationship
|
||||
- `@ManyToOne()` - Many-to-one relationship
|
||||
- `@JoinColumn()` - Foreign key column specification
|
||||
|
||||
### Constraint Decorators
|
||||
- `@Index()` - Create index
|
||||
- `@Unique()` - Unique constraint
|
||||
|
||||
## Column Options
|
||||
|
||||
```typescript
|
||||
@Column({
|
||||
type: 'varchar', // Column type
|
||||
length: 255, // Length for varchar/char
|
||||
nullable: true, // Allow NULL
|
||||
unique: true, // Unique constraint
|
||||
default: 'value', // Default value
|
||||
name: 'column_name', // Database column name
|
||||
})
|
||||
```
|
||||
|
||||
## Type Mapping
|
||||
|
||||
| SQL Type | TypeScript Type | TypeORM Type |
|
||||
|----------|-----------------|--------------|
|
||||
| bigint | number | 'bigint' |
|
||||
| integer | number | 'int' |
|
||||
| varchar | string | 'varchar' |
|
||||
| text | string | 'text' |
|
||||
| boolean | boolean | 'boolean' |
|
||||
| timestamp | Date | 'timestamp' |
|
||||
| json | object | 'json' |
|
||||
| uuid | string | 'uuid' |
|
||||
|
||||
## Notes
|
||||
|
||||
- Entity class names are PascalCase
|
||||
- One file per entity (named after the entity)
|
||||
- Relationship imports are auto-generated
|
||||
- Nullable columns use TypeScript union with `null`
|
||||
- Foreign key actions (CASCADE, etc.) are included
|
||||
- Schema names can be specified in `@Entity()` decorator
|
||||
212
pkg/writers/yaml/README.md
Normal file
212
pkg/writers/yaml/README.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# YAML Writer
|
||||
|
||||
Generates database schema definitions in YAML format.
|
||||
|
||||
## Overview
|
||||
|
||||
The YAML Writer converts RelSpec's internal database model representation into YAML format, providing a human-readable, structured representation of the database schema.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates RelSpec's canonical YAML schema format
|
||||
- Human-readable alternative to JSON
|
||||
- Complete schema representation including:
|
||||
- Databases and schemas
|
||||
- Tables, columns, and data types
|
||||
- Constraints (PK, FK, unique, check)
|
||||
- Indexes
|
||||
- Relationships
|
||||
- Views and sequences
|
||||
- Supports comments
|
||||
- Ideal for manual editing and configuration
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers/yaml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "schema.yaml",
|
||||
}
|
||||
|
||||
writer := yaml.NewWriter(options)
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Export PostgreSQL database to YAML
|
||||
relspec --input pgsql \
|
||||
--conn "postgres://localhost/mydb" \
|
||||
--output yaml \
|
||||
--out-file schema.yaml
|
||||
|
||||
# Convert GORM models to YAML
|
||||
relspec --input gorm --in-file models.go --output yaml --out-file schema.yaml
|
||||
|
||||
# Convert JSON to YAML
|
||||
relspec --input json --in-file schema.json --output yaml --out-file schema.yaml
|
||||
```
|
||||
|
||||
## Generated YAML Example
|
||||
|
||||
```yaml
|
||||
name: myapp
|
||||
database_type: postgresql
|
||||
source_format: pgsql
|
||||
schemas:
|
||||
- name: public
|
||||
tables:
|
||||
- name: users
|
||||
schema: public
|
||||
columns:
|
||||
id:
|
||||
name: id
|
||||
table: users
|
||||
schema: public
|
||||
type: bigint
|
||||
not_null: true
|
||||
is_primary_key: true
|
||||
auto_increment: true
|
||||
sequence: 1
|
||||
username:
|
||||
name: username
|
||||
table: users
|
||||
schema: public
|
||||
type: varchar
|
||||
length: 50
|
||||
not_null: true
|
||||
sequence: 2
|
||||
email:
|
||||
name: email
|
||||
table: users
|
||||
schema: public
|
||||
type: varchar
|
||||
length: 100
|
||||
not_null: true
|
||||
sequence: 3
|
||||
constraints:
|
||||
pk_users:
|
||||
name: pk_users
|
||||
type: PRIMARY KEY
|
||||
table: users
|
||||
schema: public
|
||||
columns:
|
||||
- id
|
||||
uq_users_username:
|
||||
name: uq_users_username
|
||||
type: UNIQUE
|
||||
table: users
|
||||
schema: public
|
||||
columns:
|
||||
- username
|
||||
indexes:
|
||||
idx_users_email:
|
||||
name: idx_users_email
|
||||
table: users
|
||||
schema: public
|
||||
columns:
|
||||
- email
|
||||
unique: false
|
||||
type: btree
|
||||
|
||||
- name: posts
|
||||
schema: public
|
||||
columns:
|
||||
id:
|
||||
name: id
|
||||
type: bigint
|
||||
not_null: true
|
||||
is_primary_key: true
|
||||
sequence: 1
|
||||
user_id:
|
||||
name: user_id
|
||||
type: bigint
|
||||
not_null: true
|
||||
sequence: 2
|
||||
title:
|
||||
name: title
|
||||
type: varchar
|
||||
length: 200
|
||||
not_null: true
|
||||
sequence: 3
|
||||
content:
|
||||
name: content
|
||||
type: text
|
||||
not_null: false
|
||||
sequence: 4
|
||||
constraints:
|
||||
fk_posts_user_id:
|
||||
name: fk_posts_user_id
|
||||
type: FOREIGN KEY
|
||||
table: posts
|
||||
schema: public
|
||||
columns:
|
||||
- user_id
|
||||
referenced_table: users
|
||||
referenced_schema: public
|
||||
referenced_columns:
|
||||
- id
|
||||
on_delete: CASCADE
|
||||
on_update: NO ACTION
|
||||
indexes:
|
||||
idx_posts_user_id:
|
||||
name: idx_posts_user_id
|
||||
columns:
|
||||
- user_id
|
||||
unique: false
|
||||
type: btree
|
||||
views: []
|
||||
sequences: []
|
||||
```
|
||||
|
||||
## Schema Structure
|
||||
|
||||
The YAML format mirrors the JSON structure with human-readable syntax:
|
||||
|
||||
- Database level: `name`, `database_type`, `source_format`, `schemas`
|
||||
- Schema level: `name`, `tables`, `views`, `sequences`
|
||||
- Table level: `name`, `schema`, `columns`, `constraints`, `indexes`
|
||||
- Column level: `name`, `type`, `length`, `not_null`, etc.
|
||||
- Constraint level: `name`, `type`, `columns`, foreign key details
|
||||
- Index level: `name`, `columns`, `unique`, `type`
|
||||
|
||||
## Advantages Over JSON
|
||||
|
||||
- More human-readable
|
||||
- Easier to edit manually
|
||||
- Supports comments
|
||||
- Less verbose (no braces/brackets)
|
||||
- Better for configuration files
|
||||
- Natural indentation
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **Configuration** - Schema as configuration
|
||||
- **Documentation** - Human-readable schema docs
|
||||
- **Version Control** - Easier to read diffs
|
||||
- **Manual Editing** - Easier to modify by hand
|
||||
- **Code Generation** - Template-friendly format
|
||||
|
||||
## Notes
|
||||
|
||||
- Output is properly indented (2 spaces)
|
||||
- Preserves all schema metadata
|
||||
- Can be round-tripped with YAML reader
|
||||
- Compatible with YAML 1.2
|
||||
- More readable than JSON for large schemas
|
||||
- Ideal for documentation and manual workflows
|
||||
Reference in New Issue
Block a user