Updated Readme files
This commit is contained in:
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