init
This commit is contained in:
5
.claude/commands/build.md
Normal file
5
.claude/commands/build.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
description: Build the RelSpec binary
|
||||
---
|
||||
|
||||
Build the RelSpec project by running `go build -o relspec ./cmd/relspec`. Report the build status and any errors encountered.
|
||||
9
.claude/commands/coverage.md
Normal file
9
.claude/commands/coverage.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
description: Generate test coverage report
|
||||
---
|
||||
|
||||
Generate and display test coverage for RelSpec:
|
||||
1. Run `go test -cover ./...` to get coverage percentage
|
||||
2. If detailed coverage is needed, run `go test -coverprofile=coverage.out ./...` and then `go tool cover -html=coverage.out` to generate HTML report
|
||||
|
||||
Show coverage statistics and identify areas needing more tests.
|
||||
10
.claude/commands/lint.md
Normal file
10
.claude/commands/lint.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
description: Run Go linters on the codebase
|
||||
---
|
||||
|
||||
Run linting tools on the RelSpec codebase:
|
||||
1. First run `gofmt -l .` to check formatting
|
||||
2. If golangci-lint is available, run `golangci-lint run ./...`
|
||||
3. Run `go vet ./...` to check for suspicious constructs
|
||||
|
||||
Report any issues found and suggest fixes if needed.
|
||||
5
.claude/commands/test.md
Normal file
5
.claude/commands/test.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
description: Run all tests for the RelSpec project
|
||||
---
|
||||
|
||||
Run `go test ./...` to execute all unit tests in the project. Show a summary of the results and highlight any failures.
|
||||
25
.claude/settings.json
Normal file
25
.claude/settings.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"project": {
|
||||
"name": "RelSpec",
|
||||
"description": "Database Relations Specification Tool for Go",
|
||||
"language": "go"
|
||||
},
|
||||
"agent": {
|
||||
"preferred": "Explore",
|
||||
"description": "Use Explore agent for fast codebase navigation and Go project exploration"
|
||||
},
|
||||
"codeStyle": {
|
||||
"useGofmt": true,
|
||||
"lineLength": 100,
|
||||
"tabWidth": 4,
|
||||
"useTabs": true
|
||||
},
|
||||
"testing": {
|
||||
"framework": "go test",
|
||||
"runOnChange": false
|
||||
},
|
||||
"build": {
|
||||
"command": "go build -o relspec ./cmd/relspec",
|
||||
"outputBinary": "relspec"
|
||||
}
|
||||
}
|
||||
39
.editorconfig
Normal file
39
.editorconfig
Normal file
@@ -0,0 +1,39 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# Go files
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
# YAML files
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# JSON files
|
||||
[*.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# Markdown files
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# Makefile
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
# Shell scripts
|
||||
[*.sh]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
85
.github/workflows/ci.yml
vendored
Normal file
85
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: ['1.23', '1.24', '1.25']
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go-
|
||||
|
||||
- name: Download dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Run tests
|
||||
run: go test -v -race -coverprofile=coverage.out -covermode=atomic ./...
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: ./coverage.out
|
||||
flags: unittests
|
||||
name: codecov-umbrella
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.25'
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
version: latest
|
||||
args: --config=.golangci.json
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.25'
|
||||
|
||||
- name: Build
|
||||
run: go build -v ./cmd/relspec
|
||||
|
||||
- name: Check mod tidiness
|
||||
run: |
|
||||
go mod tidy
|
||||
git diff --exit-code go.mod go.sum
|
||||
26
.gitignore
vendored
26
.gitignore
vendored
@@ -21,3 +21,29 @@
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# RelSpec specific
|
||||
relspec
|
||||
*.test
|
||||
coverage.out
|
||||
coverage.html
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Test outputs
|
||||
test_output/
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
|
||||
# Build artifacts
|
||||
dist/
|
||||
build/
|
||||
|
||||
114
.golangci.json
Normal file
114
.golangci.json
Normal file
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"formatters": {
|
||||
"enable": [
|
||||
"gofmt",
|
||||
"goimports"
|
||||
],
|
||||
"exclusions": {
|
||||
"generated": "lax",
|
||||
"paths": [
|
||||
"third_party$",
|
||||
"builtin$",
|
||||
"examples$"
|
||||
]
|
||||
},
|
||||
"settings": {
|
||||
"gofmt": {
|
||||
"simplify": true
|
||||
},
|
||||
"goimports": {
|
||||
"local-prefixes": [
|
||||
"git.warky.dev/wdevs/relspecgo"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"max-issues-per-linter": 0,
|
||||
"max-same-issues": 0
|
||||
},
|
||||
"linters": {
|
||||
"enable": [
|
||||
"gocritic",
|
||||
"misspell",
|
||||
"revive"
|
||||
],
|
||||
"exclusions": {
|
||||
"generated": "lax",
|
||||
"paths": [
|
||||
"third_party$",
|
||||
"builtin$",
|
||||
"examples$",
|
||||
"mocks?",
|
||||
"tests?"
|
||||
],
|
||||
"rules": [
|
||||
{
|
||||
"linters": [
|
||||
"dupl",
|
||||
"errcheck",
|
||||
"gocritic",
|
||||
"gosec"
|
||||
],
|
||||
"path": "_test\\.go"
|
||||
},
|
||||
{
|
||||
"linters": [
|
||||
"errcheck"
|
||||
],
|
||||
"text": "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked"
|
||||
},
|
||||
{
|
||||
"path": "_test\\.go",
|
||||
"text": "cognitive complexity|cyclomatic complexity"
|
||||
}
|
||||
]
|
||||
},
|
||||
"settings": {
|
||||
"errcheck": {
|
||||
"check-blank": false,
|
||||
"check-type-assertions": false
|
||||
},
|
||||
"gocritic": {
|
||||
"enabled-checks": [
|
||||
"boolExprSimplify",
|
||||
"builtinShadow",
|
||||
"emptyFallthrough",
|
||||
"equalFold",
|
||||
"indexAlloc",
|
||||
"initClause",
|
||||
"methodExprCall",
|
||||
"nilValReturn",
|
||||
"rangeExprCopy",
|
||||
"rangeValCopy",
|
||||
"stringXbytes",
|
||||
"typeAssertChain",
|
||||
"unlabelStmt",
|
||||
"unnamedResult",
|
||||
"unnecessaryBlock",
|
||||
"weakCond",
|
||||
"yodaStyleExpr"
|
||||
],
|
||||
"disabled-checks": [
|
||||
"ifElseChain"
|
||||
]
|
||||
},
|
||||
"revive": {
|
||||
"rules": [
|
||||
{
|
||||
"disabled": true,
|
||||
"name": "exported"
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"name": "package-comments"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"run": {
|
||||
"tests": true
|
||||
},
|
||||
"version": "2"
|
||||
}
|
||||
145
CONTRIBUTING.md
Normal file
145
CONTRIBUTING.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# Contributing to RelSpec
|
||||
|
||||
Thank you for your interest in contributing to RelSpec.
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Prerequisites
|
||||
- Go 1.21 or higher
|
||||
- Git
|
||||
- (Optional) golangci-lint for linting
|
||||
- (Optional) Docker for database testing
|
||||
|
||||
### Getting Started
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/wdevs/relspecgo.git
|
||||
cd relspecgo
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
go mod download
|
||||
```
|
||||
|
||||
3. Run tests:
|
||||
```bash
|
||||
go test ./...
|
||||
```
|
||||
|
||||
4. Build the project:
|
||||
```bash
|
||||
go build -o relspec ./cmd/relspec
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
relspecgo/
|
||||
├── cmd/ # CLI application entry point
|
||||
├── pkg/
|
||||
│ ├── readers/ # Input format readers (XML, JSON, DCTX, DB, GORM, Bun)
|
||||
│ ├── writers/ # Output format writers (GORM, Bun, JSON, YAML)
|
||||
│ ├── models/ # Internal data models for relations
|
||||
│ └── transform/ # Transformation and validation logic
|
||||
├── examples/ # Usage examples and sample files
|
||||
├── tests/ # Integration tests
|
||||
└── .claude/ # Claude Code configuration and commands
|
||||
```
|
||||
|
||||
## Adding New Readers
|
||||
|
||||
To add a new input format reader:
|
||||
|
||||
1. Create a new file in `pkg/readers/` (e.g., `myformat_reader.go`)
|
||||
2. Implement the `Reader` interface:
|
||||
```go
|
||||
type Reader interface {
|
||||
Read(source string) (*models.Schema, error)
|
||||
}
|
||||
```
|
||||
3. Add tests in `pkg/readers/myformat_reader_test.go`
|
||||
4. Register the reader in the CLI
|
||||
|
||||
## Adding New Writers
|
||||
|
||||
To add a new output format writer:
|
||||
|
||||
1. Create a new file in `pkg/writers/` (e.g., `myformat_writer.go`)
|
||||
2. Implement the `Writer` interface:
|
||||
```go
|
||||
type Writer interface {
|
||||
Write(schema *models.Schema, destination string) error
|
||||
}
|
||||
```
|
||||
3. Add tests in `pkg/writers/myformat_writer_test.go`
|
||||
4. Register the writer in the CLI
|
||||
|
||||
## Code Style
|
||||
|
||||
- Follow standard Go conventions
|
||||
- Use `gofmt` for formatting
|
||||
- Run `go vet` to check for issues
|
||||
- Use meaningful variable and function names
|
||||
- Add comments for exported functions and types
|
||||
|
||||
## Testing
|
||||
|
||||
- Write unit tests for all new functionality
|
||||
- Aim for >80% code coverage
|
||||
- Use table-driven tests where appropriate
|
||||
- Include both positive and negative test cases
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# All tests
|
||||
go test ./...
|
||||
|
||||
# With coverage
|
||||
go test -cover ./...
|
||||
|
||||
# Verbose output
|
||||
go test -v ./...
|
||||
|
||||
# Specific package
|
||||
go test ./pkg/readers/...
|
||||
```
|
||||
|
||||
## Committing Changes
|
||||
|
||||
- Write clear, descriptive commit messages
|
||||
- Follow conventional commits format: `type(scope): description`
|
||||
- Types: feat, fix, docs, test, refactor, chore
|
||||
- Example: `feat(readers): add PostgreSQL support`
|
||||
- Keep commits focused and atomic
|
||||
- Reference issues in commit messages when applicable
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
1. Create a feature branch from `master`
|
||||
2. Make your changes
|
||||
3. Add tests for new functionality
|
||||
4. Ensure all tests pass
|
||||
5. Update documentation if needed
|
||||
6. Submit a pull request with a clear description
|
||||
|
||||
## Claude Code Commands
|
||||
|
||||
This project includes Claude Code slash commands for common tasks:
|
||||
|
||||
- `/test` - Run all tests
|
||||
- `/build` - Build the binary
|
||||
- `/lint` - Run linters
|
||||
- `/coverage` - Generate coverage report
|
||||
|
||||
## Questions or Issues?
|
||||
|
||||
- Open an issue for bugs or feature requests
|
||||
- Start a discussion for questions or ideas
|
||||
- Check existing issues before creating new ones
|
||||
|
||||
## License
|
||||
|
||||
By contributing to RelSpec, you agree that your contributions will be licensed under the Apache License 2.0.
|
||||
62
Makefile
Normal file
62
Makefile
Normal file
@@ -0,0 +1,62 @@
|
||||
.PHONY: all build test lint coverage clean install help
|
||||
|
||||
# Binary name
|
||||
BINARY_NAME=relspec
|
||||
|
||||
# Build directory
|
||||
BUILD_DIR=build
|
||||
|
||||
# Go parameters
|
||||
GOCMD=go
|
||||
GOBUILD=$(GOCMD) build
|
||||
GOTEST=$(GOCMD) test
|
||||
GOGET=$(GOCMD) get
|
||||
GOMOD=$(GOCMD) mod
|
||||
GOCLEAN=$(GOCMD) clean
|
||||
|
||||
all: lint test build ## Run linting, tests, and build
|
||||
|
||||
build: ## Build the binary
|
||||
@echo "Building $(BINARY_NAME)..."
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
$(GOBUILD) -o $(BUILD_DIR)/$(BINARY_NAME) ./cmd/relspec
|
||||
@echo "Build complete: $(BUILD_DIR)/$(BINARY_NAME)"
|
||||
|
||||
test: ## Run tests
|
||||
@echo "Running tests..."
|
||||
$(GOTEST) -v -race -coverprofile=coverage.out ./...
|
||||
|
||||
coverage: test ## Run tests with coverage report
|
||||
@echo "Generating coverage report..."
|
||||
$(GOCMD) tool cover -html=coverage.out -o coverage.html
|
||||
@echo "Coverage report generated: coverage.html"
|
||||
|
||||
lint: ## Run linter
|
||||
@echo "Running linter..."
|
||||
@if command -v golangci-lint > /dev/null; then \
|
||||
golangci-lint run --config=.golangci.json; \
|
||||
else \
|
||||
echo "golangci-lint not installed. Install with: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
clean: ## Clean build artifacts
|
||||
@echo "Cleaning..."
|
||||
$(GOCLEAN)
|
||||
rm -rf $(BUILD_DIR)
|
||||
rm -f coverage.out coverage.html
|
||||
@echo "Clean complete"
|
||||
|
||||
install: ## Install the binary to $GOPATH/bin
|
||||
@echo "Installing $(BINARY_NAME)..."
|
||||
$(GOCMD) install ./cmd/relspec
|
||||
@echo "Install complete"
|
||||
|
||||
deps: ## Download dependencies
|
||||
@echo "Downloading dependencies..."
|
||||
$(GOMOD) download
|
||||
$(GOMOD) tidy
|
||||
@echo "Dependencies updated"
|
||||
|
||||
help: ## Display this help screen
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||
94
README.md
94
README.md
@@ -1,3 +1,93 @@
|
||||
# relspecgo
|
||||
# RelSpec
|
||||
|
||||
Resolve Spec Go
|
||||
> Database Relations Specification Tool for Go
|
||||
|
||||
RelSpec is a comprehensive database relations management tool that reads, transforms, and writes database table specifications across multiple formats and ORMs.
|
||||
|
||||
## Overview
|
||||
|
||||
RelSpec provides bidirectional conversion between various database specification formats, allowing you to:
|
||||
- Inspect live databases and extract their structure
|
||||
- Convert between different ORM models (GORM, Bun)
|
||||
- Transform legacy schema definitions (Clarion DCTX, XML, JSON)
|
||||
- Generate standardized specification files (JSON, YAML)
|
||||
|
||||
## 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
|
||||
|
||||
### 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
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/wdevs/relspecgo
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Inspect database and generate GORM models
|
||||
relspec --input db --conn "postgres://..." --output gorm --out-file models.go
|
||||
|
||||
# Convert GORM models to Bun
|
||||
relspec --input gorm --in-file existing.go --output bun --out-file bun_models.go
|
||||
|
||||
# Export database schema to JSON
|
||||
relspec --input db --conn "mysql://..." --output json --out-file schema.json
|
||||
|
||||
# Convert Clarion DCTX to YAML
|
||||
relspec --input dctx --in-file legacy.dctx --output yaml --out-file schema.yaml
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
relspecgo/
|
||||
├── cmd/ # CLI application
|
||||
├── pkg/
|
||||
│ ├── readers/ # Input format readers
|
||||
│ ├── writers/ # Output format writers
|
||||
│ ├── models/ # Internal data models
|
||||
│ └── transform/ # Transformation logic
|
||||
├── examples/ # Usage examples
|
||||
└── tests/ # Test files
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Prerequisites
|
||||
- Go 1.21 or higher
|
||||
- Access to test databases (optional)
|
||||
|
||||
### Building
|
||||
|
||||
```bash
|
||||
go build -o relspec ./cmd/relspec
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
go test ./...
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Apache License 2.0 - See [LICENSE](LICENSE) for details.
|
||||
|
||||
Copyright 2025 wdevs
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions welcome. Please open an issue or submit a pull request.
|
||||
120
TODO.md
Normal file
120
TODO.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# RelSpec - TODO List
|
||||
|
||||
## Project Setup
|
||||
- [ ] Initialize Go module (`go.mod`)
|
||||
- [ ] Set up project directory structure
|
||||
- [ ] Create `.editorconfig` for consistent formatting
|
||||
- [ ] Add GitHub Actions for CI/CD
|
||||
- [ ] Set up pre-commit hooks
|
||||
|
||||
## Core Infrastructure
|
||||
- [ ] Define internal data model for database relations
|
||||
- [ ] Implement relation types (one-to-one, one-to-many, many-to-many)
|
||||
- [ ] Create validation framework for specifications
|
||||
- [ ] Design plugin architecture for readers/writers
|
||||
|
||||
## Input Readers
|
||||
- [ ] **Database Inspector**
|
||||
- [ ] PostgreSQL driver
|
||||
- [ ] MySQL driver
|
||||
- [ ] SQLite driver
|
||||
- [ ] MSSQL driver
|
||||
- [ ] Foreign key detection
|
||||
- [ ] Index extraction
|
||||
|
||||
- [ ] **XML Reader**
|
||||
- [ ] XML schema parser
|
||||
- [ ] Validation against XSD
|
||||
|
||||
- [ ] **JSON Reader**
|
||||
- [ ] JSON schema parser
|
||||
- [ ] Schema validation
|
||||
|
||||
- [ ] **Clarion DCTX Reader**
|
||||
- [ ] DCTX file parser
|
||||
- [ ] Legacy format support
|
||||
|
||||
- [ ] **GORM Model Reader**
|
||||
- [ ] Go AST parser for GORM tags
|
||||
- [ ] Struct field analysis
|
||||
- [ ] Relation tag extraction
|
||||
|
||||
- [ ] **Bun Model Reader**
|
||||
- [ ] Go AST parser for Bun tags
|
||||
- [ ] Struct field analysis
|
||||
- [ ] Relation tag extraction
|
||||
|
||||
## Output Writers
|
||||
- [ ] **GORM Writer**
|
||||
- [ ] Go struct generation
|
||||
- [ ] GORM tag formatting
|
||||
- [ ] Relation definitions
|
||||
- [ ] gofmt integration
|
||||
|
||||
- [ ] **Bun Writer**
|
||||
- [ ] Go struct generation
|
||||
- [ ] Bun tag formatting
|
||||
- [ ] Relation definitions
|
||||
- [ ] gofmt integration
|
||||
|
||||
- [ ] **JSON Writer**
|
||||
- [ ] Schema serialization
|
||||
- [ ] Pretty printing
|
||||
|
||||
- [ ] **YAML Writer**
|
||||
- [ ] Schema serialization
|
||||
- [ ] Comment preservation
|
||||
|
||||
## CLI Application
|
||||
- [ ] Command-line interface using cobra
|
||||
- [ ] Input format flags
|
||||
- [ ] Output format flags
|
||||
- [ ] Connection string handling
|
||||
- [ ] File I/O operations
|
||||
- [ ] Progress indicators
|
||||
- [ ] Error handling and reporting
|
||||
- [ ] Configuration file support
|
||||
|
||||
## Testing
|
||||
- [ ] Unit tests for each reader
|
||||
- [ ] Unit tests for each writer
|
||||
- [ ] Integration tests for conversion pipelines
|
||||
- [ ] Test fixtures for all formats
|
||||
- [ ] Database test containers
|
||||
- [ ] Benchmark tests for large schemas
|
||||
|
||||
## Documentation
|
||||
- [ ] API documentation (godoc)
|
||||
- [ ] Usage examples for each format combination
|
||||
- [ ] Migration guides
|
||||
- [ ] Architecture documentation
|
||||
- [ ] Contributing guidelines
|
||||
|
||||
## Advanced Features
|
||||
- [ ] Dry-run mode for validation
|
||||
- [ ] Diff tool for comparing specifications
|
||||
- [ ] Migration script generation
|
||||
- [ ] Custom type mapping configuration
|
||||
- [ ] Batch processing support
|
||||
- [ ] Watch mode for auto-regeneration
|
||||
|
||||
## Performance
|
||||
- [ ] Concurrent processing for multiple tables
|
||||
- [ ] Streaming for large databases
|
||||
- [ ] Memory optimization
|
||||
- [ ] Caching layer for repeated operations
|
||||
|
||||
## Quality & Maintenance
|
||||
- [ ] Linting with golangci-lint
|
||||
- [ ] Code coverage > 80%
|
||||
- [ ] Security scanning
|
||||
- [ ] Dependency updates automation
|
||||
- [ ] Release automation
|
||||
|
||||
## Future Considerations
|
||||
- [ ] Web UI for visual editing
|
||||
- [ ] REST API server mode
|
||||
- [ ] Support for NoSQL databases
|
||||
- [ ] GraphQL schema generation
|
||||
- [ ] Prisma schema support
|
||||
- [ ] TypeORM support
|
||||
22
go.mod
Normal file
22
go.mod
Normal file
@@ -0,0 +1,22 @@
|
||||
module git.warky.dev/wdevs/relspecgo
|
||||
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/cobra v1.10.2 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/spf13/viper v1.21.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
36
go.sum
Normal file
36
go.sum
Normal file
@@ -0,0 +1,36 @@
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
71
make_release.sh
Normal file
71
make_release.sh
Normal file
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Ask if the user wants to make a release version
|
||||
read -p "Do you want to make a release version? (y/n): " make_release
|
||||
|
||||
if [[ $make_release =~ ^[Yy]$ ]]; then
|
||||
# Get the latest tag from git
|
||||
latest_tag=$(git describe --tags --abbrev=0 2>/dev/null)
|
||||
|
||||
if [ -z "$latest_tag" ]; then
|
||||
# No tags exist yet, start with v1.0.0
|
||||
suggested_version="v1.0.0"
|
||||
echo "No existing tags found. Starting with $suggested_version"
|
||||
else
|
||||
echo "Latest tag: $latest_tag"
|
||||
|
||||
# Remove 'v' prefix if present
|
||||
version_number="${latest_tag#v}"
|
||||
|
||||
# Split version into major.minor.patch
|
||||
IFS='.' read -r major minor patch <<< "$version_number"
|
||||
|
||||
# Increment patch version
|
||||
patch=$((patch + 1))
|
||||
|
||||
# Construct new version
|
||||
suggested_version="v${major}.${minor}.${patch}"
|
||||
echo "Suggested next version: $suggested_version"
|
||||
fi
|
||||
|
||||
# Ask the user for the version number with the suggested version as default
|
||||
read -p "Enter the version number (press Enter for $suggested_version): " version
|
||||
|
||||
# Use suggested version if user pressed Enter without input
|
||||
if [ -z "$version" ]; then
|
||||
version="$suggested_version"
|
||||
fi
|
||||
|
||||
# Prepend 'v' to the version if it doesn't start with it
|
||||
if ! [[ $version =~ ^v ]]; then
|
||||
version="v$version"
|
||||
fi
|
||||
|
||||
# Get commit logs since the last tag
|
||||
if [ -z "$latest_tag" ]; then
|
||||
# No previous tag, get all commits
|
||||
commit_logs=$(git log --pretty=format:"- %s" --no-merges)
|
||||
else
|
||||
# Get commits since the last tag
|
||||
commit_logs=$(git log "${latest_tag}..HEAD" --pretty=format:"- %s" --no-merges)
|
||||
fi
|
||||
|
||||
# Create the tag message
|
||||
if [ -z "$commit_logs" ]; then
|
||||
tag_message="Release $version"
|
||||
else
|
||||
tag_message="Release $version
|
||||
|
||||
${commit_logs}"
|
||||
fi
|
||||
|
||||
# Create an annotated tag with the commit logs
|
||||
git tag -a "$version" -m "$tag_message"
|
||||
|
||||
# Push the tag to the remote repository
|
||||
git push origin "$version"
|
||||
|
||||
echo "Tag $version created and pushed to the remote repository."
|
||||
else
|
||||
echo "No release version created."
|
||||
fi
|
||||
149
pkg/models/models.go
Normal file
149
pkg/models/models.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package models
|
||||
|
||||
type DatabaseType string
|
||||
|
||||
const (
|
||||
PostgresqlDatabaseType DatabaseType = "pgsql"
|
||||
MSSQLDatabaseType DatabaseType = "mssql"
|
||||
SqlLiteDatabaseType DatabaseType = "sqlite"
|
||||
)
|
||||
|
||||
// Database represents the complete database schema
|
||||
type Database struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Schemas []*Schema `json:"schemas" yaml:"schemas" xml:"schemas"`
|
||||
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
|
||||
DatabaseType DatabaseType `json:"database_type,omitempty" yaml:"database_type,omitempty" xml:"database_type,omitempty"`
|
||||
DatabaseVersion string `json:"database_version,omitempty" yaml:"database_version,omitempty" xml:"database_version,omitempty"`
|
||||
}
|
||||
|
||||
type Schema struct {
|
||||
Name string `json:"name" yaml:"name" xml:"name"`
|
||||
Tables []*Table `json:"tables" yaml:"tables" xml:"-"`
|
||||
Owner string `json:"owner" yaml:"owner" xml:"owner"`
|
||||
Permissions map[string]string `json:"permissions,omitempty" yaml:"permissions,omitempty" xml:"-"`
|
||||
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty" xml:"-"`
|
||||
Scripts []*Script `json:"scripts,omitempty" yaml:"scripts,omitempty" xml:"scripts,omitempty"`
|
||||
}
|
||||
|
||||
type Table struct {
|
||||
Name string `json:"name" yaml:"name" xml:"name"`
|
||||
Schema string `json:"schema" yaml:"schema" xml:"schema"`
|
||||
Columns map[string]*Column `json:"columns" yaml:"columns" xml:"-"`
|
||||
Constraints map[string]*Constraint `json:"constraints" yaml:"constraints" xml:"-"`
|
||||
Indexes map[string]*Index `json:"indexes,omitempty" yaml:"indexes,omitempty" xml:"-"`
|
||||
Relationships map[string]*Relationship `json:"relationships,omitempty" yaml:"relationships,omitempty" xml:"-"`
|
||||
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
|
||||
Tablespace string `json:"tablespace,omitempty" yaml:"tablespace,omitempty" xml:"tablespace,omitempty"`
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty" xml:"-"`
|
||||
}
|
||||
|
||||
func (m Table) GetPrimaryKey() *Column {
|
||||
for _, column := range m.Columns {
|
||||
if column.IsPrimaryKey {
|
||||
return column
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m Table) GetForeignKeys() []*Constraint {
|
||||
keys := make([]*Constraint, 0)
|
||||
|
||||
for _, c := range m.Constraints {
|
||||
if c.Type == ForeignKeyConstraint {
|
||||
keys = append(keys, c)
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// Column represents a table column
|
||||
type Column struct {
|
||||
Name string `json:"name" yaml:"name" xml:"name"`
|
||||
Table string `json:"table" yaml:"table" xml:"table"`
|
||||
Schema string `json:"schema" yaml:"schema" xml:"schema"`
|
||||
Type string `json:"type" yaml:"type" xml:"type"`
|
||||
Length int `json:"length,omitempty" yaml:"length,omitempty" xml:"length,omitempty"`
|
||||
Precision int `json:"precision,omitempty" yaml:"precision,omitempty" xml:"precision,omitempty"`
|
||||
Scale int `json:"scale,omitempty" yaml:"scale,omitempty" xml:"scale,omitempty"`
|
||||
NotNull bool `json:"not_null" yaml:"not_null" xml:"not_null"`
|
||||
Default interface{} `json:"default,omitempty" yaml:"default,omitempty" xml:"default,omitempty"`
|
||||
AutoIncrement bool `json:"auto_increment" yaml:"auto_increment" xml:"auto_increment"`
|
||||
IsPrimaryKey bool `json:"is_primary_key" yaml:"is_primary_key" xml:"is_primary_key"`
|
||||
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
|
||||
Collation string `json:"collation,omitempty" yaml:"collation,omitempty" xml:"collation,omitempty"`
|
||||
}
|
||||
|
||||
type Index struct {
|
||||
Name string `json:"name" yaml:"name" xml:"name"`
|
||||
Table string `json:"table,omitempty" yaml:"table,omitempty" xml:"table,omitempty"`
|
||||
Schema string `json:"schema,omitempty" yaml:"schema,omitempty" xml:"schema,omitempty"`
|
||||
Columns []string `json:"columns" yaml:"columns" xml:"columns"`
|
||||
Unique bool `json:"unique" yaml:"unique" xml:"unique"`
|
||||
Type string `json:"type" yaml:"type" xml:"type"` // btree, hash, gin, gist, etc.
|
||||
Where string `json:"where,omitempty" yaml:"where,omitempty" xml:"where,omitempty"` // partial index condition
|
||||
Concurrent bool `json:"concurrent,omitempty" yaml:"concurrent,omitempty" xml:"concurrent,omitempty"`
|
||||
Include []string `json:"include,omitempty" yaml:"include,omitempty" xml:"include,omitempty"` // INCLUDE columns
|
||||
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
|
||||
}
|
||||
|
||||
type RelationType string
|
||||
|
||||
const (
|
||||
OneToOne RelationType = "one_to_one"
|
||||
OneToMany RelationType = "one_to_many"
|
||||
ManyToMany RelationType = "many_to_many"
|
||||
)
|
||||
|
||||
type Relationship struct {
|
||||
Name string `json:"name" yaml:"name" xml:"name"`
|
||||
Type RelationType `json:"type" yaml:"type" xml:"type"`
|
||||
FromTable string `json:"from_table" yaml:"from_table" xml:"from_table"`
|
||||
FromSchema string `json:"from_schema" yaml:"from_schema" xml:"from_schema"`
|
||||
ToTable string `json:"to_table" yaml:"to_table" xml:"to_table"`
|
||||
ToSchema string `json:"to_schema" yaml:"to_schema" xml:"to_schema"`
|
||||
ForeignKey string `json:"foreign_key" yaml:"foreign_key" xml:"foreign_key"`
|
||||
Properties map[string]string `json:"properties" yaml:"properties" xml:"-"`
|
||||
ThroughTable string `json:"through_table,omitempty" yaml:"through_table,omitempty" xml:"through_table,omitempty"` // For many-to-many
|
||||
ThroughSchema string `json:"through_schema,omitempty" yaml:"through_schema,omitempty" xml:"through_schema,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
|
||||
}
|
||||
|
||||
type Constraint struct {
|
||||
Name string `json:"name" yaml:"name" xml:"name"`
|
||||
Type ConstraintType `json:"type" yaml:"type" xml:"type"`
|
||||
Columns []string `json:"columns" yaml:"columns" xml:"columns"`
|
||||
Expression string `json:"expression,omitempty" yaml:"expression,omitempty" xml:"expression,omitempty"`
|
||||
Schema string `json:"schema,omitempty" yaml:"schema,omitempty" xml:"schema,omitempty"`
|
||||
Table string `json:"table,omitempty" yaml:"table,omitempty" xml:"table,omitempty"`
|
||||
ReferencedTable string `json:"referenced_table" yaml:"referenced_table" xml:"referenced_table"`
|
||||
ReferencedSchema string `json:"referenced_schema" yaml:"referenced_schema" xml:"referenced_schema"`
|
||||
ReferencedColumns []string `json:"referenced_columns" yaml:"referenced_columns" xml:"referenced_columns"`
|
||||
OnDelete string `json:"on_delete" yaml:"on_delete" xml:"on_delete"` // CASCADE, SET NULL, RESTRICT, etc.
|
||||
OnUpdate string `json:"on_update" yaml:"on_update" xml:"on_update"`
|
||||
Deferrable bool `json:"deferrable,omitempty" yaml:"deferrable,omitempty" xml:"deferrable,omitempty"`
|
||||
InitiallyDeferred bool `json:"initially_deferred,omitempty" yaml:"initially_deferred,omitempty" xml:"initially_deferred,omitempty"`
|
||||
}
|
||||
|
||||
type ConstraintType string
|
||||
|
||||
const (
|
||||
PrimaryKeyConstraint ConstraintType = "primary_key"
|
||||
ForeignKeyConstraint ConstraintType = "foreign_Key"
|
||||
UniqueConstraint ConstraintType = "unique"
|
||||
CheckConstraint ConstraintType = "check"
|
||||
NotNullConstraint ConstraintType = "not_null"
|
||||
)
|
||||
|
||||
type Script struct {
|
||||
Name string `json:"name" yaml:"name" xml:"name"`
|
||||
Description string `json:"description" yaml:"description" xml:"description"`
|
||||
SQL string `json:"sql" yaml:"sql" xml:"sql"`
|
||||
Rollback string `json:"rollback,omitempty" yaml:"rollback,omitempty" xml:"rollback,omitempty"`
|
||||
RunAfter []string `json:"run_after,omitempty" yaml:"run_after,omitempty" xml:"run_after,omitempty"`
|
||||
Schema string `json:"schema,omitempty" yaml:"schema,omitempty" xml:"schema,omitempty"`
|
||||
Version string `json:"version,omitempty" yaml:"version,omitempty" xml:"version,omitempty"`
|
||||
Priority int `json:"priority,omitempty" yaml:"priority,omitempty" xml:"priority,omitempty"`
|
||||
}
|
||||
24
pkg/readers/reader.go
Normal file
24
pkg/readers/reader.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package readers
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
)
|
||||
|
||||
// Reader defines the interface for reading database specifications
|
||||
// from various input formats
|
||||
type Reader interface {
|
||||
// Read reads and parses the input, returning a Database model
|
||||
Read() (*models.Database, error)
|
||||
}
|
||||
|
||||
// ReaderOptions contains common options for readers
|
||||
type ReaderOptions struct {
|
||||
// FilePath is the path to the input file (if applicable)
|
||||
FilePath string
|
||||
|
||||
// ConnectionString is the database connection string (for DB readers)
|
||||
ConnectionString string
|
||||
|
||||
// Additional options can be added here as needed
|
||||
Metadata map[string]interface{}
|
||||
}
|
||||
32
pkg/transform/transform.go
Normal file
32
pkg/transform/transform.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package transform
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
)
|
||||
|
||||
// Transformer provides utilities for transforming database models
|
||||
type Transformer struct{}
|
||||
|
||||
// NewTransformer creates a new Transformer instance
|
||||
func NewTransformer() *Transformer {
|
||||
return &Transformer{}
|
||||
}
|
||||
|
||||
// Validate validates a database model for correctness
|
||||
func (t *Transformer) Validate(db *models.Database) error {
|
||||
// TODO: Implement validation logic
|
||||
// - Check for duplicate table names
|
||||
// - Validate column types
|
||||
// - Ensure foreign keys reference existing tables/columns
|
||||
// - Validate relation integrity
|
||||
return nil
|
||||
}
|
||||
|
||||
// Normalize normalizes a database model to a standard format
|
||||
func (t *Transformer) Normalize(db *models.Database) (*models.Database, error) {
|
||||
// TODO: Implement normalization logic
|
||||
// - Standardize naming conventions
|
||||
// - Order tables/columns consistently
|
||||
// - Apply default values
|
||||
return db, nil
|
||||
}
|
||||
24
pkg/writers/writer.go
Normal file
24
pkg/writers/writer.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package writers
|
||||
|
||||
import (
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
)
|
||||
|
||||
// Writer defines the interface for writing database specifications
|
||||
// to various output formats
|
||||
type Writer interface {
|
||||
// Write takes a Database model and writes it to the desired format
|
||||
Write(db *models.Database) error
|
||||
}
|
||||
|
||||
// WriterOptions contains common options for writers
|
||||
type WriterOptions struct {
|
||||
// OutputPath is the path where the output should be written
|
||||
OutputPath string
|
||||
|
||||
// PackageName is the Go package name (for code generation)
|
||||
PackageName string
|
||||
|
||||
// Additional options can be added here as needed
|
||||
Metadata map[string]interface{}
|
||||
}
|
||||
Reference in New Issue
Block a user