Codegen not depends on sea-schema & sqlx
This commit is contained in:
parent
6224bb6d5f
commit
0b10d30c64
@ -5,7 +5,6 @@ members = [
|
||||
"sea-orm-codegen",
|
||||
"sea-orm-cli",
|
||||
"examples/sqlx-mysql",
|
||||
"examples/codegen",
|
||||
"examples/cli",
|
||||
]
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
DATABASE_URI=mysql://sea:sea@localhost/bakery
|
||||
DATABASE_URL=mysql://sea:sea@localhost/bakery
|
||||
DATABASE_SCHEMA=bakery
|
@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "sea-orm-codegen-example"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
async-std = { version = "^1.9", features = ["attributes"] }
|
||||
sea-orm = { path = "../../" }
|
||||
sea-orm-codegen = { path = "../../sea-orm-codegen" }
|
||||
sea-query = { version = "~0.12.8" }
|
||||
strum = { version = "^0.20", features = ["derive"] }
|
||||
serde_json = { version = "^1" }
|
||||
quote = { version = "^1" }
|
@ -1,12 +0,0 @@
|
||||
# SeaORM Entity Generator Example
|
||||
|
||||
Prepare:
|
||||
|
||||
Setup a test database and configure the connection string in `main.rs`.
|
||||
Run `bakery.sql` to setup the test table and data.
|
||||
|
||||
Running:
|
||||
|
||||
```sh
|
||||
cargo run
|
||||
```
|
@ -1,75 +0,0 @@
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"cake"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Name,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Fruit,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Name => ColumnType::String(Some(255u32)).def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Fruit => Entity::has_many(super::fruit::Entity).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::fruit::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Fruit.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::filling::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
super::cake_filling::Relation::Filling.def()
|
||||
}
|
||||
fn via() -> Option<RelationDef> {
|
||||
Some(super::cake_filling::Relation::Cake.def().rev())
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
@ -1,81 +0,0 @@
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"cake_filling"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub cake_id: i32,
|
||||
pub filling_id: i32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
CakeId,
|
||||
FillingId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
CakeId,
|
||||
FillingId,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Cake,
|
||||
Filling,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::CakeId => ColumnType::Integer.def(),
|
||||
Self::FillingId => ColumnType::Integer.def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Cake => Entity::belongs_to(super::cake::Entity)
|
||||
.from(Column::CakeId)
|
||||
.to(super::cake::Column::Id)
|
||||
.into(),
|
||||
Self::Filling => Entity::belongs_to(super::filling::Entity)
|
||||
.from(Column::FillingId)
|
||||
.to(super::filling::Column::Id)
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::cake::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Cake.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::filling::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Filling.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
@ -1,67 +0,0 @@
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"filling"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Name,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Name => ColumnType::String(Some(255u32)).def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
_ => panic!("No RelationDef"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::cake::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
super::cake_filling::Relation::Cake.def()
|
||||
}
|
||||
fn via() -> Option<RelationDef> {
|
||||
Some(super::cake_filling::Relation::Filling.def().rev())
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
@ -1,80 +0,0 @@
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"fruit"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub cake_id: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Name,
|
||||
CakeId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Cake,
|
||||
Vendor,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Name => ColumnType::String(Some(255u32)).def(),
|
||||
Self::CakeId => ColumnType::Integer.def().null(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Cake => Entity::belongs_to(super::cake::Entity)
|
||||
.from(Column::CakeId)
|
||||
.to(super::cake::Column::Id)
|
||||
.into(),
|
||||
Self::Vendor => Entity::has_many(super::vendor::Entity).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::cake::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Cake.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::vendor::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Vendor.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
@ -1,7 +0,0 @@
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
||||
|
||||
pub mod cake;
|
||||
pub mod cake_filling;
|
||||
pub mod filling;
|
||||
pub mod fruit;
|
||||
pub mod vendor;
|
@ -1,7 +0,0 @@
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
||||
|
||||
pub use super::cake::Entity as Cake;
|
||||
pub use super::cake_filling::Entity as CakeFilling;
|
||||
pub use super::filling::Entity as Filling;
|
||||
pub use super::fruit::Entity as Fruit;
|
||||
pub use super::vendor::Entity as Vendor;
|
@ -1,72 +0,0 @@
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"vendor"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub fruit_id: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Name,
|
||||
FruitId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Fruit,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Name => ColumnType::String(Some(255u32)).def(),
|
||||
Self::FruitId => ColumnType::Integer.def().null(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Fruit => Entity::belongs_to(super::fruit::Entity)
|
||||
.from(Column::FruitId)
|
||||
.to(super::fruit::Column::Id)
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::fruit::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Fruit.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
@ -1,16 +0,0 @@
|
||||
mod entity;
|
||||
|
||||
use sea_orm_codegen::{EntityGenerator, Error};
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() -> Result<(), Error> {
|
||||
let uri = "mysql://sea:sea@localhost/bakery";
|
||||
let schema = "bakery";
|
||||
|
||||
let _generator = EntityGenerator::discover(uri, schema)
|
||||
.await?
|
||||
.transform()?
|
||||
.generate("src/entity")?;
|
||||
|
||||
Ok(())
|
||||
}
|
@ -20,3 +20,36 @@ clap = { version = "^2.33.3" }
|
||||
dotenv = { version = "^0.15" }
|
||||
async-std = { version = "^1.9", features = [ "attributes" ] }
|
||||
sea-orm-codegen = { path = "../sea-orm-codegen" }
|
||||
sea-schema = { version = "^0.2", default-features = false, features = [
|
||||
"sqlx-mysql",
|
||||
"discovery",
|
||||
"writer",
|
||||
] }
|
||||
sqlx = { version = "^0.5", default-features = false, features = [ "mysql" ] }
|
||||
|
||||
[features]
|
||||
default = [ "runtime-async-std-native-tls" ]
|
||||
runtime-actix-native-tls = [
|
||||
"sqlx/runtime-actix-native-tls",
|
||||
"sea-schema/runtime-actix-native-tls",
|
||||
]
|
||||
runtime-async-std-native-tls = [
|
||||
"sqlx/runtime-async-std-native-tls",
|
||||
"sea-schema/runtime-async-std-native-tls",
|
||||
]
|
||||
runtime-tokio-native-tls = [
|
||||
"sqlx/runtime-tokio-native-tls",
|
||||
"sea-schema/runtime-tokio-native-tls",
|
||||
]
|
||||
runtime-actix-rustls = [
|
||||
"sqlx/runtime-actix-rustls",
|
||||
"sea-schema/runtime-actix-rustls",
|
||||
]
|
||||
runtime-async-std-rustls = [
|
||||
"sqlx/runtime-async-std-rustls",
|
||||
"sea-schema/runtime-async-std-rustls",
|
||||
]
|
||||
runtime-tokio-rustls = [
|
||||
"sqlx/runtime-tokio-rustls",
|
||||
"sea-schema/runtime-tokio-rustls",
|
||||
]
|
||||
|
@ -9,5 +9,5 @@ cargo run -- -h
|
||||
Running Entity Generator:
|
||||
|
||||
```sh
|
||||
cargo run -- entity generate -u mysql://sea:sea@localhost/bakery -s bakery -o out
|
||||
cargo run -- entity generate -url mysql://sea:sea@localhost/bakery -schema bakery -o out
|
||||
```
|
||||
|
@ -8,18 +8,18 @@ pub fn build_cli() -> App<'static, 'static> {
|
||||
SubCommand::with_name("entity")
|
||||
.about("Generate entity")
|
||||
.arg(
|
||||
Arg::with_name("DATABASE_URI")
|
||||
.long("uri")
|
||||
.short("u")
|
||||
.help("Database URI")
|
||||
Arg::with_name("DATABASE_URL")
|
||||
.long("database-url")
|
||||
.short("url")
|
||||
.help("Database URL")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.env("DATABASE_URI"),
|
||||
.env("DATABASE_URL"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("DATABASE_SCHEMA")
|
||||
.long("schema")
|
||||
.short("s")
|
||||
.long("database-schema")
|
||||
.short("schema")
|
||||
.help("Database schema")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
|
@ -1,7 +1,9 @@
|
||||
use clap::ArgMatches;
|
||||
use dotenv::dotenv;
|
||||
use sea_orm_codegen::EntityGenerator;
|
||||
use std::{error::Error, fmt::Display};
|
||||
use sea_orm_codegen::{EntityTransformer, OutputFile};
|
||||
use sea_schema::mysql::discovery::SchemaDiscovery;
|
||||
use sqlx::MySqlPool;
|
||||
use std::{error::Error, fmt::Display, fs, io::Write, path::Path, process::Command};
|
||||
|
||||
mod cli;
|
||||
|
||||
@ -22,13 +24,35 @@ async fn main() {
|
||||
async fn run_generate_command(matches: &ArgMatches<'_>) -> Result<(), Box<dyn Error>> {
|
||||
match matches.subcommand() {
|
||||
("entity", Some(args)) => {
|
||||
let uri = args.value_of("DATABASE_URI").unwrap();
|
||||
let url = args.value_of("DATABASE_URL").unwrap();
|
||||
let schema = args.value_of("DATABASE_SCHEMA").unwrap();
|
||||
let output_dir = args.value_of("OUTPUT_DIR").unwrap();
|
||||
EntityGenerator::discover(uri, schema)
|
||||
.await?
|
||||
.transform()?
|
||||
.generate(output_dir)?;
|
||||
|
||||
let connection = MySqlPool::connect(url).await?;
|
||||
let schema_discovery = SchemaDiscovery::new(connection, schema);
|
||||
let schema = schema_discovery.discover().await;
|
||||
let table_stmts = schema
|
||||
.tables
|
||||
.into_iter()
|
||||
.map(|schema| schema.write())
|
||||
.collect();
|
||||
|
||||
let output = EntityTransformer::transform(table_stmts)?.generate();
|
||||
|
||||
let dir = Path::new(output_dir);
|
||||
fs::create_dir_all(dir)?;
|
||||
|
||||
for OutputFile { name, content } in output.files.iter() {
|
||||
let file_path = dir.join(name);
|
||||
let mut file = fs::File::create(file_path)?;
|
||||
file.write_all(content.as_bytes())?;
|
||||
}
|
||||
for OutputFile { name, .. } in output.files.iter() {
|
||||
Command::new("rustfmt")
|
||||
.arg(dir.join(name))
|
||||
.spawn()?
|
||||
.wait()?;
|
||||
}
|
||||
}
|
||||
_ => unreachable!("You should never see this message"),
|
||||
};
|
||||
|
@ -16,13 +16,7 @@ name = "sea_orm_codegen"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
sea-schema = { version = "^0.2", default-features = false, features = [
|
||||
"sqlx-mysql",
|
||||
"discovery",
|
||||
"writer",
|
||||
] }
|
||||
sea-query = { version = "~0.12.8" }
|
||||
sqlx = { version = "^0.5", default-features = false, features = ["mysql"] }
|
||||
syn = { version = "^1", default-features = false, features = [
|
||||
"derive",
|
||||
"parsing",
|
||||
@ -36,29 +30,3 @@ proc-macro2 = "^1"
|
||||
[dev-dependencies]
|
||||
async-std = { version = "^1.9", features = ["attributes"] }
|
||||
sea-orm = { path = "../" }
|
||||
|
||||
[features]
|
||||
runtime-actix-native-tls = [
|
||||
"sqlx/runtime-actix-native-tls",
|
||||
"sea-schema/runtime-actix-native-tls",
|
||||
]
|
||||
runtime-async-std-native-tls = [
|
||||
"sqlx/runtime-async-std-native-tls",
|
||||
"sea-schema/runtime-async-std-native-tls",
|
||||
]
|
||||
runtime-tokio-native-tls = [
|
||||
"sqlx/runtime-tokio-native-tls",
|
||||
"sea-schema/runtime-tokio-native-tls",
|
||||
]
|
||||
runtime-actix-rustls = [
|
||||
"sqlx/runtime-actix-rustls",
|
||||
"sea-schema/runtime-actix-rustls",
|
||||
]
|
||||
runtime-async-std-rustls = [
|
||||
"sqlx/runtime-async-std-rustls",
|
||||
"sea-schema/runtime-async-std-rustls",
|
||||
]
|
||||
runtime-tokio-rustls = [
|
||||
"sqlx/runtime-tokio-rustls",
|
||||
"sea-schema/runtime-tokio-rustls",
|
||||
]
|
||||
|
@ -1,15 +0,0 @@
|
||||
use crate::{EntityTransformer, Error};
|
||||
use sea_schema::mysql::discovery::SchemaDiscovery;
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EntityGenerator {}
|
||||
|
||||
impl EntityGenerator {
|
||||
pub async fn discover(uri: &str, schema: &str) -> Result<EntityTransformer, Error> {
|
||||
let connection = MySqlPool::connect(uri).await?;
|
||||
let schema_discovery = SchemaDiscovery::new(connection, schema);
|
||||
let schema = schema_discovery.discover().await;
|
||||
Ok(EntityTransformer { schema })
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
mod base_entity;
|
||||
mod column;
|
||||
mod conjunct_relation;
|
||||
mod generator;
|
||||
mod primary_key;
|
||||
mod relation;
|
||||
mod transformer;
|
||||
@ -10,7 +9,6 @@ mod writer;
|
||||
pub use base_entity::*;
|
||||
pub use column::*;
|
||||
pub use conjunct_relation::*;
|
||||
pub use generator::*;
|
||||
pub use primary_key::*;
|
||||
pub use relation::*;
|
||||
pub use transformer::*;
|
||||
|
@ -2,21 +2,17 @@ use crate::{
|
||||
Column, ConjunctRelation, Entity, EntityWriter, Error, PrimaryKey, Relation, RelationType,
|
||||
};
|
||||
use sea_query::TableStatement;
|
||||
use sea_schema::mysql::def::Schema;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EntityTransformer {
|
||||
pub(crate) schema: Schema,
|
||||
}
|
||||
pub struct EntityTransformer;
|
||||
|
||||
impl EntityTransformer {
|
||||
pub fn transform(self) -> Result<EntityWriter, Error> {
|
||||
pub fn transform(table_stmts: Vec<TableStatement>) -> Result<EntityWriter, Error> {
|
||||
let mut inverse_relations: HashMap<String, Vec<Relation>> = HashMap::new();
|
||||
let mut conjunct_relations: HashMap<String, Vec<ConjunctRelation>> = HashMap::new();
|
||||
let mut entities = HashMap::new();
|
||||
for table_ref in self.schema.tables.iter() {
|
||||
let table_stmt = table_ref.write();
|
||||
for table_stmt in table_stmts.into_iter() {
|
||||
let table_create = match table_stmt {
|
||||
TableStatement::Create(stmt) => stmt,
|
||||
_ => {
|
||||
|
@ -1,105 +1,93 @@
|
||||
use crate::{Entity, Error};
|
||||
use crate::Entity;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use std::{
|
||||
fs::{self, File},
|
||||
io::{self, Write},
|
||||
path::Path,
|
||||
process::Command,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EntityWriter {
|
||||
pub(crate) entities: Vec<Entity>,
|
||||
}
|
||||
|
||||
pub struct WriterOutput {
|
||||
pub files: Vec<OutputFile>,
|
||||
}
|
||||
|
||||
pub struct OutputFile {
|
||||
pub name: String,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
impl EntityWriter {
|
||||
pub fn generate(self, output_dir: &str) -> Result<(), Error> {
|
||||
for entity in self.entities.iter() {
|
||||
let code_blocks = Self::gen_code_blocks(entity);
|
||||
Self::write(output_dir, entity, code_blocks)?;
|
||||
}
|
||||
for entity in self.entities.iter() {
|
||||
Self::format_entity(output_dir, entity)?;
|
||||
}
|
||||
self.write_mod(output_dir)?;
|
||||
self.write_prelude(output_dir)?;
|
||||
Ok(())
|
||||
pub fn generate(self) -> WriterOutput {
|
||||
let mut files = Vec::new();
|
||||
files.extend(self.write_entities());
|
||||
files.push(self.write_mod());
|
||||
files.push(self.write_prelude());
|
||||
WriterOutput { files }
|
||||
}
|
||||
|
||||
pub fn write_mod(&self, output_dir: &str) -> io::Result<()> {
|
||||
let file_name = "mod.rs";
|
||||
let dir = Self::create_dir(output_dir)?;
|
||||
let file_path = dir.join(file_name);
|
||||
let mut file = fs::File::create(file_path)?;
|
||||
Self::write_doc_comment(&mut file)?;
|
||||
for entity in self.entities.iter() {
|
||||
let code_block = Self::gen_mod(entity);
|
||||
file.write_all(code_block.to_string().as_bytes())?;
|
||||
}
|
||||
Self::format_file(output_dir, file_name)?;
|
||||
Ok(())
|
||||
pub fn write_entities(&self) -> Vec<OutputFile> {
|
||||
self.entities
|
||||
.iter()
|
||||
.map(|entity| {
|
||||
let mut lines = Vec::new();
|
||||
Self::write_doc_comment(&mut lines);
|
||||
let code_blocks = Self::gen_code_blocks(entity);
|
||||
Self::write(&mut lines, code_blocks);
|
||||
OutputFile {
|
||||
name: format!("{}.rs", entity.table_name),
|
||||
content: lines.join("\n\n"),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn write_prelude(&self, output_dir: &str) -> io::Result<()> {
|
||||
let file_name = "prelude.rs";
|
||||
let dir = Self::create_dir(output_dir)?;
|
||||
let file_path = dir.join(file_name);
|
||||
let mut file = fs::File::create(file_path)?;
|
||||
Self::write_doc_comment(&mut file)?;
|
||||
for entity in self.entities.iter() {
|
||||
let code_block = Self::gen_prelude_use(entity);
|
||||
file.write_all(code_block.to_string().as_bytes())?;
|
||||
pub fn write_mod(&self) -> OutputFile {
|
||||
let mut lines = Vec::new();
|
||||
Self::write_doc_comment(&mut lines);
|
||||
let code_blocks = self
|
||||
.entities
|
||||
.iter()
|
||||
.map(|entity| Self::gen_mod(entity))
|
||||
.collect();
|
||||
Self::write(&mut lines, code_blocks);
|
||||
OutputFile {
|
||||
name: "mod.rs".to_owned(),
|
||||
content: lines.join("\n"),
|
||||
}
|
||||
Self::format_file(output_dir, file_name)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write(
|
||||
output_dir: &str,
|
||||
entity: &Entity,
|
||||
code_blocks: Vec<TokenStream>,
|
||||
) -> io::Result<()> {
|
||||
let dir = Self::create_dir(output_dir)?;
|
||||
let file_path = dir.join(format!("{}.rs", entity.table_name));
|
||||
let mut file = fs::File::create(file_path)?;
|
||||
Self::write_doc_comment(&mut file)?;
|
||||
for code_block in code_blocks {
|
||||
file.write_all(code_block.to_string().as_bytes())?;
|
||||
file.write_all(b"\n\n")?;
|
||||
pub fn write_prelude(&self) -> OutputFile {
|
||||
let mut lines = Vec::new();
|
||||
Self::write_doc_comment(&mut lines);
|
||||
let code_blocks = self
|
||||
.entities
|
||||
.iter()
|
||||
.map(|entity| Self::gen_prelude_use(entity))
|
||||
.collect();
|
||||
Self::write(&mut lines, code_blocks);
|
||||
OutputFile {
|
||||
name: "prelude.rs".to_owned(),
|
||||
content: lines.join("\n"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_doc_comment(file: &mut File) -> io::Result<()> {
|
||||
pub fn write(lines: &mut Vec<String>, code_blocks: Vec<TokenStream>) {
|
||||
lines.extend(
|
||||
code_blocks
|
||||
.into_iter()
|
||||
.map(|code_block| code_block.to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn write_doc_comment(lines: &mut Vec<String>) {
|
||||
let ver = env!("CARGO_PKG_VERSION");
|
||||
let comments = vec![format!(
|
||||
"//! SeaORM Entity. Generated by sea-orm-codegen {}",
|
||||
ver
|
||||
)];
|
||||
for comment in comments {
|
||||
file.write_all(comment.as_bytes())?;
|
||||
file.write_all(b"\n\n")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_dir(output_dir: &str) -> io::Result<&Path> {
|
||||
let dir = Path::new(output_dir);
|
||||
fs::create_dir_all(dir)?;
|
||||
Ok(dir)
|
||||
}
|
||||
|
||||
pub fn format_entity(output_dir: &str, entity: &Entity) -> io::Result<()> {
|
||||
Self::format_file(output_dir, &format!("{}.rs", entity.table_name))
|
||||
}
|
||||
|
||||
pub fn format_file(output_dir: &str, file_name: &str) -> io::Result<()> {
|
||||
Command::new("rustfmt")
|
||||
.arg(Path::new(output_dir).join(file_name))
|
||||
.spawn()?
|
||||
.wait()?;
|
||||
Ok(())
|
||||
lines.extend(comments);
|
||||
lines.push("".to_owned());
|
||||
}
|
||||
|
||||
pub fn gen_code_blocks(entity: &Entity) -> Vec<TokenStream> {
|
||||
|
@ -3,7 +3,6 @@ use std::{error, fmt, io};
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
StdIoError(io::Error),
|
||||
SqlxError(sqlx::Error),
|
||||
TransformError(String),
|
||||
}
|
||||
|
||||
@ -11,7 +10,6 @@ impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::StdIoError(e) => write!(f, "{:?}", e),
|
||||
Self::SqlxError(e) => write!(f, "{:?}", e),
|
||||
Self::TransformError(e) => write!(f, "{:?}", e),
|
||||
}
|
||||
}
|
||||
@ -21,7 +19,6 @@ impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
Self::StdIoError(e) => Some(e),
|
||||
Self::SqlxError(e) => Some(e),
|
||||
Self::TransformError(_) => None,
|
||||
}
|
||||
}
|
||||
@ -32,9 +29,3 @@ impl From<io::Error> for Error {
|
||||
Self::StdIoError(io_err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<sqlx::Error> for Error {
|
||||
fn from(sqlx_err: sqlx::Error) -> Self {
|
||||
Self::SqlxError(sqlx_err)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user